5. The Rewarder
https://www.damnvulnerabledefi.xyz/challenges/the-rewarder/
Last updated
https://www.damnvulnerabledefi.xyz/challenges/the-rewarder/
Last updated
There’s a pool offering rewards in tokens every 5 days for those who deposit their DVT tokens into it.
Alice, Bob, Charlie and David have already deposited some DVT tokens, and have won their rewards!
You don’t have any DVT tokens. But in the upcoming round, you must claim most rewards for yourself.
By the way, rumours say a new pool has just launched. Isn’t it offering flash loans of DVT tokens?
Let us examine the deposit() on Rewards Pool contract.
mints accounting tokens in a 1:1 ratio against the DVT tokens deposited
calls distributeRewards()
distributeRewards()
checks if its time for a new round of rewards distribution: isNewRewardsRound()
rewards are distributed in 5 day intervals from the lastRecordedSnapshotTimestamp
if it is indeed time for a new rewards round, _recordSnapshot() is executed
increments lastSnapshotIdForRewards
updates the timestamp on lastRecordedSnapshotTimestamp
increments roundNumber
checks current totalDeposits and amountDeposited by the uer
if both are non-zero positive values, calculate rewards earned by user
rewards awarded are based on the percentage of contribution
if rewards > 0, mint reward tokens to the user, and record the timestamp into the mapping lastRewardTimestamps
Attack vector
take a flash loan from the flashpool,
deposit into rewards pool during an eligible rewards round
return flash loan
The weakness is that the rewarderPool does not check for how long a deposit has been held within it, to allocate rewards. It simply calculates rewards as a function of size, disregarding time.
create a new contract for the attack: