The nonReentrant
modifier in the InheritanceManager contract contains a critical vulnerability where the reentrancy lock checks one transient storage slot but modifies a different one. This mismatch renders the reentrancy protection completely ineffective, allowing malicious contracts to perform reentrancy attacks on functions that should be protected.
The vulnerable modifier is implemented as follows:
The issue is that the modifier:
Checks if slot 1 is non-zero with tload(1)
But sets slot 0 to 1 with tstore(0, 1)
before executing the function
And resets slot 0 to 0 with tstore(0, 0)
after execution
This mismatch between checking slot 1 but modifying slot 0 means the lock is never actually enforced. Since slot 1 is never modified by the contract, the if tload(1)
condition will always evaluate to false, allowing multiple reentrant calls to pass through.
This is particularly concerning because the comment explicitly states that this is a "gas efficient cross-function reentrancy lock using transient storage," implying it should be secure against reentrancy attacks.
The impact of this vulnerability is critical:
Complete Reentrancy Protection Failure: Any function using this modifier is vulnerable to reentrancy attacks despite the intended protection.
Critical Functions Exposed: Several sensitive functions use this modifier:
sendERC20
: Could be exploited to drain ERC20 tokens
sendETH
: Could be exploited to drain ETH
contractInteractions
: Could be exploited to perform multiple malicious contract calls
False Sense of Security: The presence of the modifier suggests protection that doesn't exist, which could lead to less scrutiny during code review.
Complex Attack Vectors: Since contractInteractions
allows arbitrary contract interactions with ETH transfer, an attacker could craft a malicious contract that reenters the InheritanceManager contract via this function.
Manual code review.
Fix the slot mismatch by using consistent transient storage slots:
Alternatively, implement the nonReentrant modifier using standard Solidity without assembly for improved readability and maintainability:
If transient storage is preferred for gas optimization, consider using a more explicit implementation:
Add comprehensive tests specifically targeting reentrancy protection to ensure the fixed implementation works as expected.
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.