First Flight #18: T-Swap

First Flight #18
Beginner FriendlyDeFiFoundry
100 EXP
View results
Submission Details
Severity: high
Valid

Incorrect swapping mechanism in `TSwapPool.sellPoolTokens` leads to user losses

Summary

  • In the sellPoolTokens function users specify the number of pool tokens they want to sell using the poolTokenAmount parameter. However, the function currently miscalculates the swapped amount as shown on the PoC below. This issue arises because the swapExactOutput function is called instead of the correct swapExactInput function. Users provide the exact amount of input tokens, not the output amount.

  • sellPoolTokens tokens is also missing a deadline check meaning users might inadvertently be selling at an unfavorable rate.

Vulnerability Details

  • PoC - Copy this test into TSwapPool.t.sol

  • According to the test below, the user's actual balance is lower than the expected balance, indicating the user is selling for less.

function testSellPoolTokens() public {
vm.startPrank(liquidityProvider);
weth.approve(address(pool), 100e18);
poolToken.approve(address(pool), 100e18);
pool.deposit(100e18, 100e18, 100e18, uint64(block.timestamp));
vm.stopPrank();
vm.startPrank(user);
poolToken.approve(address(pool), type(uint256).max);
//User has starting 1e19 of pool token balance
uint256 startingUserBalance = poolToken.balanceOf(user);
uint256 poolTokenAmounToSell = 1e10;
pool.sellPoolTokens(poolTokenAmounToSell);
uint256 expectedFinalUserBalance = startingUserBalance - poolTokenAmounToSell;
uint256 actualFinalUserBalance = poolToken.balanceOf(user);
assertEq(expectedFinalUserBalance, actualFinalUserBalance); //expected: 9999999990000000000 vs actual: 9999999899699097282
//Something is wrong, the actual final balance is lower!
}

Impact

  • Users will swap the wrong amount, resulting in losses.

  • Seeling tokens without deadline may occur at an unfavorable rates.

Tools Used

  • Manual review

Recommendations

  • Add a new parameter, for example, expectedWethAmount, which represents the minimum amount of weth to be received

  • Add a deadline parameter to be passed to swapExactInput

function sellPoolTokens(
uint256 poolTokenAmount,
+ uint256 expectedWethAmount,
+ uint64 deadline
) external returns (uint256 wethAmount) {
- return swapExactOutput(i_poolToken, i_wethToken, poolTokenAmount, uint64(block.timestamp));
+ return swapExactInput(i_poolToken, poolTokenAmount, i_wethToken, expectedWethAmount, deadline);
}
Updates

Appeal created

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

`sellPoolTokens` mismatches input and output tokens causing users to receive the incorrect amount of tokens

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.