Based on Solmate ERC20 contract's implementation. The transferFrom
function returns a boolean value, indicating if a transfer proceeded or not, but it's not reverting the transaction which is an issue. Lack of successful transfer check in Staking::deposit
can allow an attacker to steal rewards from staking vault.
I implemented this transferFrom
function that intentionally returns false in LoveToken.sol
, to conduct the test case:
As pointed out in the documentation of the protocol:
For every 1 token deposited and 1 week left in the contract, 1 LoveToken is rewarded.
Examples:
7 tokens deposited for 2 weeks = 14 LoveToken reward
An attacker stakes 7 ether of love token the transfer fails because of the custom transfer function, but the userStakes
mapping is updated, which plays a crutial role for executing the attack.
The tokens are left for 2 weeks in the contract.
The attacker claims his 14 love token reward.
Note on the PoC: Since the mock transferFrom
function is also used in Staking::claimRewards
the transfer will fail, but the accrued reward tokens can be seen in the emitted RewardsClaimed
event, by making the verbosity higher level from the command line.
Add the following in StakingTest.t.sol
file and run forge test --mt testStealFromStakingVault -vvvv
in the command line:
Logs from the event:
Medium: It may happen under specific condition, but the severity will be critical for the protocol.
Manual Review, Foundry
Use OpenZeppelin's SafeERC20
library for safe transfers or check the returned bool values of all transfer
and transferFrom
functions in the protocol with require
or if
statement.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.