diff --git a/foundry/src/TychoRouter.sol b/foundry/src/TychoRouter.sol index d80acb9..538cc43 100644 --- a/foundry/src/TychoRouter.sol +++ b/foundry/src/TychoRouter.sol @@ -486,15 +486,14 @@ contract TychoRouter is Address.sendValue(payable(receiver), amountOut); } - if (tokenIn != tokenOut) { - uint256 currentBalanceTokenOut = _balanceOf(tokenOut, receiver); - uint256 userAmount = currentBalanceTokenOut - initialBalanceTokenOut; - if (userAmount != amountOut) { - revert TychoRouter__AmountOutNotFullyReceived( - userAmount, amountOut - ); - } - } + _verifyAmountOutWasReceived( + tokenIn, + tokenOut, + initialBalanceTokenOut, + amountOut, + receiver, + amountIn + ); } /** @@ -543,15 +542,14 @@ contract TychoRouter is Address.sendValue(payable(receiver), amountOut); } - if (tokenIn != tokenOut) { - uint256 currentBalanceTokenOut = _balanceOf(tokenOut, receiver); - uint256 userAmount = currentBalanceTokenOut - initialBalanceTokenOut; - if (userAmount != amountOut) { - revert TychoRouter__AmountOutNotFullyReceived( - userAmount, amountOut - ); - } - } + _verifyAmountOutWasReceived( + tokenIn, + tokenOut, + initialBalanceTokenOut, + amountOut, + receiver, + amountIn + ); } /** @@ -596,16 +594,14 @@ contract TychoRouter is _unwrapETH(amountOut); Address.sendValue(payable(receiver), amountOut); } - - if (tokenIn != tokenOut) { - uint256 currentBalanceTokenOut = _balanceOf(tokenOut, receiver); - uint256 userAmount = currentBalanceTokenOut - initialBalanceTokenOut; - if (userAmount != amountOut) { - revert TychoRouter__AmountOutNotFullyReceived( - userAmount, amountOut - ); - } - } + _verifyAmountOutWasReceived( + tokenIn, + tokenOut, + initialBalanceTokenOut, + amountOut, + receiver, + amountIn + ); } /** @@ -834,4 +830,27 @@ contract TychoRouter is return token == address(0) ? owner.balance : IERC20(token).balanceOf(owner); } + + /** + * @dev Verifies that the expected amount of output tokens was received by the receiver. + * It also handles the case of arbitrage swaps where the input and output tokens are the same. + */ + function _verifyAmountOutWasReceived( + address tokenIn, + address tokenOut, + uint256 initialBalanceTokenOut, + uint256 amountOut, + address receiver, + uint256 amountIn + ) internal view { + uint256 currentBalanceTokenOut = _balanceOf(tokenOut, receiver); + if (tokenIn == tokenOut) { + // If it is an arbitrage, we need to remove the amountIn from the initial balance to get a correct userAmount + initialBalanceTokenOut -= amountIn; + } + uint256 userAmount = currentBalanceTokenOut - initialBalanceTokenOut; + if (userAmount != amountOut) { + revert TychoRouter__AmountOutNotFullyReceived(userAmount, amountOut); + } + } }