diff --git a/foundry/src/TychoRouter.sol b/foundry/src/TychoRouter.sol index 1b693fd..f9597a1 100644 --- a/foundry/src/TychoRouter.sol +++ b/foundry/src/TychoRouter.sol @@ -58,6 +58,9 @@ import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; error TychoRouter__AddressZero(); error TychoRouter__EmptySwaps(); error TychoRouter__NegativeSlippage(uint256 amount, uint256 minAmount); +error TychoRouter__AmountOutNotFullyReceived( + uint256 amountIn, uint256 amountConsumed +); error TychoRouter__MessageValueMismatch(uint256 value, uint256 amount); error TychoRouter__InvalidDataLength(); error TychoRouter__UndefinedMinAmountOut(); @@ -420,6 +423,8 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { _wrapETH(amountIn); tokenIn = address(_weth); } + + uint256 initialBalanceTokenOut = _balanceOf(tokenOut, receiver); amountOut = _splitSwap(amountIn, nTokens, swaps); if (amountOut < minAmountOut) { @@ -428,11 +433,17 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { if (unwrapEth) { _unwrapETH(amountOut); - } - if (tokenOut == address(0)) { Address.sendValue(payable(receiver), amountOut); - } else { - IERC20(tokenOut).safeTransfer(receiver, amountOut); + } + + if (tokenIn != tokenOut) { + uint256 currentBalanceTokenOut = _balanceOf(tokenOut, receiver); + uint256 userAmount = currentBalanceTokenOut - initialBalanceTokenOut; + if (userAmount != amountOut) { + revert TychoRouter__AmountOutNotFullyReceived( + userAmount, amountOut + ); + } } } @@ -470,6 +481,7 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { (address executor, bytes calldata protocolData) = swap_.decodeSingleSwap(); + uint256 initialBalanceTokenOut = _balanceOf(tokenOut, receiver); amountOut = _callExecutor(executor, amountIn, protocolData); if (amountOut < minAmountOut) { @@ -478,11 +490,17 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { if (unwrapEth) { _unwrapETH(amountOut); - } - if (tokenOut == address(0)) { Address.sendValue(payable(receiver), amountOut); - } else { - IERC20(tokenOut).safeTransfer(receiver, amountOut); + } + + if (tokenIn != tokenOut) { + uint256 currentBalanceTokenOut = _balanceOf(tokenOut, receiver); + uint256 userAmount = currentBalanceTokenOut - initialBalanceTokenOut; + if (userAmount != amountOut) { + revert TychoRouter__AmountOutNotFullyReceived( + userAmount, amountOut + ); + } } } @@ -517,7 +535,9 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { tokenIn = address(_weth); } + uint256 initialBalanceTokenOut = _balanceOf(tokenOut, receiver); amountOut = _sequentialSwap(amountIn, swaps); + uint256 currentBalanceTokenIn = _balanceOf(tokenIn, address(this)); if (amountOut < minAmountOut) { revert TychoRouter__NegativeSlippage(amountOut, minAmountOut); @@ -525,11 +545,17 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { if (unwrapEth) { _unwrapETH(amountOut); - } - if (tokenOut == address(0)) { Address.sendValue(payable(receiver), amountOut); - } else { - IERC20(tokenOut).safeTransfer(receiver, amountOut); + } + + if (tokenIn != tokenOut) { + uint256 currentBalanceTokenOut = _balanceOf(tokenOut, receiver); + uint256 userAmount = currentBalanceTokenOut - initialBalanceTokenOut; + if (userAmount != amountOut) { + revert TychoRouter__AmountOutNotFullyReceived( + userAmount, amountOut + ); + } } } @@ -764,4 +790,13 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { _handleCallback(data); return ""; } + + function _balanceOf(address token, address owner) + internal + view + returns (uint256) + { + return + token == address(0) ? owner.balance : IERC20(token).balanceOf(owner); + } } diff --git a/foundry/src/executors/CurveExecutor.sol b/foundry/src/executors/CurveExecutor.sol index 933077e..8c9995c 100644 --- a/foundry/src/executors/CurveExecutor.sol +++ b/foundry/src/executors/CurveExecutor.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.26; import "@interfaces/IExecutor.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "./TokenTransfer.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; error CurveExecutor__AddressZero(); error CurveExecutor__InvalidDataLength(); @@ -54,7 +55,7 @@ contract CurveExecutor is IExecutor, TokenTransfer { payable returns (uint256) { - if (data.length != 65) revert CurveExecutor__InvalidDataLength(); + if (data.length != 85) revert CurveExecutor__InvalidDataLength(); ( address tokenIn, @@ -64,7 +65,8 @@ contract CurveExecutor is IExecutor, TokenTransfer { int128 i, int128 j, bool tokenApprovalNeeded, - TransferType transferType + TransferType transferType, + address receiver ) = _decodeData(data); _transfer( @@ -109,7 +111,16 @@ contract CurveExecutor is IExecutor, TokenTransfer { } uint256 balanceAfter = _balanceOf(tokenOut); - return balanceAfter - balanceBefore; + uint256 amountOut = balanceAfter - balanceBefore; + + if (receiver != address(this)) { + if (tokenOut == nativeToken) { + Address.sendValue(payable(receiver), amountOut); + } else { + IERC20(tokenOut).safeTransfer(receiver, amountOut); + } + } + return amountOut; } function _decodeData(bytes calldata data) @@ -123,7 +134,8 @@ contract CurveExecutor is IExecutor, TokenTransfer { int128 i, int128 j, bool tokenApprovalNeeded, - TransferType transferType + TransferType transferType, + address receiver ) { tokenIn = address(bytes20(data[0:20])); @@ -134,6 +146,7 @@ contract CurveExecutor is IExecutor, TokenTransfer { j = int128(uint128(uint8(data[62]))); tokenApprovalNeeded = data[63] != 0; transferType = TransferType(uint8(data[64])); + receiver = address(bytes20(data[65:85])); } receive() external payable { diff --git a/foundry/src/executors/UniswapV4Executor.sol b/foundry/src/executors/UniswapV4Executor.sol index aafbd7d..9191f98 100644 --- a/foundry/src/executors/UniswapV4Executor.sol +++ b/foundry/src/executors/UniswapV4Executor.sol @@ -46,6 +46,7 @@ contract UniswapV4Executor is IExecutor, V4Router, ICallback, TokenTransfer { address tokenOut, bool zeroForOne, TransferType transferType, + address receiver, UniswapV4Executor.UniswapV4Pool[] memory pools ) = _decodeData(data); @@ -72,7 +73,7 @@ contract UniswapV4Executor is IExecutor, V4Router, ICallback, TokenTransfer { bytes memory actions = abi.encodePacked( uint8(Actions.SWAP_EXACT_IN_SINGLE), uint8(Actions.SETTLE_ALL), - uint8(Actions.TAKE_ALL) + uint8(Actions.TAKE) ); bytes[] memory params = new bytes[](3); @@ -87,7 +88,7 @@ contract UniswapV4Executor is IExecutor, V4Router, ICallback, TokenTransfer { }) ); params[1] = abi.encode(tokenIn, amountIn); // currency to settle - params[2] = abi.encode(tokenOut, uint256(0)); // currency to take + params[2] = abi.encode(tokenOut, receiver, uint256(0)); // currency to take. 0 means to take the full amount swapData = abi.encode(actions, params); } else { PathKey[] memory path = new PathKey[](pools.length); @@ -104,7 +105,7 @@ contract UniswapV4Executor is IExecutor, V4Router, ICallback, TokenTransfer { bytes memory actions = abi.encodePacked( uint8(Actions.SWAP_EXACT_IN), uint8(Actions.SETTLE_ALL), - uint8(Actions.TAKE_ALL) + uint8(Actions.TAKE) ); bytes[] memory params = new bytes[](3); @@ -119,22 +120,23 @@ contract UniswapV4Executor is IExecutor, V4Router, ICallback, TokenTransfer { }) ); params[1] = abi.encode(currencyIn, amountIn); - params[2] = abi.encode(Currency.wrap(tokenOut), uint256(0)); + params[2] = + abi.encode(Currency.wrap(tokenOut), receiver, uint256(0)); swapData = abi.encode(actions, params); } uint256 tokenOutBalanceBefore; tokenOutBalanceBefore = tokenOut == address(0) - ? address(this).balance - : IERC20(tokenOut).balanceOf(address(this)); + ? receiver.balance + : IERC20(tokenOut).balanceOf(receiver); executeActions(swapData); uint256 tokenOutBalanceAfter; tokenOutBalanceAfter = tokenOut == address(0) - ? address(this).balance - : IERC20(tokenOut).balanceOf(address(this)); + ? receiver.balance + : IERC20(tokenOut).balanceOf(receiver); calculatedAmount = tokenOutBalanceAfter - tokenOutBalanceBefore; @@ -155,10 +157,11 @@ contract UniswapV4Executor is IExecutor, V4Router, ICallback, TokenTransfer { address tokenOut, bool zeroForOne, TransferType transferType, + address receiver, UniswapV4Pool[] memory pools ) { - if (data.length < 67) { + if (data.length < 88) { revert UniswapV4Executor__InvalidDataLength(); } @@ -166,10 +169,11 @@ contract UniswapV4Executor is IExecutor, V4Router, ICallback, TokenTransfer { tokenOut = address(bytes20(data[20:40])); zeroForOne = (data[40] != 0); transferType = TransferType(uint8(data[41])); + receiver = address(bytes20(data[42:62])); - uint256 poolsLength = (data.length - 42) / 26; // 26 bytes per pool object + uint256 poolsLength = (data.length - 62) / 26; // 26 bytes per pool object pools = new UniswapV4Pool[](poolsLength); - bytes memory poolsData = data[42:]; + bytes memory poolsData = data[62:]; uint256 offset = 0; for (uint256 i = 0; i < poolsLength; i++) { address intermediaryToken; diff --git a/foundry/test/TychoRouterIntegration.t.sol b/foundry/test/TychoRouterIntegration.t.sol index 053c780..f168175 100644 --- a/foundry/test/TychoRouterIntegration.t.sol +++ b/foundry/test/TychoRouterIntegration.t.sol @@ -12,7 +12,7 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup { uint256 balancerBefore = IERC20(DAI_ADDR).balanceOf(ALICE); // Encoded solution generated using `test_split_swap_strategy_encoder_no_permit2` (bool success,) = tychoRouterAddr.call( - hex"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000008f1d5c1cae37400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000059005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d01395000100000000000000" + hex"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000008f1d5c1cae37400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000059005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000100000000000000" ); vm.stopPrank(); @@ -37,7 +37,7 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup { IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); // Encoded solution generated using `test_split_encoding_strategy_usv4` (bool success,) = tychoRouterAddr.call( - hex"7c553846000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330000000000000000000000000000000000000000005064ff624d54346285543f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000006824c2ae00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fd3cb6000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041850e1add80e90f19d7b1ac70721b5dec8a6bdcb57999ea957f831ea57c4ce1a116bec18d2cae2559421ead48186b6985176fee7f8d2e3452c1518dc2635224b41c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007900770001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb486982508145454ce325ddbe47a25d4ec3d231193300040000000000000000000000000000000000000000000bb800003c6982508145454ce325ddbe47a25d4ec3d23119330061a80001f400000000000000" + hex"7c553846000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330000000000000000000000000000000000000000005064ff624d54346285543f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe9342000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041c96ca498573c3c283e270700101c963405003b631ce90988c3690248b5cab66a70a1cb074afa6acf671300c917b8d6ac0149ae538c95a67a844175bfa9ae7d811b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d008b0001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb486982508145454ce325ddbe47a25d4ec3d23119330004cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000bb800003c6982508145454ce325ddbe47a25d4ec3d23119330061a80001f400000000000000000000000000000000000000" ); vm.stopPrank(); @@ -60,7 +60,7 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup { // Encoded solution generated using `test_split_encoding_strategy_usv4_eth_in` (bool success,) = tychoRouterAddr.call{value: 1 ether}( - hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d2311933000000000000000000000000000000000000000000c87c939ae635f92dc2379c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006824c2cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fd3cd3000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041a97e156e8c7a48a968efe2f057700ce8458ecfbfb53e0319fc9223b2364aba20227d2ee00226b42e2f28aeb002a242576d75152b270d73a8926f595190828f3d1c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005f005d0001000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d231193301056982508145454ce325ddbe47a25d4ec3d23119330061a80001f400" + hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d2311933000000000000000000000000000000000000000000c87c939ae635f92dc2379c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe934200000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004197c8f24177a14b631dd3a9226c08a0a376fcaf7894364b5131db4415890fc2c57a48bb5497d36a57a4aa359fd6781788c697f6a85500d7bee3e7a1597f0900b81b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007300710001000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330105cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc26982508145454ce325ddbe47a25d4ec3d23119330061a80001f400000000000000000000000000" ); vm.stopPrank(); @@ -87,7 +87,7 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup { // Encoded solution generated using `test_split_encoding_strategy_usv4_eth_out` (bool success,) = tychoRouterAddr.call( - hex"7c55384600000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f81490b4f29aade000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000000000000000000000000000000000006824c2da00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fd3ce20000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000416b224d97fe1a35f2698380969c22854cf7ed92881ea484df7adb438f8d8e78e66c8617131f6712c5f3b4fa07725725081b2ebe27cd44acd11332a4a72bded96c1b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005f005d0001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000040000000000000000000000000000000000000000000bb800003c00" + hex"7c55384600000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f81490b4f29aade000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe9342000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041dbb84c68a4293bcf6303ca45327614667c54226086ddcfa2daa9289c1657da9a57268f4d8ceea3c831d43e5a96b1dc54766bc3fda8845d5c7e266981b9d84c651b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007300710001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000004cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000bb800003c00000000000000000000000000" ); vm.stopPrank(); @@ -109,7 +109,7 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup { vm.startPrank(ALICE); // Encoded solution generated using `test_split_swap_strategy_encoder_wrap` (bool success,) = tychoRouterAddr.call{value: 1 ether}( - hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000903146e5f6c59c064b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006821640400000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9de0c000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041b34e1f3d4e78942b2429b776073a5dfab1420f763de7d7e2a2296ca8abf684f923f7ae7945e824d8a084b9610d33ed49246a36e8e0efbce8ae210b0474f9fe3a1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000059005700020000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000" + hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000903146e5f6c59c064b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000068261ff900000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe9a01000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041eaba97110bc7c3586bf8fa3d3d2c24a3863e84d2e1688689e325e750f860802d745309e3dc818fe029f439c14a52d9a3f48f2873733259c342eb01bdf8ac896b1c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000059005700020000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000" ); vm.stopPrank(); @@ -131,7 +131,7 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup { IERC20(DAI_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); // Encoded solution generated using `test_split_swap_strategy_encoder_unwrap` (bool success,) = tychoRouterAddr.call( - hex"7c5538460000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000a2a15d09519be00000000000000000000000000000000000000000000000000000000000006821641200000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9de1a00000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004181d23336d0cacd47a4d228590a825a1d92a48378cd481ff308b6d235e14b925c584f31e420682879bea58363ca4aa44a3b79557b15a9f73078a4696e00f55f911b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000059005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fa478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d01395010200000000000000" + hex"7c5538460000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000a2a15d09519be00000000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe93420000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000413c401d4a22c3e0b693b4f9d0807f6107ab6b6d6b716a45978ba175af6e717ae617d4c13b8603db25ee6902b807ee049588ce27030bf3f60833bf26e9561f560c1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000059005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fa478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d01395010200000000000000" ); vm.stopPrank(); @@ -159,7 +159,7 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup { vm.startPrank(ALICE); // Encoded solution generated using `test_split_encoding_strategy_ekubo` (bool success,) = address(tychoRouter).call{value: 1 ether}( - hex"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000078007600010000003d7ebc40af7092e3f1c81f2e996cba5cae2090d705a4ad4f68d0b91cfd19687c881e50f3a00242828c0000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4851d02a5948496a67827242eabc5725531342527c0000000000000000000000000000000000000000" + hex"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000078007600010000003d7ebc40af7092e3f1c81f2e996cba5cae2090d705cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4851d02a5948496a67827242eabc5725531342527c0000000000000000000000000000000000000000" ); uint256 balancerAfter = IERC20(USDC_ADDR).balanceOf(ALICE); @@ -181,9 +181,9 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); IERC20(WETH_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); - // Encoded solution generated using `test_split_swap_strategy_encoder_complex` + // Encoded solution generated using `test_split_swap_strategy_encoder_complex_route` (bool success,) = tychoRouterAddr.call( - hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006821643700000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9de3f00000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004112f41a590796702b322fa5a9ee1602daef9b22d732e4fd8f122f072b65dda325271f630759db500db8a42bd4f41ddc18ddda63650deaf36228dca702e28eefd31b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164005700028000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d013950002005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d013950002005702030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fae461ca67b15dc8dc81ce7615e0320da1a9ab8d53ede3eca2a72b3aecc820e955b36f38437d013950100005701030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a4163ede3eca2a72b3aecc820e955b36f38437d01395010000000000000000000000000000000000000000000000000000000000" + hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe9342000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041d137d0776bc16ff9c49bfd3e96103ceb6926654f314489cafcf5a64ab7a9c4f2061ed5ffdef67c33c3c5b78036d28d9eb73da156a0e68d8740235be50e88a3481b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164005700028000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d013950002005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d013950002005702030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fae461ca67b15dc8dc81ce7615e0320da1a9ab8d5cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20100005701030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2010000000000000000000000000000000000000000000000000000000000" ); vm.stopPrank(); @@ -210,7 +210,7 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup { IERC20(WETH_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); // Encoded solution generated using `test_sequential_swap_strategy_encoder_complex_route` (bool success,) = tychoRouterAddr.call( - hex"51bcc7b60000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006821644a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9de5200000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041530bdcde0c687eacb51a339f30c7b3eff7c078a3bbd4bc852519568dcdf271bb4c6ac05583f32c4a8d1a99be3a2817fe86c15ad2a06c5cf938bde9c22bc80f301c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d01395000200525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a4163ede3eca2a72b3aecc820e955b36f38437d013950100000000000000000000000000000000000000000000000000" + hex"51bcc7b60000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe934200000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041d137d0776bc16ff9c49bfd3e96103ceb6926654f314489cafcf5a64ab7a9c4f2061ed5ffdef67c33c3c5b78036d28d9eb73da156a0e68d8740235be50e88a3481b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d01395000200525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20100000000000000000000000000000000000000000000000000" ); vm.stopPrank(); @@ -234,7 +234,7 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup { IERC20(WETH_ADDR).approve(tychoRouterAddr, type(uint256).max); // Encoded solution generated using `test_sequential_swap_strategy_encoder_no_permit2` (bool success,) = tychoRouterAddr.call( - hex"e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d01395000100525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a4163ede3eca2a72b3aecc820e955b36f38437d013950100000000000000000000000000000000000000000000000000" + hex"e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d01395000100525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20100000000000000000000000000000000000000000000000000" ); vm.stopPrank(); @@ -252,9 +252,9 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup { // Approve permit2 vm.startPrank(ALICE); IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); - // Encoded solution generated using `test_cyclic_sequential_swap` + // Encoded solution generated using `test_cyclic_sequential_swap_split_strategy` (bool success,) = tychoRouterAddr.call( - hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f4308e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006821647000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9de780000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000413c8b048dc7b7614106a5aa1fa13e48c02a6a9714dfa07d2c424f68b81a5f828c39ace62f2dd57d7bfad10910ae44f77d68aec5c079fce456028b1bd7f72053151c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0006e00010000002e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400102006e01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d80000" + hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f4308e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe934200000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004194fc497ac440b520981d23b4713425da21dc1c801e657d218a917b5c51339a660b9a5fe0a346cb0aacc0d67ebf03f8fa3ec9fade437ef1b08ea837b2442931b61b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0006e00010000002e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400102006e01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc28ad599c3a0ff1de082011efddc58f1908eb6e6d80000" ); assertTrue(success, "Call Failed"); @@ -271,7 +271,7 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup { IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); // Encoded solution generated using `test_split_input_cyclic_swap` (bool success,) = tychoRouterAddr.call( - hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005ef619b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006821659d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9dfa5000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041dd84c5cdc51719e377598eccd8eac0aae036e7e0745a7c65b5d44cc817071a7460ccc73934363f33cc7af71dc07545aeff1d92f8c2f0b2973e1fc37e7b2de3551c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139006e00019999992e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400102006e00010000002e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d80102005701000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2b4e16d0168e52d35cacd2c6185b44281ec28c9dc3ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000" + hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005ef619b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe934200000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004194fc497ac440b520981d23b4713425da21dc1c801e657d218a917b5c51339a660b9a5fe0a346cb0aacc0d67ebf03f8fa3ec9fade437ef1b08ea837b2442931b61b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139006e00019999992e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400102006e00010000002e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d80102005701000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2b4e16d0168e52d35cacd2c6185b44281ec28c9dccd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000" ); assertTrue(success, "Call Failed"); @@ -288,7 +288,7 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup { IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); // Encoded solution generated using `test_split_output_cyclic_swap` (bool success,) = tychoRouterAddr.call( - hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005eea514000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000682165ac00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9dfb400000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004107f2b0f9c2e4e308ab43b288d69de30d84b10c8075e4dd9a2cf66594f97a52fb34de2534b89bf1887da74c92fd03464f45baff700dd32e213e3add1a3f351e891b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48b4e16d0168e52d35cacd2c6185b44281ec28c9dc3ede3eca2a72b3aecc820e955b36f38437d013950102006e01009999992e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400000006e01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d8000000000000000000" + hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005eea514000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe934200000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004194fc497ac440b520981d23b4713425da21dc1c801e657d218a917b5c51339a660b9a5fe0a346cb0aacc0d67ebf03f8fa3ec9fade437ef1b08ea837b2442931b61b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48b4e16d0168e52d35cacd2c6185b44281ec28c9dc3ede3eca2a72b3aecc820e955b36f38437d013950102006e01009999992e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480001f4cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc288e6a0c2ddd26feeb64f039a2c41296fcb3f56400000006e01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb8cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc28ad599c3a0ff1de082011efddc58f1908eb6e6d8000000000000000000" ); assertTrue(success, "Call Failed"); @@ -304,7 +304,7 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup { IERC20(UWU_ADDR).approve(tychoRouterAddr, type(uint256).max); // Encoded solution generated using `test_split_encoding_strategy_curve` (bool success,) = tychoRouterAddr.call( - hex"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000055c08ca52497e2f1534b59e2917bf524d4765257000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000005c005a00010000001d1499e622d69689cdf9004d05ec547d650ff21155c08ca52497e2f1534b59e2917bf524d4765257c02aaa39b223fe8d0a0e5c4f27ead9083c756cc277146b0a1d08b6844376df6d9da99ba7f1b19e71020100010300000000" + hex"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000055c08ca52497e2f1534b59e2917bf524d4765257000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000070006e00010000001d1499e622d69689cdf9004d05ec547d650ff21155c08ca52497e2f1534b59e2917bf524d4765257c02aaa39b223fe8d0a0e5c4f27ead9083c756cc277146b0a1d08b6844376df6d9da99ba7f1b19e710201000103cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000" ); assertTrue(success, "Call Failed"); @@ -312,19 +312,4 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup { vm.stopPrank(); } - - function testSplitCurveIntegrationStETH() public { - deal(ALICE, 1 ether); - - vm.startPrank(ALICE); - // Encoded solution generated using `test_split_encoding_strategy_curve_st_eth` - (bool success,) = tychoRouterAddr.call{value: 1 ether}( - hex"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe840000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000005c005a00010000001d1499e622d69689cdf9004d05ec547d650ff211eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeae7ab96520de3a18e5e111b5eaab095312d7fe84dc24316b9ae028f1497c275eb9192a3ea0f67022010001000500000000" - ); - - assertTrue(success, "Call Failed"); - assertEq(IERC20(STETH_ADDR).balanceOf(ALICE), 1000754689941529590); - - vm.stopPrank(); - } } diff --git a/foundry/test/TychoRouterSequentialSwap.t.sol b/foundry/test/TychoRouterSequentialSwap.t.sol index 9efd39b..9e35c6f 100644 --- a/foundry/test/TychoRouterSequentialSwap.t.sol +++ b/foundry/test/TychoRouterSequentialSwap.t.sol @@ -36,7 +36,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { encodeUniswapV2Swap( DAI_ADDR, DAI_USDC_POOL, - tychoRouterAddr, + ALICE, true, TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL ) @@ -44,22 +44,6 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { return swaps; } - function testSequentialSwapInternalMethod() public { - // Trade 1 WETH for USDC through DAI - see _getSequentialSwaps for more info - uint256 amountIn = 1 ether; - deal(WETH_ADDR, ALICE, amountIn); - vm.startPrank(ALICE); - IERC20(WETH_ADDR).approve(tychoRouterAddr, amountIn); - - bytes[] memory swaps = _getSequentialSwaps(false); - tychoRouter.exposedSequentialSwap(amountIn, pleEncode(swaps)); - vm.stopPrank(); - - uint256 usdcBalance = IERC20(USDC_ADDR).balanceOf(tychoRouterAddr); - assertEq(usdcBalance, 2644659787); - assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); - } - function testSequentialSwapPermit2() public { // Trade 1 WETH for USDC through DAI - see _getSequentialSwaps for more info uint256 amountIn = 1 ether; @@ -232,7 +216,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { encodeUniswapV2Swap( DAI_ADDR, DAI_USDC_POOL, - tychoRouterAddr, + ALICE, true, TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL ) diff --git a/foundry/test/TychoRouterSingleSwap.t.sol b/foundry/test/TychoRouterSingleSwap.t.sol index 8a8a4d3..f2fba1b 100644 --- a/foundry/test/TychoRouterSingleSwap.t.sol +++ b/foundry/test/TychoRouterSingleSwap.t.sol @@ -24,7 +24,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { bytes memory protocolData = encodeUniswapV2Swap( WETH_ADDR, WETH_DAI_POOL, - tychoRouterAddr, + ALICE, false, TokenTransfer.TransferType.TRANSFER_PERMIT2_TO_PROTOCOL ); @@ -65,7 +65,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { bytes memory protocolData = encodeUniswapV2Swap( WETH_ADDR, WETH_DAI_POOL, - tychoRouterAddr, + ALICE, false, TokenTransfer.TransferType.TRANSFER_FROM_TO_PROTOCOL ); @@ -106,7 +106,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { bytes memory protocolData = encodeUniswapV2Swap( WETH_ADDR, WETH_DAI_POOL, - tychoRouterAddr, + ALICE, false, TokenTransfer.TransferType.TRANSFER_FROM_TO_PROTOCOL ); @@ -132,7 +132,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { bytes memory protocolData = encodeUniswapV2Swap( WETH_ADDR, WETH_DAI_POOL, - tychoRouterAddr, + ALICE, false, TokenTransfer.TransferType.TRANSFER_FROM_TO_PROTOCOL ); @@ -167,7 +167,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { bytes memory protocolData = encodeUniswapV2Swap( WETH_ADDR, WETH_DAI_POOL, - tychoRouterAddr, + ALICE, false, TokenTransfer.TransferType.TRANSFER_FROM_TO_PROTOCOL ); @@ -216,7 +216,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { bytes memory protocolData = encodeUniswapV2Swap( WETH_ADDR, WETH_DAI_POOL, - tychoRouterAddr, + ALICE, false, TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL ); @@ -296,7 +296,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { IERC20(WETH_ADDR).approve(tychoRouterAddr, type(uint256).max); // Encoded solution generated using `test_single_swap_strategy_encoder_no_permit2` (bool success,) = tychoRouterAddr.call( - hex"20144a070000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000008f1d5c1cae3740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d0139500010000000000000000000000000000" + hex"20144a070000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000008f1d5c1cae3740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200010000000000000000000000000000" ); vm.stopPrank(); @@ -315,7 +315,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { IERC20(WETH_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); // Encoded solution generated using `test_single_swap_strategy_encoder` (bool success,) = tychoRouterAddr.call( - hex"30ace1b10000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000903146e5f6c59c064b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000682169c100000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9e3c900000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000412d3f0fee3fc61987512f024f20b1448eb934f82105a91653dd169179c693aaf95d09ef666ce1d38be70b8156fa6e4ea3e8717204e02fe7ba99a1fc4e5a26e6e11b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d0139500020000000000000000000000000000" + hex"30ace1b10000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000903146e5f6c59c064b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006826193a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fe934200000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041d137d0776bc16ff9c49bfd3e96103ceb6926654f314489cafcf5a64ab7a9c4f2061ed5ffdef67c33c3c5b78036d28d9eb73da156a0e68d8740235be50e88a3481b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb11cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200020000000000000000000000000000" ); vm.stopPrank(); diff --git a/foundry/test/TychoRouterSplitSwap.t.sol b/foundry/test/TychoRouterSplitSwap.t.sol index 00f8406..46817c4 100644 --- a/foundry/test/TychoRouterSplitSwap.t.sol +++ b/foundry/test/TychoRouterSplitSwap.t.sol @@ -47,7 +47,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { encodeUniswapV2Swap( WBTC_ADDR, USDC_WBTC_POOL, - tychoRouterAddr, + ALICE, true, TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL ) @@ -72,7 +72,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { encodeUniswapV2Swap( DAI_ADDR, DAI_USDC_POOL, - tychoRouterAddr, + ALICE, true, TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL ) @@ -92,7 +92,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { tychoRouter.exposedSplitSwap(amountIn, 4, pleEncode(swaps)); vm.stopPrank(); - uint256 usdcBalance = IERC20(USDC_ADDR).balanceOf(tychoRouterAddr); + uint256 usdcBalance = IERC20(USDC_ADDR).balanceOf(ALICE); assertEq(usdcBalance, 2615491639); assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); } @@ -136,7 +136,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { deal(WETH_ADDR, ALICE, amountIn); vm.startPrank(ALICE); - IERC20(WETH_ADDR).approve(address(tychoRouterAddr), amountIn); + IERC20(WETH_ADDR).approve(tychoRouterAddr, amountIn); bytes[] memory swaps = _getSplitSwaps(false); @@ -154,7 +154,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { uint256 usdcBalance = IERC20(USDC_ADDR).balanceOf(ALICE); assertEq(usdcBalance, 2615491639); - assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); + assertEq(IERC20(WETH_ADDR).balanceOf(ALICE), 0); } function testSplitSwapUndefinedMinAmount() public { @@ -268,7 +268,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { bytes memory protocolData = encodeUniswapV2Swap( WETH_ADDR, WETH_DAI_POOL, - tychoRouterAddr, + ALICE, false, TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL ); @@ -367,7 +367,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { bytes memory protocolData = encodeUniswapV3Swap( WETH_ADDR, DAI_ADDR, - tychoRouterAddr, + ALICE, DAI_WETH_USV3, zeroForOne, TokenTransfer.TransferType.TRANSFER_PERMIT2_TO_PROTOCOL @@ -428,6 +428,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { USDT_ADDR, true, TokenTransfer.TransferType.TRANSFER_PERMIT2_TO_ROUTER, + ALICE, pools ); @@ -476,7 +477,12 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { }); bytes memory protocolData = UniswapV4Utils.encodeExactInput( - USDE_ADDR, WBTC_ADDR, true, TokenTransfer.TransferType.NONE, pools + USDE_ADDR, + WBTC_ADDR, + true, + TokenTransfer.TransferType.NONE, + ALICE, + pools ); bytes memory swap = encodeSplitSwap( @@ -488,7 +494,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { tychoRouter.exposedSplitSwap(amountIn, 2, pleEncode(swaps)); - assertEq(IERC20(WBTC_ADDR).balanceOf(tychoRouterAddr), 102718); + assertEq(IERC20(WBTC_ADDR).balanceOf(ALICE), 102718); } function testSplitInputCyclicSwapInternalMethod() public { diff --git a/foundry/test/executors/CurveExecutor.t.sol b/foundry/test/executors/CurveExecutor.t.sol index a49a2dc..278413c 100644 --- a/foundry/test/executors/CurveExecutor.t.sol +++ b/foundry/test/executors/CurveExecutor.t.sol @@ -37,7 +37,8 @@ contract CurveExecutorExposed is CurveExecutor { int128 i, int128 j, bool tokenApprovalNeeded, - TokenTransfer.TransferType transferType + TokenTransfer.TransferType transferType, + address receiver ) { return _decodeData(data); @@ -67,7 +68,8 @@ contract CurveExecutorTest is Test, Constants { uint8(2), uint8(0), true, - TokenTransfer.TransferType.NONE + TokenTransfer.TransferType.NONE, + ALICE ); ( @@ -78,7 +80,8 @@ contract CurveExecutorTest is Test, Constants { int128 i, int128 j, bool tokenApprovalNeeded, - TokenTransfer.TransferType transferType + TokenTransfer.TransferType transferType, + address receiver ) = curveExecutorExposed.decodeData(data); assertEq(tokenIn, WETH_ADDR); @@ -89,6 +92,7 @@ contract CurveExecutorTest is Test, Constants { assertEq(j, 0); assertEq(tokenApprovalNeeded, true); assertEq(uint8(transferType), uint8(TokenTransfer.TransferType.NONE)); + assertEq(receiver, ALICE); } function testTriPool() public { @@ -96,15 +100,12 @@ contract CurveExecutorTest is Test, Constants { uint256 amountIn = 1 ether; deal(DAI_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = _getData(DAI_ADDR, USDC_ADDR, TRIPOOL, 1); + bytes memory data = _getData(DAI_ADDR, USDC_ADDR, TRIPOOL, 1, ALICE); uint256 amountOut = curveExecutorExposed.swap(amountIn, data); assertEq(amountOut, 999797); - assertEq( - IERC20(USDC_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); + assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), amountOut); } function testStEthPool() public { @@ -113,14 +114,14 @@ contract CurveExecutorTest is Test, Constants { deal(address(curveExecutorExposed), amountIn); bytes memory data = - _getData(ETH_ADDR_FOR_CURVE, STETH_ADDR, STETH_POOL, 1); + _getData(ETH_ADDR_FOR_CURVE, STETH_ADDR, STETH_POOL, 1, ALICE); uint256 amountOut = curveExecutorExposed.swap(amountIn, data); assertEq(amountOut, 1001072414418410897); assertEq( - IERC20(STETH_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut + IERC20(STETH_ADDR).balanceOf(ALICE), + amountOut - 1 // there is something weird in this pool, but won't investigate for now because we don't currently support it in the simulation ); } @@ -129,15 +130,13 @@ contract CurveExecutorTest is Test, Constants { uint256 amountIn = 1 ether; deal(WETH_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = _getData(WETH_ADDR, WBTC_ADDR, TRICRYPTO2_POOL, 3); + bytes memory data = + _getData(WETH_ADDR, WBTC_ADDR, TRICRYPTO2_POOL, 3, ALICE); uint256 amountOut = curveExecutorExposed.swap(amountIn, data); assertEq(amountOut, 2279618); - assertEq( - IERC20(WBTC_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); + assertEq(IERC20(WBTC_ADDR).balanceOf(ALICE), amountOut); } function testSUSDPool() public { @@ -145,15 +144,12 @@ contract CurveExecutorTest is Test, Constants { uint256 amountIn = 100 * 10 ** 6; deal(USDC_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = _getData(USDC_ADDR, SUSD_ADDR, SUSD_POOL, 1); + bytes memory data = _getData(USDC_ADDR, SUSD_ADDR, SUSD_POOL, 1, ALICE); uint256 amountOut = curveExecutorExposed.swap(amountIn, data); assertEq(amountOut, 100488101605550214590); - assertEq( - IERC20(SUSD_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); + assertEq(IERC20(SUSD_ADDR).balanceOf(ALICE), amountOut); } function testFraxUsdcPool() public { @@ -161,15 +157,13 @@ contract CurveExecutorTest is Test, Constants { uint256 amountIn = 1 ether; deal(FRAX_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = _getData(FRAX_ADDR, USDC_ADDR, FRAX_USDC_POOL, 1); + bytes memory data = + _getData(FRAX_ADDR, USDC_ADDR, FRAX_USDC_POOL, 1, ALICE); uint256 amountOut = curveExecutorExposed.swap(amountIn, data); assertEq(amountOut, 998097); - assertEq( - IERC20(USDC_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); + assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), amountOut); } function testUsdeUsdcPool() public { @@ -177,15 +171,13 @@ contract CurveExecutorTest is Test, Constants { uint256 amountIn = 100 * 10 ** 6; deal(USDC_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = _getData(USDC_ADDR, USDE_ADDR, USDE_USDC_POOL, 1); + bytes memory data = + _getData(USDC_ADDR, USDE_ADDR, USDE_USDC_POOL, 1, ALICE); uint256 amountOut = curveExecutorExposed.swap(amountIn, data); assertEq(amountOut, 100064812138999986170); - assertEq( - IERC20(USDE_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); + assertEq(IERC20(USDE_ADDR).balanceOf(ALICE), amountOut); } function testDolaFraxPyusdPool() public { @@ -194,32 +186,27 @@ contract CurveExecutorTest is Test, Constants { deal(DOLA_ADDR, address(curveExecutorExposed), amountIn); bytes memory data = - _getData(DOLA_ADDR, FRAXPYUSD_POOL, DOLA_FRAXPYUSD_POOL, 1); + _getData(DOLA_ADDR, FRAXPYUSD_POOL, DOLA_FRAXPYUSD_POOL, 1, ALICE); uint256 amountOut = curveExecutorExposed.swap(amountIn, data); assertEq(amountOut, 99688992); - assertEq( - IERC20(FRAXPYUSD_POOL).balanceOf(address(curveExecutorExposed)), - amountOut - ); + assertEq(IERC20(FRAXPYUSD_POOL).balanceOf(ALICE), amountOut); } function testCryptoPoolWithETH() public { // Swapping XYO -> ETH on a CryptoPool, deployed by factory 0xF18056Bbd320E96A48e3Fbf8bC061322531aac99 uint256 amountIn = 1 ether; - uint256 initialBalance = address(curveExecutorExposed).balance; // this address already has some ETH assigned to it + uint256 initialBalance = address(ALICE).balance; // this address already has some ETH assigned to it deal(XYO_ADDR, address(curveExecutorExposed), amountIn); bytes memory data = - _getData(XYO_ADDR, ETH_ADDR_FOR_CURVE, ETH_XYO_POOL, 2); + _getData(XYO_ADDR, ETH_ADDR_FOR_CURVE, ETH_XYO_POOL, 2, ALICE); uint256 amountOut = curveExecutorExposed.swap(amountIn, data); assertEq(amountOut, 6081816039338); - assertEq( - address(curveExecutorExposed).balance, initialBalance + amountOut - ); + assertEq(ALICE.balance, initialBalance + amountOut); } function testCryptoPool() public { @@ -227,15 +214,13 @@ contract CurveExecutorTest is Test, Constants { uint256 amountIn = 1000 ether; deal(BSGG_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = _getData(BSGG_ADDR, USDT_ADDR, BSGG_USDT_POOL, 2); + bytes memory data = + _getData(BSGG_ADDR, USDT_ADDR, BSGG_USDT_POOL, 2, ALICE); uint256 amountOut = curveExecutorExposed.swap(amountIn, data); assertEq(amountOut, 23429); - assertEq( - IERC20(USDT_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); + assertEq(IERC20(USDT_ADDR).balanceOf(ALICE), amountOut); } function testTricryptoPool() public { @@ -243,15 +228,13 @@ contract CurveExecutorTest is Test, Constants { uint256 amountIn = 1 ether; deal(WETH_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = _getData(WETH_ADDR, USDC_ADDR, TRICRYPTO_POOL, 2); + bytes memory data = + _getData(WETH_ADDR, USDC_ADDR, TRICRYPTO_POOL, 2, ALICE); uint256 amountOut = curveExecutorExposed.swap(amountIn, data); assertEq(amountOut, 1861130974); - assertEq( - IERC20(USDC_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); + assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), amountOut); } function testTwoCryptoPool() public { @@ -259,15 +242,13 @@ contract CurveExecutorTest is Test, Constants { uint256 amountIn = 1 ether; deal(UWU_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = _getData(UWU_ADDR, WETH_ADDR, UWU_WETH_POOL, 2); + bytes memory data = + _getData(UWU_ADDR, WETH_ADDR, UWU_WETH_POOL, 2, ALICE); uint256 amountOut = curveExecutorExposed.swap(amountIn, data); assertEq(amountOut, 2873786684675); - assertEq( - IERC20(WETH_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); + assertEq(IERC20(WETH_ADDR).balanceOf(ALICE), amountOut); } function testStableSwapPool() public { @@ -276,15 +257,12 @@ contract CurveExecutorTest is Test, Constants { deal(CRVUSD_ADDR, address(curveExecutorExposed), amountIn); bytes memory data = - _getData(CRVUSD_ADDR, USDT_ADDR, CRVUSD_USDT_POOL, 1); + _getData(CRVUSD_ADDR, USDT_ADDR, CRVUSD_USDT_POOL, 1, ALICE); uint256 amountOut = curveExecutorExposed.swap(amountIn, data); assertEq(amountOut, 999910); - assertEq( - IERC20(USDT_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); + assertEq(IERC20(USDT_ADDR).balanceOf(ALICE), amountOut); } function testMetaPool() public { @@ -293,22 +271,20 @@ contract CurveExecutorTest is Test, Constants { deal(WTAO_ADDR, address(curveExecutorExposed), amountIn); bytes memory data = - _getData(WTAO_ADDR, WSTTAO_ADDR, WSTTAO_WTAO_POOL, 1); + _getData(WTAO_ADDR, WSTTAO_ADDR, WSTTAO_WTAO_POOL, 1, ALICE); uint256 amountOut = curveExecutorExposed.swap(amountIn, data); assertEq(amountOut, 32797923610); - assertEq( - IERC20(WSTTAO_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); + assertEq(IERC20(WSTTAO_ADDR).balanceOf(ALICE), amountOut); } function _getData( address tokenIn, address tokenOut, address pool, - uint8 poolType + uint8 poolType, + address receiver ) internal view returns (bytes memory data) { (int128 i, int128 j) = _getIndexes(tokenIn, tokenOut, pool); data = abi.encodePacked( @@ -319,7 +295,8 @@ contract CurveExecutorTest is Test, Constants { uint8(uint256(uint128(i))), uint8(uint256(uint128(j))), true, - TokenTransfer.TransferType.NONE + TokenTransfer.TransferType.NONE, + receiver ); } diff --git a/foundry/test/executors/UniswapV4Executor.t.sol b/foundry/test/executors/UniswapV4Executor.t.sol index 62f61c9..9ff7f72 100644 --- a/foundry/test/executors/UniswapV4Executor.t.sol +++ b/foundry/test/executors/UniswapV4Executor.t.sol @@ -22,6 +22,7 @@ contract UniswapV4ExecutorExposed is UniswapV4Executor { address tokenOut, bool zeroForOne, TokenTransfer.TransferType transferType, + address receiver, UniswapV4Pool[] memory pools ) { @@ -68,7 +69,7 @@ contract UniswapV4ExecutorTest is Test, Constants { }); bytes memory data = UniswapV4Utils.encodeExactInput( - USDE_ADDR, USDT_ADDR, zeroForOne, transferType, pools + USDE_ADDR, USDT_ADDR, zeroForOne, transferType, ALICE, pools ); ( @@ -76,6 +77,7 @@ contract UniswapV4ExecutorTest is Test, Constants { address tokenOut, bool zeroForOneDecoded, TokenTransfer.TransferType transferTypeDecoded, + address receiver, UniswapV4Executor.UniswapV4Pool[] memory decodedPools ) = uniswapV4Exposed.decodeData(data); @@ -83,6 +85,7 @@ contract UniswapV4ExecutorTest is Test, Constants { assertEq(tokenOut, USDT_ADDR); assertEq(zeroForOneDecoded, zeroForOne); assertEq(uint8(transferTypeDecoded), uint8(transferType)); + assertEq(receiver, ALICE); assertEq(decodedPools.length, 2); assertEq(decodedPools[0].intermediaryToken, USDT_ADDR); assertEq(decodedPools[0].fee, pool1Fee); @@ -108,7 +111,12 @@ contract UniswapV4ExecutorTest is Test, Constants { }); bytes memory data = UniswapV4Utils.encodeExactInput( - USDE_ADDR, USDT_ADDR, true, TokenTransfer.TransferType.NONE, pools + USDE_ADDR, + USDT_ADDR, + true, + TokenTransfer.TransferType.NONE, + ALICE, + pools ); uint256 amountOut = uniswapV4Exposed.swap(amountIn, data); @@ -117,14 +125,14 @@ contract UniswapV4ExecutorTest is Test, Constants { USDE.balanceOf(address(uniswapV4Exposed)), usdeBalanceBeforeSwapExecutor - amountIn ); - assertTrue(USDT.balanceOf(address(uniswapV4Exposed)) == amountOut); + assertTrue(USDT.balanceOf(ALICE) == amountOut); } function testSingleSwapIntegration() public { // USDE -> USDT // Generated by the Tycho swap encoder - test_encode_uniswap_v4_simple_swap bytes memory protocolData = - hex"4c9edd5852cd905f086c759e8383e09bff1e68b3dac17f958d2ee523a2206206994597c13d831ec70100dac17f958d2ee523a2206206994597c13d831ec7000064000001"; + hex"4c9edd5852cd905f086c759e8383e09bff1e68b3dac17f958d2ee523a2206206994597c13d831ec70100cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2dac17f958d2ee523a2206206994597c13d831ec7000064000001"; uint256 amountIn = 100 ether; deal(USDE_ADDR, address(uniswapV4Exposed), amountIn); uint256 usdeBalanceBeforePool = USDE.balanceOf(poolManager); @@ -134,10 +142,9 @@ contract UniswapV4ExecutorTest is Test, Constants { uint256 amountOut = uniswapV4Exposed.swap(amountIn, protocolData); assertEq(USDE.balanceOf(poolManager), usdeBalanceBeforePool + amountIn); assertEq( - USDE.balanceOf(address(uniswapV4Exposed)), - usdeBalanceBeforeSwapExecutor - amountIn + USDE.balanceOf(ALICE), usdeBalanceBeforeSwapExecutor - amountIn ); - assertTrue(USDT.balanceOf(address(uniswapV4Exposed)) == amountOut); + assertTrue(USDT.balanceOf(ALICE) == amountOut); } function testMultipleSwap() public { @@ -162,7 +169,12 @@ contract UniswapV4ExecutorTest is Test, Constants { }); bytes memory data = UniswapV4Utils.encodeExactInput( - USDE_ADDR, WBTC_ADDR, true, TokenTransfer.TransferType.NONE, pools + USDE_ADDR, + WBTC_ADDR, + true, + TokenTransfer.TransferType.NONE, + ALICE, + pools ); uint256 amountOut = uniswapV4Exposed.swap(amountIn, data); @@ -171,9 +183,7 @@ contract UniswapV4ExecutorTest is Test, Constants { USDE.balanceOf(address(uniswapV4Exposed)), usdeBalanceBeforeSwapExecutor - amountIn ); - assertTrue( - IERC20(WBTC_ADDR).balanceOf(address(uniswapV4Exposed)) == amountOut - ); + assertTrue(IERC20(WBTC_ADDR).balanceOf(ALICE) == amountOut); } function testMultipleSwapIntegration() public { @@ -181,7 +191,7 @@ contract UniswapV4ExecutorTest is Test, Constants { // Generated by the Tycho swap encoder - test_encode_uniswap_v4_sequential_swap bytes memory protocolData = - hex"4c9edd5852cd905f086c759e8383e09bff1e68b32260fac5e5542a773aa44fbcfedf7c193bc2c5990100dac17f958d2ee523a2206206994597c13d831ec70000640000012260fac5e5542a773aa44fbcfedf7c193bc2c599000bb800003c"; + hex"4c9edd5852cd905f086c759e8383e09bff1e68b32260fac5e5542a773aa44fbcfedf7c193bc2c5990100cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2dac17f958d2ee523a2206206994597c13d831ec70000640000012260fac5e5542a773aa44fbcfedf7c193bc2c599000bb800003c"; uint256 amountIn = 100 ether; deal(USDE_ADDR, address(uniswapV4Exposed), amountIn); @@ -195,8 +205,6 @@ contract UniswapV4ExecutorTest is Test, Constants { USDE.balanceOf(address(uniswapV4Exposed)), usdeBalanceBeforeSwapExecutor - amountIn ); - assertTrue( - IERC20(WBTC_ADDR).balanceOf(address(uniswapV4Exposed)) == amountOut - ); + assertTrue(IERC20(WBTC_ADDR).balanceOf(ALICE) == amountOut); } } diff --git a/foundry/test/executors/UniswapV4Utils.sol b/foundry/test/executors/UniswapV4Utils.sol index 1ccc29c..c96465c 100644 --- a/foundry/test/executors/UniswapV4Utils.sol +++ b/foundry/test/executors/UniswapV4Utils.sol @@ -9,6 +9,7 @@ library UniswapV4Utils { address tokenOut, bool zeroForOne, UniswapV4Executor.TransferType transferType, + address receiver, UniswapV4Executor.UniswapV4Pool[] memory pools ) public pure returns (bytes memory) { bytes memory encodedPools; @@ -23,7 +24,7 @@ library UniswapV4Utils { } return abi.encodePacked( - tokenIn, tokenOut, zeroForOne, transferType, encodedPools + tokenIn, tokenOut, zeroForOne, transferType, receiver, encodedPools ); } } diff --git a/src/encoding/evm/strategy_encoder/strategy_encoders.rs b/src/encoding/evm/strategy_encoder/strategy_encoders.rs index 2536812..45a83d8 100644 --- a/src/encoding/evm/strategy_encoder/strategy_encoders.rs +++ b/src/encoding/evm/strategy_encoder/strategy_encoders.rs @@ -111,16 +111,19 @@ impl StrategyEncoder for SingleSwapStrategyEncoder { NativeAction::Unwrap => unwrap = true, } } - + let protocol = grouped_swap.protocol_system.clone(); let swap_encoder = self - .get_swap_encoder(&grouped_swap.protocol_system) + .get_swap_encoder(&protocol) .ok_or_else(|| { EncodingError::InvalidInput(format!( "Swap encoder not found for protocol: {}", - grouped_swap.protocol_system + protocol )) })?; + let swap_receiver = + if !unwrap { solution.receiver.clone() } else { self.router_address.clone() }; + let mut grouped_protocol_data: Vec = vec![]; for swap in grouped_swap.swaps.iter() { let transfer_type = self.get_transfer_type( @@ -133,7 +136,7 @@ impl StrategyEncoder for SingleSwapStrategyEncoder { ); let encoding_context = EncodingContext { - receiver: self.router_address.clone(), + receiver: swap_receiver.clone(), exact_out: solution.exact_out, router_address: Some(self.router_address.clone()), group_token_in: grouped_swap.input_token.clone(), @@ -286,16 +289,25 @@ impl StrategyEncoder for SequentialSwapStrategyEncoder { } let mut swaps = vec![]; - for grouped_swap in grouped_swaps.iter() { + for (i, grouped_swap) in grouped_swaps.iter().enumerate() { + let protocol = grouped_swap.protocol_system.clone(); let swap_encoder = self - .get_swap_encoder(&grouped_swap.protocol_system) + .get_swap_encoder(&protocol) .ok_or_else(|| { EncodingError::InvalidInput(format!( "Swap encoder not found for protocol: {}", - grouped_swap.protocol_system + protocol )) })?; + // if it is the last swap and there isn't an unwrap at the end, we can set the receiver + // to the final user + let swap_receiver = if i == grouped_swaps.len() - 1 && !unwrap { + solution.receiver.clone() + } else { + self.router_address.clone() + }; + let mut grouped_protocol_data: Vec = vec![]; for swap in grouped_swap.swaps.iter() { let transfer_type = self.get_transfer_type( @@ -308,7 +320,7 @@ impl StrategyEncoder for SequentialSwapStrategyEncoder { ); let encoding_context = EncodingContext { - receiver: self.router_address.clone(), + receiver: swap_receiver.clone(), exact_out: solution.exact_out, router_address: Some(self.router_address.clone()), group_token_in: grouped_swap.input_token.clone(), @@ -516,15 +528,22 @@ impl StrategyEncoder for SplitSwapStrategyEncoder { let mut swaps = vec![]; for grouped_swap in grouped_swaps.iter() { + let protocol = grouped_swap.protocol_system.clone(); let swap_encoder = self - .get_swap_encoder(&grouped_swap.protocol_system) + .get_swap_encoder(&protocol) .ok_or_else(|| { EncodingError::InvalidInput(format!( "Swap encoder not found for protocol: {}", - grouped_swap.protocol_system + protocol )) })?; + let swap_receiver = if !unwrap && grouped_swap.output_token == solution.checked_token { + solution.receiver.clone() + } else { + self.router_address.clone() + }; + let mut grouped_protocol_data: Vec = vec![]; for swap in grouped_swap.swaps.iter() { let transfer_type = self.get_transfer_type( @@ -537,7 +556,7 @@ impl StrategyEncoder for SplitSwapStrategyEncoder { ); let encoding_context = EncodingContext { - receiver: self.router_address.clone(), + receiver: swap_receiver.clone(), exact_out: solution.exact_out, router_address: Some(self.router_address.clone()), group_token_in: grouped_swap.input_token.clone(), @@ -766,7 +785,7 @@ mod tests { "5615deb798bb3e4dfa0139dfa1b3d433cc23b72f", // executor address "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // token in "a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id - "3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver + "cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // receiver "00", // zero2one "02", // transfer type "00000000000000", // padding @@ -869,13 +888,13 @@ mod tests { "5615deb798bb3e4dfa0139dfa1b3d433cc23b72f", // executor address "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // token in "a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id - "3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver + "cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // receiver "00", // zero2one "02", // transfer type "0000000000000000000000000000", // padding )); let hex_calldata = encode(&calldata); - println!("{}", hex_calldata); + println!("test_single_swap_strategy_encoder: {}", hex_calldata); assert_eq!(hex_calldata[..456], expected_input); assert_eq!(hex_calldata[1224..], expected_swap); @@ -930,7 +949,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("{}", hex_calldata); + println!("test_single_swap_strategy_encoder_wrap: {}", hex_calldata); } #[test] @@ -982,7 +1001,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("{}", hex_calldata); + println!("test_split_swap_strategy_encoder_wrap: {}", hex_calldata); } #[test] @@ -1034,7 +1053,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("{}", hex_calldata); + println!("test_split_swap_strategy_encoder_unwrap: {}", hex_calldata); } #[test] @@ -1126,7 +1145,7 @@ mod tests { .unwrap(); let _hex_calldata = encode(&calldata); - println!("{}", _hex_calldata); + println!("test_split_swap_strategy_encoder_complex_route: {}", _hex_calldata); } #[test] @@ -1192,14 +1211,11 @@ mod tests { .unwrap(); let _hex_calldata = encode(&calldata); - println!("{}", _hex_calldata); + println!("test_sequential_swap_strategy_encoder_complex_route: {}", _hex_calldata); } #[test] fn test_sequential_swap_strategy_encoder_no_permit2() { - // Note: This test does not assert anything. It is only used to obtain integration test - // data for our router solidity test. - // // Performs a split swap from WETH to USDC though WBTC and DAI using USV2 pools // // WETH ───(USV2)──> WBTC ───(USV2)──> USDC @@ -1253,8 +1269,41 @@ mod tests { .encode_strategy(solution) .unwrap(); - let _hex_calldata = encode(&calldata); - println!("{}", _hex_calldata); + let hex_calldata = encode(&calldata); + println!("test_sequential_swap_strategy_encoder_no_permit2: {}", hex_calldata); + + let expected = String::from(concat!( + "e8a980d7", /* function selector */ + "0000000000000000000000000000000000000000000000000de0b6b3a7640000", // amount in + "000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // token in + "000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // token ou + "00000000000000000000000000000000000000000000000000000000018f61ec", // min amount out + "0000000000000000000000000000000000000000000000000000000000000000", // wrap + "0000000000000000000000000000000000000000000000000000000000000000", // unwrap + "000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // receiver + "0000000000000000000000000000000000000000000000000000000000000100", /* length ple + * encode */ + "00000000000000000000000000000000000000000000000000000000000000a8", + // swap 1 + "0052", // swap length + "5615deb798bb3e4dfa0139dfa1b3d433cc23b72f", // executor address + "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // token in + "bb2b8038a1640196fbe3e38816f3e67cba72d940", // component id + "3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver (router) + "00", // zero to one + "01", // transfer type + // swap 2 + "0052", // swap length + "5615deb798bb3e4dfa0139dfa1b3d433cc23b72f", // executor address + "2260fac5e5542a773aa44fbcfedf7c193bc2c599", // token in + "004375dff511095cc5a197a54140a24efef3a416", // component id + "cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // receiver (final user) + "01", // zero to one + "00", // transfer type + "000000000000000000000000000000000000000000000000", // padding + )); + + assert_eq!(hex_calldata, expected); } #[test] @@ -1373,9 +1422,9 @@ mod tests { let expected_swaps = String::from(concat!( // length of ple encoded swaps without padding - "0000000000000000000000000000000000000000000000000000000000000079", + "000000000000000000000000000000000000000000000000000000000000008d", // ple encoded swaps - "0077", // Swap length + "008b", // Swap length "00", // token in index "01", // token out index "000000", // split @@ -1386,6 +1435,7 @@ mod tests { "6982508145454ce325ddbe47a25d4ec3d2311933", // group token in "00", // zero2one "04", // transfer type (transfer to router) + "cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // receiver // First pool params "0000000000000000000000000000000000000000", // intermediary token (ETH) "000bb8", // fee @@ -1394,14 +1444,14 @@ mod tests { "6982508145454ce325ddbe47a25d4ec3d2311933", // intermediary token (PEPE) "0061a8", // fee "0001f4", // tick spacing - "00000000000000" // padding + "00000000000000000000000000000000000000" // padding )); let hex_calldata = encode(&calldata); assert_eq!(hex_calldata[..520], expected_input); assert_eq!(hex_calldata[1288..], expected_swaps); - println!("{}", hex_calldata); + println!("test_split_encoding_strategy_usv4: {}", hex_calldata); } #[test] @@ -1461,7 +1511,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("{}", hex_calldata); + println!("test_split_encoding_strategy_ekubo: {}", hex_calldata); } #[test] @@ -1529,7 +1579,7 @@ mod tests { "5615deb798bb3e4dfa0139dfa1b3d433cc23b72f", // executor address "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // token in "a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id - "3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver + "cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // receiver "00", // zero2one "01", // transfer type "0000000000000000000000000000", // padding @@ -1539,7 +1589,7 @@ mod tests { let hex_calldata = encode(&calldata); assert_eq!(hex_calldata, expected_input); - println!("{}", hex_calldata); + println!("test_single_swap_strategy_encoder_no_permit2: {}", hex_calldata); } #[test] @@ -1612,7 +1662,7 @@ mod tests { "5615deb798bb3e4dfa0139dfa1b3d433cc23b72f", // executor address "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // token in "a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id - "3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver + "cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // receiver "00", // zero2one "01", // transfer type "00000000000000", // padding @@ -1622,7 +1672,7 @@ mod tests { let hex_calldata = encode(&calldata); assert_eq!(hex_calldata, expected_input); - println!("{}", hex_calldata); + println!("test_split_swap_strategy_encoder_no_permit2: {}", hex_calldata); } #[test] @@ -1686,7 +1736,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("{}", hex_calldata); + println!("test_split_encoding_strategy_usv4_eth_in: {}", hex_calldata); } #[test] fn test_split_encoding_strategy_usv4_eth_out() { @@ -1753,7 +1803,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("{}", hex_calldata); + println!("test_split_encoding_strategy_usv4_eth_out: {}", hex_calldata); } #[test] @@ -1863,7 +1913,7 @@ mod tests { "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // token in "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // token out "0001f4", // pool fee - "3ede3eca2a72b3aecc820e955b36f38437d01395", // router address + "3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver "88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", // component id "01", // zero2one "02", // transfer type @@ -1874,7 +1924,7 @@ mod tests { "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // token in "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // token out "000bb8", // pool fee - "3ede3eca2a72b3aecc820e955b36f38437d01395", // router address + "cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // receiver "8ad599c3a0ff1de082011efddc58f1908eb6e6d8", // component id "00", // zero2one "00", // transfer type @@ -1883,7 +1933,7 @@ mod tests { assert_eq!(hex_calldata[..520], expected_input); assert_eq!(hex_calldata[1288..], expected_swaps); - println!("{}", hex_calldata); + println!("test_cyclic_sequential_swap_split_strategy: {}", hex_calldata); } #[test] @@ -2017,7 +2067,7 @@ mod tests { "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // token in "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // token out "0001f4", // pool fee - "3ede3eca2a72b3aecc820e955b36f38437d01395", // router address + "3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver "88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", // component id "01", // zero2one "02", // transfer type @@ -2029,7 +2079,7 @@ mod tests { "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // token in "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // token out "000bb8", // pool fee - "3ede3eca2a72b3aecc820e955b36f38437d01395", // router address + "3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver "8ad599c3a0ff1de082011efddc58f1908eb6e6d8", // component id "01", // zero2one "02", // transfer type @@ -2040,7 +2090,7 @@ mod tests { "5615deb798bb3e4dfa0139dfa1b3d433cc23b72f", // executor address, "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // token in "b4e16d0168e52d35cacd2c6185b44281ec28c9dc", // component id, - "3ede3eca2a72b3aecc820e955b36f38437d01395", // router address + "cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // receiver "00", // zero2one "00", // transfer type "00000000000000" // padding @@ -2048,7 +2098,7 @@ mod tests { .join(""); assert_eq!(hex_calldata[..520], expected_input); assert_eq!(hex_calldata[1288..], expected_swaps); - println!("{}", hex_calldata); + println!("test_split_input_cyclic_swap: {}", hex_calldata); } #[test] @@ -2178,7 +2228,7 @@ mod tests { "5615deb798bb3e4dfa0139dfa1b3d433cc23b72f", // executor address "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // token in "b4e16d0168e52d35cacd2c6185b44281ec28c9dc", // component id - "3ede3eca2a72b3aecc820e955b36f38437d01395", // router address + "3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver "01", // zero2one "02", // transfer type "006e", // ple encoded swaps @@ -2189,7 +2239,7 @@ mod tests { "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // token in "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // token out "0001f4", // pool fee - "3ede3eca2a72b3aecc820e955b36f38437d01395", // router address + "cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // receiver "88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", // component id "00", // zero2one "00", // transfer type @@ -2201,7 +2251,7 @@ mod tests { "c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // token in "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // token out "000bb8", // pool fee - "3ede3eca2a72b3aecc820e955b36f38437d01395", // router address + "cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // receiver "8ad599c3a0ff1de082011efddc58f1908eb6e6d8", // component id "00", // zero2one "00", // transfer type @@ -2211,7 +2261,7 @@ mod tests { assert_eq!(hex_calldata[..520], expected_input); assert_eq!(hex_calldata[1288..], expected_swaps); - println!("{}", hex_calldata); + println!("test_split_output_cyclic_swap: {}", hex_calldata); } #[test] @@ -2273,7 +2323,7 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("{}", hex_calldata); + println!("test_split_encoding_strategy_curve: {}", hex_calldata); } #[test] @@ -2335,6 +2385,6 @@ mod tests { .unwrap(); let hex_calldata = encode(&calldata); - println!("{}", hex_calldata); + println!("test_split_encoding_strategy_curve_st_eth: {}", hex_calldata); } } diff --git a/src/encoding/evm/strategy_encoder/transfer_optimizations.rs b/src/encoding/evm/strategy_encoder/transfer_optimizations.rs index 5188986..08ac181 100644 --- a/src/encoding/evm/strategy_encoder/transfer_optimizations.rs +++ b/src/encoding/evm/strategy_encoder/transfer_optimizations.rs @@ -24,12 +24,13 @@ pub trait TransferOptimization { // In the case of wrapping, check if the swap's token in is the wrapped token to // determine if it's the first swap. Otherwise, compare to the given token. - let is_first_swap = - (swap.token_in == given_token) || ((swap.token_in == wrapped_token) && wrap); + let is_first_swap = swap.token_in == given_token; if swap.token_in == native_token { // Funds are already in router. All protocols currently take care of native transfers. TransferType::None + } else if (swap.token_in == wrapped_token) && wrap { + TransferType::TransferToProtocol } else if is_first_swap && send_funds_to_pool { if permit2 { // Transfer from swapper to pool using permit2. @@ -149,7 +150,7 @@ mod tests { let strategy = MockStrategy {}; let transfer_method = strategy.get_transfer_type(swap.clone(), eth(), eth(), weth(), false, true); - assert_eq!(transfer_method, TransferType::TransferFromToProtocol); + assert_eq!(transfer_method, TransferType::TransferToProtocol); } #[test] diff --git a/src/encoding/evm/swap_encoder/swap_encoders.rs b/src/encoding/evm/swap_encoder/swap_encoders.rs index 5581cc0..c2e803a 100644 --- a/src/encoding/evm/swap_encoder/swap_encoders.rs +++ b/src/encoding/evm/swap_encoder/swap_encoders.rs @@ -207,6 +207,7 @@ impl SwapEncoder for UniswapV4SwapEncoder { group_token_out_address, zero_to_one, (encoding_context.transfer_type as u8).to_be_bytes(), + bytes_to_address(&encoding_context.receiver)?, pool_params, ); @@ -548,6 +549,7 @@ impl SwapEncoder for CurveSwapEncoder { j.to_be_bytes::<1>(), approval_needed, (encoding_context.transfer_type as u8).to_be_bytes(), + bytes_to_address(&encoding_context.receiver)?, ); Ok(args.abi_encode_packed()) @@ -765,9 +767,8 @@ mod tests { split: 0f64, }; let encoding_context = EncodingContext { - // The receiver address was taken from `address(uniswapV4Exposed)` in the - // UniswapV4Executor.t.sol - receiver: Bytes::from("0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f"), + // The receiver is ALICE to match the solidity tests + receiver: Bytes::from("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2"), exact_out: false, // Same as the executor address router_address: Some(Bytes::from("0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f")), @@ -786,7 +787,7 @@ mod tests { .encode_swap(swap, encoding_context) .unwrap(); let hex_swap = encode(&encoded_swap); - println!("{}", hex_swap); + println!("test_encode_uniswap_v4_simple_swap: {}", hex_swap); assert_eq!( hex_swap, @@ -799,6 +800,8 @@ mod tests { "01", // transfer type "00", + // receiver + "cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // pool params: // - intermediary token "dac17f958d2ee523a2206206994597c13d831ec7", @@ -877,11 +880,11 @@ mod tests { let usdt_address = Bytes::from("0xdAC17F958D2ee523a2206206994597C13D831ec7"); let wbtc_address = Bytes::from("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"); let router_address = Bytes::from("0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f"); - let receiver_address = router_address.clone(); // The context is the same for both swaps, since the group token in and out are the same let context = EncodingContext { - receiver: receiver_address.clone(), + // The receiver is ALICE to match the solidity tests + receiver: Bytes::from("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2"), exact_out: false, router_address: Some(router_address.clone()), group_token_in: usde_address.clone(), @@ -955,7 +958,7 @@ mod tests { let combined_hex = format!("{}{}", encode(&initial_encoded_swap), encode(&second_encoded_swap)); - println!("{}", combined_hex); + println!("test_encode_uniswap_v4_sequential_swap: {}", combined_hex); assert_eq!( combined_hex, String::from(concat!( @@ -967,6 +970,8 @@ mod tests { "01", // transfer type "00", + // receiver + "cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // pool params: // - intermediary token USDT "dac17f958d2ee523a2206206994597c13d831ec7", @@ -982,6 +987,7 @@ mod tests { "00003c" )) ); + println!("{}", combined_hex) } mod ekubo { @@ -1276,6 +1282,8 @@ mod tests { "01", // transfer type "05", + // receiver, + "1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e" )) ); } @@ -1344,6 +1352,8 @@ mod tests { "01", // transfer type "05", + // receiver + "1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e" )) ); } @@ -1422,6 +1432,8 @@ mod tests { "01", // transfer type "05", + // receiver + "1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e" )) ); } diff --git a/src/encoding/evm/tycho_encoders.rs b/src/encoding/evm/tycho_encoders.rs index 1ecf41f..5d285e0 100644 --- a/src/encoding/evm/tycho_encoders.rs +++ b/src/encoding/evm/tycho_encoders.rs @@ -1050,6 +1050,8 @@ mod tests { "00", // transfer type "00", + // receiver + "cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // first pool intermediary token (ETH) "0000000000000000000000000000000000000000", // fee