sherlock-audit / 2024-05-elfi-protocol-judging

0 stars 0 forks source link

ZeroTrust - Precision loss in `_executeMintStakeUsd()` #291

Closed sherlock-admin4 closed 1 week ago

sherlock-admin4 commented 2 weeks ago

ZeroTrust

Medium

Precision loss in _executeMintStakeUsd()

Summary

Precision loss in _executeMintStakeUsd()

Vulnerability Detail

function _executeMintStakeUsd(
        Mint.Request memory params,
        UsdPool.Props storage pool,
        uint256 baseMintAmount
    ) internal returns (uint256) {
        address stableToken = params.requestToken;
        uint256 totalSupply = TokenUtils.totalSupply(params.stakeToken);
        uint8 tokenDecimals = TokenUtils.decimals(stableToken);
        uint8 stakeTokenDecimals = TokenUtils.decimals(params.stakeToken);
        uint256 poolValue = pool.getUsdPoolValue();
        uint256 mintStakeTokenAmount;
        if (totalSupply == 0 && poolValue == 0) {
                                //@audit = Math.mulDiv(value, 10 ** stakeTokenDecimals, 10 ** tokenDecimals)
@>>            mintStakeTokenAmount = CalUtils.decimalsToDecimals(baseMintAmount, tokenDecimals, stakeTokenDecimals);
        } else if (totalSupply == 0 && poolValue > 0) {
            uint256 totalBaseMintAmount = baseMintAmount +
                CalUtils.usdToToken(poolValue, tokenDecimals, OracleProcess.getLatestUsdUintPrice(stableToken, true));
            mintStakeTokenAmount = CalUtils.decimalsToDecimals(totalBaseMintAmount, tokenDecimals, stakeTokenDecimals);
        } else if (poolValue == 0) {
            revert Errors.PoolValueIsZero();
        } else {
            uint256 baseMintAmountInUsd = CalUtils.tokenToUsd(
                baseMintAmount,
                tokenDecimals,
                OracleProcess.getLatestUsdUintPrice(stableToken, true)
            );//@audit baseMintAmountInUsd*totalSupply/poolValue
@>>            mintStakeTokenAmount = totalSupply.mul(baseMintAmountInUsd).div(poolValue);
        }
        if (params.minStakeAmount > 0 && mintStakeTokenAmount < params.minStakeAmount) {
            revert Errors.MintStakeTokenTooSmall(params.minStakeAmount, mintStakeTokenAmount);
        }

        StakeToken(params.stakeToken).mint(params.account, mintStakeTokenAmount);

        return mintStakeTokenAmount;
    }

Assume stakeTokenDecimals is 6 and tokenDecimals(like Dai) is 18. The amount of mintStakeTokenAmount is smaller than the actual amount due to precision loss. The same issue in totalSupply.mul(baseMintAmountInUsd).div(poolValue);

Impact

This results in financial loss for the user.

Code Snippet

https://github.com/sherlock-audit/2024-05-elfi-protocol/blob/main/elfi-perp-contracts/contracts/process/MintProcess.sol#L228

Tool used

Manual Review

Recommendation

nevillehuang commented 2 days ago

Invalid, lack required PoC by sherlock rules for precision loss issues as per here