First Flight #18: T-Swap

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

Incorrect Input handling in `TSwapPool::sellPoolTokens` causes users to receive wrong amount of tokens

Summary

Input is handled incorrectly which provide Incorrect amount to tokens to users.

Vulnerability Details

sellPoolTokens function is used to allows users to make sells of given tokens and get WETH as a output. User can input, how much tokens they want to sell by specifying the poolTokenAmount parameter. But current logic in the correct incorrectly handle this input and miscalculate the swapped amount.

function sellPoolTokens(
uint256 poolTokenAmount
) external returns (uint256 wethAmount) {
return
@> swapExactOutput(
i_poolToken,
i_wethToken,
poolTokenAmount,
uint64(block.timestamp)
);
}
function swapExactOutput(
IERC20 inputToken,
IERC20 outputToken,
@> uint256 outputAmount, /// input token amount is being passed here
uint64 deadline
)
public
revertIfZero(outputAmount)
revertIfDeadlinePassed(deadline)
returns (uint256 inputAmount)
{
uint256 inputReserves = inputToken.balanceOf(address(this));
uint256 outputReserves = outputToken.balanceOf(address(this));
inputAmount = getInputAmountBasedOnOutput(
outputAmount,
inputReserves,
outputReserves
);
_swap(inputToken, inputAmount, outputToken, outputAmount);
}

As we can see, the swapExactOutput function is being used which is incorrect in current context.
As users is specifying the exact amount of input tokens so swapExactInput should be called.

POC

In existing test suite, add following test -

function testAmountMismatchDueToWrongInputHandling () public {
vm.startPrank(liquidityProvider);
weth.approve(address(pool), 100e18);
poolToken.approve(address(pool), 50e18);
pool.deposit(100e18, 100e18, 50e18, uint64(block.timestamp));
assertEq(pool.balanceOf(liquidityProvider), 100e18);
assertEq(weth.balanceOf(liquidityProvider), 100e18);
vm.stopPrank();
vm.startPrank(user);
poolToken.approve(address(pool), 10e18);
console.log("user token balance before swap:", poolToken.balanceOf(user));
console.log("user weth balance before swap: ", weth.balanceOf(user));
pool.sellPoolTokens(1e18);
console.log("user balance:", poolToken.balanceOf(user));
console.log("user weth balance after swap: ", weth.balanceOf(user));
}

now run forge test --mt testAmountMismatchDueToWrongInputHandlin -vv and it will show following results in output.

[⠊] Compiling...
[⠑] Compiling 1 files with Solc 0.8.20
[⠘] Solc 0.8.20 finished in 1.63s
Compiler run successful :
Ran 1 test for test/unit/TSwapPool.t.sol:TSwapPoolTest
[PASS] testAmountMismatchDueToWrongInputHandling() (gas: 233011)
Logs:
user token balance before swap: 10000000000000000000
user weth balance before swap: 10000000000000000000
user balance: 4934297843024021560
user weth balance after swap: 11000000000000000000
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.15ms (244.79µs CPU time)
Ran 1 test suite in 154.09ms (1.15ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)

As we can see that we inputted 1 token but it deducted more than 5 tokens and output token we received was exactly 1 weth. This means input and output amounts are being flipped at the moment at function level.

Impact

Users will get mismatched amounts of tokens, which will affect the core protocol.

Tools Used

Manual Review

Recommendations

Update the current logic to use swapExactInput instead of swapExactOutput. To make this change properly, sellPoolTokens function requires a new parameter (ie minWethToReceive to be passed to swapExactInput).

Example implementation is attached below:

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

Appeal created

inallhonesty Lead Judge 12 months 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.