31263 - [SC - Critical] RevenueHandlercheckpoint counts unclaimed rewar...

Submitted on May 15th 2024 at 22:47:08 UTC by @yttriumzz for Boost | Alchemix

Report ID: #31263

Report type: Smart Contract

Report severity: Critical

Target: https://github.com/alchemix-finance/alchemix-v2-dao/blob/main/src/RevenueHandler.sol

Impacts:

  • Theft of unclaimed yield

Description

Brief/Intro

Anyone calls RevenueHandler.checkpoint to update the reward for the current epoch. checkpoint will calculate the reward based on the reward token balance of the contract. However, these balances include unclaimed rewards. In other words, the unclaimed rewards of some users are included in the rewards of the new epoch.

Vulnerability Details

Please look at the following code. When tokenConfig.poolAdapter is not set, thisBalance is directly used as the reward for the new epoch.

///// https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/RevenueHandler.sol#L245-L264
                uint256 thisBalance = IERC20(token).balanceOf(address(this));

                // If poolAdapter is set, the revenue token is an alchemic-token
                if (tokenConfig.poolAdapter != address(0)) {
                    // Treasury only receives revenue if the token is an alchemic-token
                    treasuryAmt = (thisBalance * treasuryPct) / BPS;
                    IERC20(token).safeTransfer(treasury, treasuryAmt);

                    // Only melt if there is an alchemic-token to melt to
                    amountReceived = _melt(token);

                    // Update amount of alchemic-token revenue received for this epoch
                    epochRevenues[currentEpoch][tokenConfig.debtToken] += amountReceived;
                } else {
                    // If the revenue token doesn't have a poolAdapter, it is not an alchemic-token
                    amountReceived = thisBalance;

                    // Update amount of non-alchemic-token revenue received for this epoch
                    epochRevenues[currentEpoch][token] += amountReceived;
                }

Suggested fix

Record the balance as a reward instead of using all the balance directly

Impact Details

Users who claim rewards every epoch will receive more rewards, and other users will receive less rewards

References

None

Proof of concept

The PoC patch

Run the PoC

The log

Last updated

Was this helpful?