5. The Rewarder

https://www.damnvulnerabledefi.xyz/challenges/the-rewarder/

Objective

  • 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?

Approach

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.

Solution

create a new contract for the attack:

Test Exploit()

Last updated