feat: Verify that no amount in is left in the router
--- don't change below this line --- ENG-4087 Took 1 hour 41 minutes Took 2 minutes
This commit is contained in:
@@ -18,6 +18,7 @@ import {LibSwap} from "../lib/LibSwap.sol";
|
|||||||
error TychoRouter__WithdrawalFailed();
|
error TychoRouter__WithdrawalFailed();
|
||||||
error TychoRouter__AddressZero();
|
error TychoRouter__AddressZero();
|
||||||
error TychoRouter__NegativeSlippage(uint256 amount, uint256 minAmount);
|
error TychoRouter__NegativeSlippage(uint256 amount, uint256 minAmount);
|
||||||
|
error TychoRouter__AmountInNotFullySpent(uint256 leftoverAmount);
|
||||||
error TychoRouter__MessageValueMismatch(uint256 value, uint256 amount);
|
error TychoRouter__MessageValueMismatch(uint256 value, uint256 amount);
|
||||||
|
|
||||||
contract TychoRouter is
|
contract TychoRouter is
|
||||||
@@ -153,6 +154,7 @@ contract TychoRouter is
|
|||||||
// For native ETH, assume funds already in our router. Else, transfer and handle approval.
|
// For native ETH, assume funds already in our router. Else, transfer and handle approval.
|
||||||
if (wrapEth) {
|
if (wrapEth) {
|
||||||
_wrapETH(amountIn);
|
_wrapETH(amountIn);
|
||||||
|
tokenIn = address(_weth);
|
||||||
} else if (tokenIn != address(0)) {
|
} else if (tokenIn != address(0)) {
|
||||||
permit2.permit(msg.sender, permitSingle, signature);
|
permit2.permit(msg.sender, permitSingle, signature);
|
||||||
permit2.transferFrom(
|
permit2.transferFrom(
|
||||||
@@ -175,6 +177,11 @@ contract TychoRouter is
|
|||||||
revert TychoRouter__NegativeSlippage(amountOut, minAmountOut);
|
revert TychoRouter__NegativeSlippage(amountOut, minAmountOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint256 leftoverAmountIn = IERC20(tokenIn).balanceOf(address(this));
|
||||||
|
if (leftoverAmountIn > 0) {
|
||||||
|
revert TychoRouter__AmountInNotFullySpent(leftoverAmountIn);
|
||||||
|
}
|
||||||
|
|
||||||
if (unwrapEth) {
|
if (unwrapEth) {
|
||||||
_unwrapETH(amountOut);
|
_unwrapETH(amountOut);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -733,4 +733,56 @@ contract TychoRouterTest is TychoRouterTestSetup {
|
|||||||
// all of it (and thus our splits are correct).
|
// all of it (and thus our splits are correct).
|
||||||
assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0);
|
assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testSwapAmountInNotFullySpent() public {
|
||||||
|
// Trade 1 WETH for DAI with 1 swap on Uniswap V2
|
||||||
|
// Has invalid data as input! There is only one swap with 60% of the input amount
|
||||||
|
uint256 amountIn = 1 ether;
|
||||||
|
deal(WETH_ADDR, ALICE, amountIn);
|
||||||
|
|
||||||
|
vm.startPrank(ALICE);
|
||||||
|
|
||||||
|
(
|
||||||
|
IAllowanceTransfer.PermitSingle memory permitSingle,
|
||||||
|
bytes memory signature
|
||||||
|
) = handlePermit2Approval(WETH_ADDR, amountIn);
|
||||||
|
|
||||||
|
bytes memory protocolData = encodeUniswapV2Swap(
|
||||||
|
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
|
||||||
|
);
|
||||||
|
|
||||||
|
bytes memory swap = encodeSwap(
|
||||||
|
uint8(0),
|
||||||
|
uint8(1),
|
||||||
|
(0xffffff * 60) / 100, // 60%
|
||||||
|
address(usv2Executor),
|
||||||
|
bytes4(0),
|
||||||
|
protocolData
|
||||||
|
);
|
||||||
|
|
||||||
|
bytes[] memory swaps = new bytes[](1);
|
||||||
|
swaps[0] = swap;
|
||||||
|
|
||||||
|
vm.expectRevert(
|
||||||
|
abi.encodeWithSelector(
|
||||||
|
TychoRouter__AmountInNotFullySpent.selector, 400000000000000000
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
tychoRouter.swap(
|
||||||
|
amountIn,
|
||||||
|
WETH_ADDR,
|
||||||
|
DAI_ADDR,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
2,
|
||||||
|
ALICE,
|
||||||
|
permitSingle,
|
||||||
|
signature,
|
||||||
|
pleEncode(swaps)
|
||||||
|
);
|
||||||
|
|
||||||
|
vm.stopPrank();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user