InheritanceManager.sol implements reentrancy locks/guards with the help of transient storage. However, due to a slot mismatch, reentrancy is still possible.
The nonReentrant modifier in InheritanceManager.sol implements reentrancy locks/guards with the help of transient storage.
[1] reads the value from transient storage at slot 1. If the value is non-zero (locked), the transaction reverts ([2]). Note how steps [3] and [4] use tstore(0, 1) and tstore(0, 0) respectively. This slot incosistency renders nonReentrant ineffective against reentrancy.
The following code demonstrates the ability of owner to call InheritanceManager::sendETH until the InheritanceManager contract has no funds.
We fund InheritanceManager with 10 ETH
owner calls sendETH(1e18, address(InheritanceManagerTest))
sendETH triggers receive
receive keeps calling sendETH until InheritanceManager contract is drained
The balance of InheritanceManagerTest should be 10 ETH
Place test_nonReentrantReentrancy in InheritanceManagerTest.t.sol,
and add a receive function in the InheritanceManagerTest contract:
Finally, run the test:
Functions that are nonReentrant-protected are also guarded by the onlyOwner modifier which requires for msg.sender to be the owner. Taking sendETH(uint256 _amount, address _to) as an example, even if _to is malicious, they wouldn't be able to reenter thanks to onlyOwner. However, the logic flaw in nonReentrant should be fixed to prevent potential issues in the future.
Manual review
Foundry
Ensure slot consistency:
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.