This means, that whenever the balances change in the protocol, the ratio between the two amounts should remain constant, hence the k
. However, this is broken due to the extra incentive in the _swap
function. Meaning that over time the protocol funds will be drained.
The follow block of code is responsible for the issue.
**Impact:**A user could maliciously drain the protocol of funds by doing a lot of swaps and collecting the extra incentive given out by the protocol.
function testInvariantGetsBroken() public{
vm.startPrank(liquidityProvider);
weth.approve(address(pool), 100e18);
poolToken.approve(address(pool), 100e18);
pool.deposit(100e18, 100e18, 100e18, uint64(block.timestamp));
vm.stopPrank();
uint256 outputWeth = 1e17;
vm.startPrank(user);
poolToken.approve(address(pool), type(uint256).max);
poolToken.mint(user, 100e18);
pool.swapExactOutput(poolToken, weth, outputWeth, uint64(block.timestamp));
pool.swapExactOutput(poolToken, weth, outputWeth, uint64(block.timestamp));
pool.swapExactOutput(poolToken, weth, outputWeth, uint64(block.timestamp));
pool.swapExactOutput(poolToken, weth, outputWeth, uint64(block.timestamp));
pool.swapExactOutput(poolToken, weth, outputWeth, uint64(block.timestamp));
pool.swapExactOutput(poolToken, weth, outputWeth, uint64(block.timestamp));
pool.swapExactOutput(poolToken, weth, outputWeth, uint64(block.timestamp));
pool.swapExactOutput(poolToken, weth, outputWeth, uint64(block.timestamp));
pool.swapExactOutput(poolToken, weth, outputWeth, uint64(block.timestamp));
int256 startingY = int256(weth.balanceOf(address(pool)));
int256 expectedChangeInY = int256(-1) * int256(outputWeth);
pool.swapExactOutput(poolToken, weth, outputWeth, uint64(block.timestamp));
vm.stopPrank();
uint256 endingY = weth.balanceOf(address(pool));
int256 actualChangeInY = int256(endingY) - int256(startingY);
assert(actualChangeInY == expectedChangeInY);
}
function _swap(
IERC20 inputToken,
uint256 inputAmount,
IERC20 outputToken,
uint256 outputAmount
) private {
if (
_isUnknown(inputToken) ||
_isUnknown(outputToken) ||
inputToken == outputToken
) {
revert TSwapPool__InvalidToken();
}
- swap_count++;
- if (swap_count >= SWAP_COUNT_MAX) {
- swap_count = 0;
- outputToken.safeTransfer(msg.sender, 1_000_000_000_000_000_000);
- }
emit Swap(
msg.sender,
inputToken,
inputAmount,
outputToken,
outputAmount
);
inputToken.safeTransferFrom(msg.sender, address(this), inputAmount);
outputToken.safeTransfer(msg.sender, outputAmount);
}