Read Only Reentrancy
Jump to navigation
Jump to search
Read-only reentrancy is a novel attack vector in which instead of reentering into the same smart contract in which state changes have yet to be made, an attacker reenters into another contract which reads from the state of the original contract.
// UNSECURE
contract A {
// Has a reentrancy guard to prevent reentrancy
// but makes state change only after external call to sender
function withdraw() external nonReentrant {
uint256 amount = balances[msg.sender];
(bool success,) = msg.sender.call{value: balances[msg.sender]}("");
require(success);
balances[msg.sender] = 0;
}
}
contract B {
// Allows sender to claim equivalent B tokens for A tokens they hold
function claim() external nonReentrant {
require(!claimed[msg.sender]);
balances[msg.sender] = A.balances[msg.sender];
claimed[msg.sender] = true;
}
}
As we can see in the above example, although both functions have a nonReentrant modifier, it is still possible for an attacker to call B.claim
during the callback in A.withdraw
, and since the attackers balance was not yet updated, execution succeeds.