31597 - [SC - High] Loss of precision while calculating claimable f...

Submitted on May 21st 2024 at 16:09:53 UTC by @savi0ur for Boost | Alchemix

Report ID: #31597

Report type: Smart Contract

Report severity: High

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

Impacts:

  • Contract fails to deliver promised returns, but doesn't lose value

Description

Bug Description

https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/VotingEscrow.sol#L38

/// @notice Multiplier for the slope of the decay
uint256 public constant MULTIPLIER = 2;

https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/VotingEscrow.sol#L44

int256 internal constant iMULTIPLIER = 2;

https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/VotingEscrow.sol#L1157-L1160

function _calculatePoint(LockedBalance memory _locked, uint256 _time) internal pure returns (Point memory point) {
    if (_locked.end > _time && _locked.amount > 0) {
        point.slope = _locked.maxLockEnabled ? int256(0) : (int256(_locked.amount) * iMULTIPLIER) / iMAXTIME;
        point.bias = _locked.maxLockEnabled
            ? ((int256(_locked.amount) * iMULTIPLIER) / iMAXTIME) * (int256(_locked.end - _time))
            : (point.slope * (int256(_locked.end - _time)));
    }
}

As we can see, iMULTIPLIER and MULTIPLIER is set to 2, which is not sufficient to preserve the precision.

point.slope and point.bias are calculated as follow:

When (int256(_locked.amount) * iMULTIPLIER) < iMAXTIME and ((int256(_locked.amount) * iMULTIPLIER) < iMAXTIME, it results in zero. So for the locked amounts which is small enough when multiplied by iMULTIPLIER=2 end up being lower than iMAXTIME, will not be counted in bias and slope calculation. At that point in time, there slope and bias will be zero.

For example,

As we can, both slope and bias become zero.

https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/FluxToken.sol#L224

Similarly, in getClaimableFlux function, claimableFlux is calculated as

Here also, veMul = 2 as its fetched from VotingEscrow's multiplier.

Impact

Precision loss while calculating claimable flux and point's bias and slope.

Recommendation

Increase MULTIPLIER and iMULTIPLIER precision from 2 to 1e18, for higher precision.

References

  • https://github.com/alchemix-finance/alchemix-v2-dao/blob/main/src/VotingEscrow.sol

  • https://github.com/alchemix-finance/alchemix-v2-dao/blob/main/src/FluxToken.sol

Proof Of Concept

Steps to Run using Foundry:

  • Paste following foundry code in src/test/FluxToken.t.sol

  • Run using FOUNDRY_PROFILE=default forge test --fork-url $FORK_URL --fork-block-number 17133822 --match-contract FluxTokenTest --match-test testPrecisionLoss -vv

Console Output:

As we can see, by increasing MULTIPLIER, precision has increased. We have used 200000 as MULTIPLIER here to show precision issue as it was set 2 initially.

Last updated

Was this helpful?