Summary
The TSwapPool:swapExactInput
has a named return, but that named return is not used anywhere in the function body, hence the function is always going to return zero (0).
Vulnerability Details
The user will always see zero (0) returning from TSwapPool:swapExactInput
leading to confusion at best, and panic at worst.
Tools Used
Foundry
Proof of Concept
modifier addLiquidity {
vm.startPrank(liquidityProvider);
weth.approve(address(pool), 100e18);
poolToken.approve(address(pool), 100e18);
pool.deposit(100e18, 100e18, 100e18, uint64(block.timestamp));
_;
}
function testSwapExactInput(uint32 fuzzInput) addLiquidity public {
if (fuzzInput == 0) { return; }
IERC20 inputToken = poolToken;
uint256 inputAmount = uint256(fuzzInput);
IERC20 outputToken = weth;
uint256 minOutputAmount = 0;
uint64 deadline = uint64(block.timestamp + 15 minutes);
vm.startPrank(user);
inputToken.approve(address(pool), inputAmount);
uint256 output = pool.swapExactInput(inputToken, inputAmount, outputToken, minOutputAmount, deadline);
assertEq(output, 0);
}
Recommended Mitigation
Is to simply is the named return variable.
function swapExactInput(
IERC20 inputToken,
uint256 inputAmount,
IERC20 outputToken,
uint256 minOutputAmount,
uint64 deadline
)
public
revertIfZero(inputAmount)
revertIfDeadlinePassed(deadline)
returns (uint256 output)
{
uint256 inputReserves = inputToken.balanceOf(address(this));
uint256 outputReserves = outputToken.balanceOf(address(this));
- uint256 outputAmount = getOutputAmountBasedOnInput(
+ output = getOutputAmountBasedOnInput(
inputAmount,
inputReserves,
outputReserves
);
- if (outputAmount < minOutputAmount) {
+ if (output < minOutputAmount) {
revert TSwapPool__OutputTooLow(outputAmount, minOutputAmount);
}
- _swap(inputToken, inputAmount, outputToken, outputAmount);
+ _swap(inputToken, inputAmount, outputToken, output);
}