code-423n4 / 2021-09-wildcredit-findings

0 stars 0 forks source link

TridentRouter.addLiquidity() Add liquidity to IndexPool through TridentRouter may casue loss of a small portion of users funds #99

Closed code423n4 closed 2 years ago

code423n4 commented 2 years ago

Handle

WatchPug

Vulnerability details

The mint function in IndexPool requires the liquidity provider to transfer in amounts no less than the amounts of tokens' reserve proportionally to the toMint amount.

However, the TridentRouter won't calculate the toMint amount and amountsIn for the liquidity provider, and the extra amounts won't return to the liquidity provider.

This means the user must calculate the amountsIn off-chain and transfer a bit more of each token to make sure the mint can succeed, and most certainly there will be a small portion of users funds won't get added as liquidity (as part of the reserves) but remains in the pool contract.

https://github.com/sushiswap/trident/blob/9f949d9bddf7f12775e0c6ae641e9305c4762ea2/contracts/pool/IndexPool.sol#L90-L111

function mint(bytes calldata data) public override lock returns (uint256 liquidity) {
        (address recipient, uint256 toMint) = abi.decode(data, (address, uint256));

        uint120 ratio = uint120(_div(toMint, totalSupply));

        for (uint256 i = 0; i < tokens.length; i++) {
            address tokenIn = tokens[i];
            uint120 reserve = records[tokenIn].reserve;
            // @dev If token balance is '0', initialize with `ratio`.
            uint120 amountIn = reserve != 0 ? uint120(_mul(ratio, reserve)) : ratio;
            require(amountIn >= MIN_BALANCE, "MIN_BALANCE");
            // @dev Check Trident router has sent `amountIn` for skim into pool.
            unchecked {
                // @dev This is safe from overflow - only logged amounts handled.
                require(_balance(tokenIn) >= amountIn + reserve, "NOT_RECEIVED");
                records[tokenIn].reserve += amountIn;
            }
            emit Mint(msg.sender, tokenIn, amountIn, recipient);
        }
        _mint(recipient, toMint);
        liquidity = toMint;
    }

Recommendation

Consider calculating the final amountsIn and toMint amount for the msg.sender and take user's input of amountsIn as maxAmountsIn in TridentRouter.addLiquidity() for IndexPool.

itsmetechjay commented 2 years ago

Withdrawn by warden. Per WatchPug: "I mistakenly submitted some issues of sushi to wild credit while having two tabs open at the same time"