Attacker calls MarginRouter.crossSwapExactTokensForTokens with a fake pair and the same token[0] == tokne[1].
crossSwapExactTokensForTokens(1000 WETH, 0, [ATTACKER_CONTRACT], [WETH, WETH]). When the amounts are computed by the amounts = UniswapStyleLib.getAmountsOut(amountIn - fees, pairs, tokens); call, the attacker contract returns fake reserves that yield 0 output
When _swapExactT4T is called, the funds are sent to the fake contract and doing nothing passes all checks in _swap call that follows because the startingBalance is stored after the initial Fund withdraw to the pair.
The full impact is not yet known as registerTrade could still fail when subtracting the inAmount and adding 0 outAmount.
At least, this attack is similar to a withdrawal which is supposed to only occur after a certain coolingOffPeriod has passed, but this time-lock is circumvented with this attack.
Recommended mitigation steps
Move the fund withdrawal to the first pair after the startingBalance assignment.
Check fromToken != toToken as cyclical trades (arbitrages) are likely not what margin traders are after.
Consider if the same check is required for registerTradeAndBorrow / adjustAmounts functions.
Email address
mail@cmichel.io
Handle
@cmichelio
Eth address
0x6823636c2462cfdcD8d33fE53fBCD0EdbE2752ad
Vulnerability details
Attacker calls
MarginRouter.crossSwapExactTokensForTokens
with a fake pair and the same token[0] == tokne[1].crossSwapExactTokensForTokens(1000 WETH, 0, [ATTACKER_CONTRACT], [WETH, WETH])
. When the amounts are computed by theamounts = UniswapStyleLib.getAmountsOut(amountIn - fees, pairs, tokens);
call, the attacker contract returns fake reserves that yield 0 output When_swapExactT4T
is called, the funds are sent to the fake contract and doing nothing passes all checks in_swap
call that follows because thestartingBalance
is stored after the initial Fund withdraw to the pair.Impact
The full impact is not yet known as
registerTrade
could still fail when subtracting theinAmount
and adding 0outAmount
. At least, this attack is similar to a withdrawal which is supposed to only occur after a certaincoolingOffPeriod
has passed, but this time-lock is circumvented with this attack.Recommended mitigation steps
Move the fund withdrawal to the first pair after the
startingBalance
assignment. CheckfromToken != toToken
as cyclical trades (arbitrages) are likely not what margin traders are after. Consider if the same check is required forregisterTradeAndBorrow
/adjustAmounts
functions.