First Flight #18: T-Swap

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

`TSwapPool::_swap` function transfers additional token from the pool to user every 10 swaps, breaking the `x * y = k` invariant and causing pool imbalance

Summary

The _swap function in the TSwapPool contract gives the user an extra token every 10 swaps as an incentive. This behavior breaks the constant product invariant x * y = k fundamental to Automated Market Makers (AMMs). By transferring an extra token, the pool's reserves become imbalanced, leading to a deviation from the invariant and causing potential economic issues.

Vulnerability Details

Proof of Concept Add the following function in TSwapPool.t.sol
```
function testInvariantBreaks() public {
    uint256 initialWETH = 50e18;
    uint256 initialPoolToken = 100e18;

    // Adding initial liquidity to the pool
    vm.startPrank(liquidityProvider);
    weth.approve(address(pool), type(uint256).max);
    poolToken.approve(address(pool), type(uint256).max);
    pool.deposit(initialWETH, initialPoolToken, initialPoolToken, uint64(block.timestamp));
    vm.stopPrank();

    uint256 outputWeth = 1e16;
    int256 startingY = int256(weth.balanceOf(address(pool)));
    // Negative because Y is taken away from the pool
    int256 expectedDeltaY;

    vm.startPrank(user);
    poolToken.approve(address(pool), type(uint256).max);

    // Swap token 10 times
    for (uint256 i = 1; i < 11; ++i) {
        pool.swapExactOutput(poolToken, weth, outputWeth, uint64(block.timestamp));
        expectedDeltaY = int256(-1) * int256(outputWeth) * int256(i);
    }

    uint256 endingY = weth.balanceOf(address(pool));

    int256 actualDeltaY = int256(endingY) - int256(startingY);

    // Pool has less token than it suppose to be because it transfer a free token to user every 10 swap
    vm.expectRevert();
    assertEq(actualDeltaY, expectedDeltaY);
}
```

This shows that the pool is imbalanced because additional tokens are transferred to the user, breaking the invariant.

Impact

The constant product invariant is crucial for maintaining the correct price ratios between tokens in the liquidity pool. By breaking this invariant, the pool may imbalanced, severely impact the protocol's core functionality

Tools Used

  • Manual review

  • Foundry invariant testing

Recommendations

  1. Consider removing this incentive method.

Updates

Appeal created

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

In `TSwapPool::_swap` the extra tokens given to users after every swapCount breaks the protocol invariant of x * y = k

Support

FAQs

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