20,000 USDC
View results
Submission Details
Severity: high

Users can steal all `weth` from staking contract

Summary

claim() function in staking.sol updates claimable[msg.sender] to 0 after transferring tokens to caller. Reentrancy is possible if the WETH is crafted to change the control flow such as erc777 which are backward compatible to erc20.

Vulnerability Details

claim() function handovers control to msg.sender before updating claimable. msg.sender can reenter claim function until weth becomes 0.

function claim() external {
updateFor(msg.sender);
WETH.transfer(msg.sender, claimable[msg.sender]); //@audit possible reentrancy to claim infinitely
claimable[msg.sender] = 0;
balance = WETH.balanceOf(address(this));
}

Attack follows the following flow:

  1. Staking contract has 10000 weth

  2. Attacker calls deposits(10). (totalSupply set to 10)

  3. This updates balance from 0 to 10000 and index 0 to 1000

  4. 1000 weth is deposited in 1 day.

  5. Attacker calls claim(). The claimable[attacker] is calculated as 1000. (assuming totalSupply remains 10)

  6. Attacker receives tokens and reenter contract until weth.balanceOf(staking) > 0.

  7. As claimable[attacker] still gives 1000 or more. He can steal all weth in contract.

  8. claimable[attacker] set to 0

  9. balance is updated to 0

Deposit
WETH: : 10000.000000000000000000
User1 balance: : 10.000000000000000000
User1 claimable: : 0.000000000000000000
User1 WETH: : 0.000000000000000000
Claim
WETH: : 0.000000000000000000
User1 balance: : 10.000000000000000000
User1 claimable: : 0.000000000000000000
User1 WETH: : 11000.000000000000000000

Impact

weth funds are stolen.

Tools Used

Foundry, Manual review

Recommendations

Update claimable[msg.sender] = 0 before transferring tokens.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.