Read Only Reentrancy

From WEB3 Vulnerapedia
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.

Sources

https://github.com/kadenzipfel/smart-contract-vulnerabilities/blob/master/vulnerabilities/reentrancy.md

https://medium.com/coinmonks/protect-your-solidity-smart-contracts-from-reentrancy-attacks-9972c3af7c21