The InheritanceManager::nonReentrant
modifier that's intended to protect against reentrancy attacks contains a critical vulnerability due to inconsistent transient storage slot usage. The modifier checks one storage slot but sets a different one:
This implementation checks the value in transient storage slot 1 (tload(1)
), but it sets and resets the flag in transient storage slot 0 (tstore(0, 1)
and tstore(0, 0)
). As a result, the reentrancy check will never detect a reentrant call because it's monitoring a different slot than the one being modified.
This vulnerability completely breaks the reentrancy protection mechanism.
However, since all functions where the nonReentrant
modifier is implemented (InheritanceManager::sendERC20
, InheritanceManager::sendETH
, and InheritanceManager::contractInteractions
) are also protected by the onlyOwner
modifier, this issue is not a problem.
InheritanceManager::sendERC20
and InheritanceManager::sendETH
send tokens from the contract. Since only the owner can do this, reentrancy is not applicable.
InheritanceManager::contractInteractions
calls external contracts (which could be malicious), but the receive
/fallback
call will not go through because msg.sender
will be the address of the malicious contract and not the owner, so it will revert.
It's a low / informational severity
Fix the transient storage slot inconsistency by using the same slot for both checking and setting the reentrancy guard:
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.