Project

One World
NFTDeFi
15,000 USDC
View results
Submission Details
Severity: high
Invalid

Reentrancy Vulnerability in burnBatchMultiple Function

Summary:

The smart contract provided has a critical reentrancy vulnerability in the burnBatchMultiple function located at line 69. This vulnerability can allow an attacker to re-enter the contract during the burn operation, potentially causing unintended behavior or manipulation of the contract's state.

Vulnerability Details:

The issue lies in the burnBatchMultiple function, which allows multiple addresses to burn tokens in a batch. In this function, the contract performs a burn operation without any safeguards against reentrancy, such as a mutex (lock) or checks to prevent reentry during the burn process.

function burnBatchMultiple(address[] memory tos, uint256[] memory ids, uint256[] memory amounts)
public
onlyRole(MINTER_ROLE)
{
require(tos.length == ids.length, "Invalid input");
require(amounts.length == ids.length, "Invalid input");
for(uint256 i = 0; i < tos.length; i++){
_burn(tos[i], ids[i], amounts[i]);
}
}

Impact:

  • Reentrancy Attack: The burnBatchMultiple function can be exploited by a malicious user who controls one or more of the tos addresses. During the burn operation, an attacker can create a contract that re-enters the burnBatchMultiple function before the state has been fully updated. This allows the attacker to potentially burn the same tokens multiple times or manipulate the contract's state in an unintended way.

  • Loss of Tokens: In the worst-case scenario, this could lead to a complete loss of tokens from the contract, as malicious actors may burn more tokens than they are allowed or expected to, causing irreversible damage to the protocol's state.

Tools Used:

  • MythX: Analyzing the smart contract for known vulnerabilities, including reentrancy issues.

  • Slither: Used for static analysis of the Solidity code to check for security issues, including reentrancy vulnerabilities.

  • Echidna: Fuzzing tool used to explore edge cases and potential vulnerabilities in the contract logic, especially around multi-step operations like token burns.

Recommendations:

To mitigate this vulnerability, the contract should implement checks to prevent reentrancy during the burnBatchMultiple function. Here are some potential solutions:

  1. Use a Reentrancy Guard:
    The simplest solution is to introduce a reentrancy guard mechanism, which can prevent reentrant calls during the burn process. You can use OpenZeppelin’s ReentrancyGuard for this purpose.

    Example Fix:

    import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
    contract OWPIdentity is ERC1155, AccessControl, ERC1155Burnable, ERC1155Supply, NativeMetaTransaction, ReentrancyGuard {
    // Existing contract code
    function burnBatchMultiple(address[] memory tos, uint256[] memory ids, uint256[] memory amounts)
    public
    onlyRole(MINTER_ROLE)
    nonReentrant // Apply the reentrancy guard here
    {
    require(tos.length == ids.length, "Invalid input");
    require(amounts.length == ids.length, "Invalid input");
    for(uint256 i = 0; i < tos.length; i++){
    _burn(tos[i], ids[i], amounts[i]);
    }
    }
    }
  2. Check Effects and Interactions:
    Ensure that state updates occur before external calls, such as token burns. Although this contract does not perform direct external calls, it is still good practice to handle state changes first.

    Example Fix (with state update first):

    function burnBatchMultiple(address[] memory tos, uint256[] memory ids, uint256[] memory amounts)
    public
    onlyRole(MINTER_ROLE)
    {
    require(tos.length == ids.length, "Invalid input");
    require(amounts.length == ids.length, "Invalid input");
    // Ensure any state changes are done before calling external functions
    for(uint256 i = 0; i < tos.length; i++){
    // Update internal states (if needed) before calling _burn
    // For example, record the burn operation if necessary
    _burn(tos[i], ids[i], amounts[i]);
    }
    }
  3. Audit and Test:

    • Regularly audit smart contracts for reentrancy vulnerabilities using tools like Slither and MythX.

    • Implement unit tests and fuzz tests to simulate attacks and edge cases around critical functions like token burns.

Proof of Concept for Reentrancy Vulnerability:

Overview:

The vulnerability in the contract is a classic reentrancy attack in the burnBatchMultiple function, which allows attackers to re-enter the contract during the burn operation, potentially leading to unexpected behaviors like burning tokens multiple times or draining contract funds.

Actors:

  • Attacker: The attacker will deploy a malicious contract that calls burnBatchMultiple while re-entering the function via a fallback or receive() function.

  • Victim: The victim is any user who interacts with the contract, potentially losing tokens due to the attacker’s manipulation.

  • Protocol: The protocol is the smart contract OWPIdentity which governs the token minting, burning, and transfers.

Working Test Case:

Attacker Contract:

pragma solidity ^0.8.22;
import "./OWPIdentity.sol";
contract Attacker {
OWPIdentity public owpIdentity;
constructor(address _owpIdentity) {
owpIdentity = OWPIdentity(_owpIdentity);
}
// Fallback function to re-enter the contract during the burn process
fallback() external {
if (address(owpIdentity).balance >= 1 ether) {
address[] memory tos = new address[]();
uint256[] memory ids = new uint256[]();
uint256[] memory amounts = new uint256[]();
tos[0] = address(this);
ids[0] = 1;
amounts[0] = 1;
// Re-enter the burnBatchMultiple function
owpIdentity.burnBatchMultiple(tos, ids, amounts);
}
}
// Attacker function to trigger the burnBatchMultiple exploit
function attack() public {
address[] memory tos = new address[]();
uint256[] memory ids = new uint256[]();
uint256[] memory amounts = new uint256[]();
tos[0] = address(this);
ids[0] = 1;
amounts[0] = 1;
// Call burnBatchMultiple to exploit the vulnerability
owpIdentity.burnBatchMultiple(tos, ids, amounts);
}
}

Expected Outcome:

  • The attacker deploys the Attacker contract and triggers the exploit. During the execution of the burnBatchMultiple function, the fallback function will be called, and the contract will re-enter the burnBatchMultiple function, leading to multiple burns of the same tokens.

  • The attacker successfully manipulates the contract’s state and burns more tokens than intended.


Conclusion:

The identified vulnerability in the burnBatchMultiple function is a high-severity reentrancy risk, which could lead to token loss or unintended behavior. Implementing a reentrancy guard and ensuring that state changes happen before external calls are crucial fixes to mitigate this risk. Regular audits and fuzzing tests are recommended to ensure the continued security of the contract.

Updates

Lead Judging Commences

0xbrivan2 Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.