sellProfits()
can be sanwiched.
The amountOutMinimum: 0,
in the ISwapRouter.ExactInputSingleParams memory params
opens up sandwiching opportunities. Consider the following example of why setting amountOutMinimum
is very dangerous. In this code implementation, the Fees.sol
contract sells all tokens into a Uniswap pair.
For demonstration purposes, a x*y = k AMM is used, with k set to 10000 initially. The pool's starting balances are
X: 100
WETH: 100
WETH | Token |
---|---|
100 | 100 |
The Fees.sol
contract intends to sell 10 of Token for WETH. With the pool's state of (100/100) he would receive 9.0909 WETH back. With an effective price of 1.1 for this trade.
However, a MEV-Searcher sees the operation in the Mempool and decides to sandwich it. What he does is:
Swap 10 Token for WETH. He will receive 9.0909 WETH. The new pool state is:
WETH | Token |
---|---|
90.90 | 110 |
Now the selling operation of Fees.sol
comes in. With the pool balance afterwards being:
WETH | Token |
---|---|
83.33 | 120 |
Due to the pool being imbalanced, the Fees.sol
contract only realized an effective price of 1.32.
Now the MEW-back backruns the selling operation of Fees.sol
and sells his WETH back into the pool. Resulting in the following pool state.
WETH | Token |
---|---|
92.42 | 108 |
The MEW Searcher has gained 12 Tokens with his last trade. This sequence of actions made the MEW-Bot 2 Tokens in Profit. (He started of with 10 Tokens and now has 12).
Given the size of imbalance (via flashloans for example) these sandwiches can be far more devastating for the Fees.sol
contract.
Any Trade can be sandwiched. Resulting in potentially 0 return Amount. This outcome is valid as the contract is willing to accept 0 WETH return Amount of Tokens for a trade.
Manual review
Always calculate an estimated return when executing sellProfits()
.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.