/// @dev Mints LP tokens - should be called via the router after transferring `bento` tokens.
/// The router must ensure that sufficient LP tokens are minted by using the return value.
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;
}
Proof of Concept
Given:
A IndexPool of 60% WBTC and 40% pBTC;
Alice is the first liquidity provider.
Alice try to mint 100e18 of liquidity;
Alice transfers 1e18 WBTC and 1e18 pBTC;
Alice gets 100e18 of liquidity, worth 1 BTC.
Impact
A significant portion (50% in the case above) of the user's funds cannot be retrieved.
Recommendation
Always mint IndexPool.INIT_POOL_SUPPLY of liquidity to the first liquidity provider and takes just the MIN_BALANCE of each token.
This makes the first liquidity provider always gets a 50% share of the pool while paying MIN_BALANCE of each token.
Handle
WatchPug
Vulnerability details
https://github.com/sushiswap/trident/blob/6bd4c053b6213ffc612987eb565aa3813d5f0d13/contracts/pool/IndexPool.sol#L33
https://github.com/sushiswap/trident/blob/6bd4c053b6213ffc612987eb565aa3813d5f0d13/contracts/pool/IndexPool.sol#L93-L105
Proof of Concept
Given:
Impact
A significant portion (50% in the case above) of the user's funds cannot be retrieved.
Recommendation
Always mint
IndexPool.INIT_POOL_SUPPLY
of liquidity to the first liquidity provider and takes just the MIN_BALANCE of each token.This makes the first liquidity provider always gets a 50% share of the pool while paying MIN_BALANCE of each token.