[M-05] claim Function Fails to Protect Stakeholders from Slippage
Proof of Concept
Stakeholders are allowed to claim their Sale and Raise tokens for the liquidity positions when the Pool officially launches.
The claim function in the contract burns the stakeholder's claimable liquidity from Uniswap V3 Pool, deducts platform and performance fees, and sends the net tokens to the stakeholder by adding fees their position generated.
However, the current implementation fails to protect against slippage, which can lead to unexpected result for Stakeholders/loss of funds.
function claim(uint256 tokenId)
external
payable
override
isAuthorizedForToken(tokenId)
returns (uint256 amount0, uint256 amount1)
{
// SNIP
{
// SNIP
// get amount of token0 and token1 that pool will return for us
1-> (amount0, amount1) = pool.burn(TICK_LOWER, TICK_UPPER, liquidity2Claim);
// get amount of token0 and token1 after deduct platform fee
2-> (amount0, amount1) = _deductFees(amount0, amount1, _project.platformFee);
bytes32 positionKey = PositionKey.compute(address(this), TICK_LOWER, TICK_UPPER);
// calculate amount of fees that position generated
(, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, , ) = pool.positions(positionKey);
uint256 fees0 = FullMath.mulDiv(feeGrowthInside0LastX128 - position.feeGrowthInside0LastX128, positionLiquidity, FixedPoint128.Q128);
uint256 fees1 = FullMath.mulDiv(feeGrowthInside1LastX128 - position.feeGrowthInside1LastX128, positionLiquidity, FixedPoint128.Q128);
// amount of fees after deduct performance fee
3-> (fees0, fees1) = _deductFees(fees0, fees1, _project.performanceFee);
// fees is combined with liquidity token amount to return to the user
amount0 += fees0;
amount1 += fees1;
position.feeGrowthInside0LastX128 = feeGrowthInside0LastX128;
position.feeGrowthInside1LastX128 = feeGrowthInside1LastX128;
// subtraction is safe because we checked positionLiquidity is gte liquidity2Claim
position.liquidity = positionLiquidity - liquidity2Claim;
emit DecreaseLiquidity(tokenId, liquidity2Claim, amount0, amount1);
}
// SNIP
}
Let's focus on each 3 points marked above:
burning Liquidity:
Once the Pool launches, interaction directly with Uniswap V3 Pool is allowed. Users can swap to influence the balance of the pool.
The amount of tokens received from the Uniswap V3 Pool function while burning might be manipulated by front-runners due to the decentralized nature of AMMs.
Lack of slippage protection exposes users to such attacks.
Deducting Platform Fees:
Platform Fees can be updated by the Owner of ILOManager through the setPlatformFee function.
If the owner updates the fees while a user's transaction is pending, it can lead to unexpected and unfair outcomes for the user if the fee is increased.
Deducting Performance Fees:
Again, Performance Fees can also be updated by the Owner of ILOManager through the setPerformanceFee function.
If the owner updates the fees while a user's transaction is pending, it can lead to unexpected and unfair outcomes for the user if the fee is increased.
Due to these factors, validating amount0 and amount1 is crucial to ensure they meet the user's expectations.
Impact
Loss of funds due to slippage and unexpected fee increases.
Tools Used
VS Code
Recommended Mitigation Steps
Consider adding amount0Min and amount1Min parameters in function definition and ensure that Stakeholders receive atleast those tokens at the end.
Lines of code
https://github.com/code-423n4/2024-06-vultisig/blob/main/src/ILOPool.sol#L184
Vulnerability details
[M-05]
claim
Function Fails to Protect Stakeholders from SlippageProof of Concept
Stakeholders are allowed to claim their Sale and Raise tokens for the liquidity positions when the Pool officially launches.
The
claim
function in the contract burns the stakeholder's claimable liquidity from Uniswap V3 Pool, deducts platform and performance fees, and sends the net tokens to the stakeholder by adding fees their position generated.However, the current implementation fails to protect against slippage, which can lead to unexpected result for Stakeholders/loss of funds.
Let's focus on each 3 points marked above:
burning Liquidity:
Once the Pool launches, interaction directly with Uniswap V3 Pool is allowed. Users can
swap
to influence the balance of the pool.The amount of tokens received from the Uniswap V3 Pool function while burning might be manipulated by front-runners due to the decentralized nature of AMMs.
Lack of slippage protection exposes users to such attacks.
Deducting Platform Fees:
Platform Fees can be updated by the Owner of
ILOManager
through thesetPlatformFee
function.If the owner updates the fees while a user's transaction is pending, it can lead to unexpected and unfair outcomes for the user if the fee is increased.
Deducting Performance Fees:
Again, Performance Fees can also be updated by the Owner of
ILOManager
through thesetPerformanceFee
function.If the owner updates the fees while a user's transaction is pending, it can lead to unexpected and unfair outcomes for the user if the fee is increased.
Due to these factors, validating
amount0
andamount1
is crucial to ensure they meet the user's expectations.Impact
Loss of funds due to slippage and unexpected fee increases.
Tools Used
VS Code
Recommended Mitigation Steps
Consider adding
amount0Min
andamount1Min
parameters in function definition and ensure that Stakeholders receive atleast those tokens at the end.Assessed type
Other