Read Only Reentrancy

  • An external call from a secure smart contract "A" invokes the fallback() function in the attacker's contract. The attacker executes the code in the fallback() function to run against a target contract "B", which some how indirectly related to contract "A".
  • In the given example, Contract "B" derives the price of the LP token from Contract "A"


Read Only Reentrancy

Code Audit

// VulnContract
// users stake LP_TOKEN
// getReward rewards the users based on the current price of the pool LP token
contract VulnContract {
IERC20 public constant token = IERC20(LP_TOKEN);
ICurve private constant pool = ICurve(STETH_POOL);
mapping(address => uint) public balanceOf;
function stake(uint amount) external {
token.transferFrom(msg.sender, address(this), amount);
balanceOf[msg.sender] += amount;
function unstake(uint amount) external {
balanceOf[msg.sender] -= amount;
token.transfer(msg.sender, amount);
function getReward() external returns (uint) {
//rewarding tokens based on the current virtual price of the pool LP token
uint reward = (balanceOf[msg.sender] * pool.get_virtual_price()) / 1 ether;
// Omitting code to transfer reward tokens
return reward;