sherlock-audit / 2023-04-blueberry-judging

8 stars 5 forks source link

J4de - `WCurveGauge.sol#burn` function should use LP Token's decimals instead of `1e18` #71

Closed sherlock-admin closed 1 year ago

sherlock-admin commented 1 year ago

J4de

medium

WCurveGauge.sol#burn function should use LP Token's decimals instead of 1e18

Summary

WCurveGauge.sol#_mintCrv should use LP Token's decimals instead of 1e18

Vulnerability Detail

File: wrapper/WCurveGauge.sol
142     function burn(
143         uint256 id,
144         uint256 amount
145     ) external nonReentrant returns (uint256 rewards) {
146         if (amount == type(uint256).max) {
147             amount = balanceOf(msg.sender, id);
148         }
149         (uint256 gid, uint256 stCrvPerShare) = decodeId(id);
150         _burn(msg.sender, id, amount);
151         ILiquidityGauge gauge = ILiquidityGauge(gaugeController.gauges(gid));
152         require(address(gauge) != address(0), "gauge not registered");
153         _mintCrv(gauge, gid);
154         gauge.withdraw(amount);
155         IERC20Upgradeable(gauge.lp_token()).safeTransfer(msg.sender, amount);
156  >>     uint256 stCrv = (stCrvPerShare * amount) / 1e18;
157  >>     uint256 enCrv = (accCrvPerShares[gid] * amount) / 1e18;
158         if (enCrv > stCrv) {
159             rewards = enCrv - stCrv;
160             CRV.safeTransfer(msg.sender, rewards);
161         }
162         return rewards;
163     }

The burn function is used to extract the token of the user despoit, and transfer the reward CRV to the user. Lines 156 and 157 are CrvPerShare of user mint and now. The problem here is that gauge.lp_token().decimals() should be used instead of 1e18.

Assuming that the decimals of LP Token is 8, the rewards received by users will be reduced by 1e10 times. Conversely, if the decimals of LP Token is 20, then the user's reward will increase by 100 times.

Impact

There may be two situations, depending on the decimals of LP Token:

  1. All users are rewarded less than expected, excess rewards will be trapped in the contract
  2. A small number of people have obtained excess rewards, and because the CRV is not enough, the contract is permanently DOS, and the rest cannot withdraw their own funds

Code Snippet

https://github.com/sherlock-audit/2023-04-blueberry/blob/main/blueberry-core/contracts/wrapper/WCurveGauge.sol#L156-L157

Tool used

Manual Review

Recommendation

    function burn(
        uint256 id,
        uint256 amount
    ) external nonReentrant returns (uint256 rewards) {
        if (amount == type(uint256).max) {
            amount = balanceOf(msg.sender, id);
        }
        (uint256 gid, uint256 stCrvPerShare) = decodeId(id);
        _burn(msg.sender, id, amount);
        ILiquidityGauge gauge = ILiquidityGauge(gaugeController.gauges(gid));
        require(address(gauge) != address(0), "gauge not registered");
        _mintCrv(gauge, gid);
        gauge.withdraw(amount);
        IERC20Upgradeable(gauge.lp_token()).safeTransfer(msg.sender, amount);
-       uint256 stCrv = (stCrvPerShare * amount) / 1e18;
-       uint256 enCrv = (accCrvPerShares[gid] * amount) / 1e18;
+       uint256 stCrv = (stCrvPerShare * amount) / gauge.lp_token().decimals();
+       uint256 enCrv = (accCrvPerShares[gid] * amount) / gauge.lp_token().decimals();
        if (enCrv > stCrv) {
            rewards = enCrv - stCrv;
            CRV.safeTransfer(msg.sender, rewards);
        }
        return rewards;
    }