The InheritanceManager
contract contains a critical vulnerability in its nonReentrant
modifier that fails to provide reentrancy protection. The modifier checks transient storage slot 1 for the lock, but sets and resets the lock in slot 0, completely breaking the protection mechanism and allowing malicious contracts to perform reentrant calls that could drain funds from the contract.
The vulnerability exists in the nonReentrant
modifier implementation in InheritanceManager.sol
:
The critical issue is that the modifier:
Checks transient storage slot 1 (tload(1)
) to detect reentrancy
Sets transient storage slot 0 (tstore(0, 1)
) to indicate a function is executing
Resets transient storage slot 0 (tstore(0, 0)
) after execution
Since different storage slots are used for checking and setting the lock, the reentrancy protection fails completely. During a reentrant call, slot 1 remains at its default value of 0, so the check if tload(1) { revert(0, 0) }
will pass, allowing the reentrant call to proceed despite the lock in slot 0 being set to 1.
This vulnerability affects multiple critical functions in the contract:
sendERC20(address _tokenAddress, uint256 _amount, address _to)
sendETH(uint256 _amount, address _to)
contractInteractions(address _target, bytes calldata _payload, uint256 _value, bool _storeTarget)
All of these functions make external calls to potentially malicious contracts while relying on the broken reentrancy protection.
PoC Result:
The impact of this vulnerability is critical:
An attacker can create a malicious contract that, when receiving ETH or tokens from the InheritanceManager
contract, performs reentrant calls back into the contract's vulnerable functions.
Through these reentrant calls, the attacker can:
Drain ETH held by the contract via multiple calls to sendETH()
Drain ERC20 tokens via multiple calls to sendERC20()
Execute arbitrary external calls via contractInteractions()
Even though these functions have the onlyOwner
modifier, the attack occurs when the owner legitimately calls one of these functions with the attacker's contract as the recipient.
A single authorized transaction by the owner could result in multiple unauthorized withdrawals, leading to complete loss of funds.
Foundry
Manual Code Review
To fix this vulnerability, modify the nonReentrant
modifier to use the same transient storage slot for both checking and setting the lock:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.