Read-Only Reentrancy Explained in Detail
Read-only reentrancy abuses a stale read, not a direct state write. The attacker triggers a state transition, enters a callback window, then calls a view function while accounting is only partly updated.
Another protocol, oracle integration, lending market, or vault may treat that stale value as valid.
Smart contract example
function removeLiquidity(uint256 shares) external {
uint256 assetsOut = trackedAssets * shares / totalShares;
totalShares -= shares;
token.transfer(msg.sender, assetsOut); // callback window
trackedAssets -= assetsOut;
}
function sharePrice() external view returns (uint256) {
return trackedAssets * 1e18 / totalShares;
}
During the callback, totalShares is reduced but trackedAssets is not. A contract reading sharePrice() can see an inflated price.
Read-Only Reentrancy in Auditing
View functions often become oracle inputs. A stale view can move collateral values, LP token prices, vault exchange rates, rewards, or liquidation decisions.
The source protocol and the consuming protocol both need review.
Red flags in code
-
Views returning
price,exchangeRate,getVirtualPrice,totalAssets, orpricePerShare. -
External calls during withdraw, redeem, burn, swap, claim, or liquidity removal.
-
Integrations trusting same-block view values as oracle inputs.
-
Accounting split across multiple variables updated before and after a callback.
-
View functions that do not account for active transitions or locks.
-
Reentrancy guards used only on state-changing functions.
How to test or review it
-
Call oracle-like views from a receiver callback.
-
Compare view outputs before, during, and after the state transition.
-
Test consuming protocols that read the value in the same transaction.
-
Check whether views should revert during active state changes.
-
Prefer delayed, cached, or independently verified oracle values for protocol-critical pricing.
-
Add invariant tests for share price, total assets, reserves, and collateral values.