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.
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.
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 thetoMint
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
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.