feat: (WIP) Support selection of transfer into router
- For protocols like Balancer and Curve, which expect funds to be in the router at the time of swap, we must support also transferring funds from the user into the router. Doing this in the router would mean we are dealing with transfers in two different places: in the router main methods and in the executors. To avoid this, we are now performing transfers just in the executors, and two transfer types have been added to support transfers into the router. TODO: - Add this for Balancer and Curve (only added for USV4 atm). - TODO consider renaming TRANSFER_FROM and TRANSFER_PERMIT2 to include "pool" in the name
This commit is contained in:
committed by
Diana Carvalho
parent
59a80dc392
commit
a301a1cef3
@@ -99,7 +99,7 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard {
|
||||
/**
|
||||
* @notice Executes a swap operation based on a predefined swap graph, supporting internal token amount splits.
|
||||
* This function enables multi-step swaps, optional ETH wrapping/unwrapping, and validates the output amount
|
||||
* against a user-specified minimum. This function performs a transferFrom to retrieve tokens from the caller.
|
||||
* against a user-specified minimum.
|
||||
*
|
||||
* @dev
|
||||
* - If `wrapEth` is true, the contract wraps the provided native ETH into WETH and uses it as the sell token.
|
||||
@@ -130,11 +130,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard {
|
||||
address receiver,
|
||||
bytes calldata swaps
|
||||
) public payable whenNotPaused nonReentrant returns (uint256 amountOut) {
|
||||
if (address(tokenIn) != address(0)) {
|
||||
IERC20(tokenIn).safeTransferFrom(
|
||||
msg.sender, address(this), amountIn
|
||||
);
|
||||
}
|
||||
return _splitSwapChecked(
|
||||
amountIn,
|
||||
tokenIn,
|
||||
@@ -187,15 +182,9 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard {
|
||||
bytes calldata signature,
|
||||
bytes calldata swaps
|
||||
) external payable whenNotPaused nonReentrant returns (uint256 amountOut) {
|
||||
// For native ETH, assume funds already in our router. Else, transfer and handle approval.
|
||||
// For native ETH, assume funds already in our router. Else, handle approval.
|
||||
if (tokenIn != address(0)) {
|
||||
permit2.permit(msg.sender, permitSingle, signature);
|
||||
permit2.transferFrom(
|
||||
msg.sender,
|
||||
address(this),
|
||||
uint160(amountIn),
|
||||
permitSingle.details.token
|
||||
);
|
||||
}
|
||||
|
||||
return _splitSwapChecked(
|
||||
@@ -214,7 +203,7 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard {
|
||||
/**
|
||||
* @notice Executes a swap operation based on a predefined swap graph with no split routes.
|
||||
* This function enables multi-step swaps, optional ETH wrapping/unwrapping, and validates the output amount
|
||||
* against a user-specified minimum. This function performs a transferFrom to retrieve tokens from the caller.
|
||||
* against a user-specified minimum.
|
||||
*
|
||||
* @dev
|
||||
* - If `wrapEth` is true, the contract wraps the provided native ETH into WETH and uses it as the sell token.
|
||||
@@ -243,7 +232,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard {
|
||||
address receiver,
|
||||
bytes calldata swaps
|
||||
) public payable whenNotPaused nonReentrant returns (uint256 amountOut) {
|
||||
IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
|
||||
return _sequentialSwapChecked(
|
||||
amountIn,
|
||||
tokenIn,
|
||||
@@ -292,15 +280,9 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard {
|
||||
bytes calldata signature,
|
||||
bytes calldata swaps
|
||||
) external payable whenNotPaused nonReentrant returns (uint256 amountOut) {
|
||||
// For native ETH, assume funds already in our router. Else, transfer and handle approval.
|
||||
// For native ETH, assume funds already in our router. Else, handle approval.
|
||||
if (tokenIn != address(0)) {
|
||||
permit2.permit(msg.sender, permitSingle, signature);
|
||||
permit2.transferFrom(
|
||||
msg.sender,
|
||||
address(this),
|
||||
uint160(amountIn),
|
||||
permitSingle.details.token
|
||||
);
|
||||
}
|
||||
|
||||
return _sequentialSwapChecked(
|
||||
@@ -318,7 +300,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard {
|
||||
/**
|
||||
* @notice Executes a single swap operation.
|
||||
* This function enables optional ETH wrapping/unwrapping, and validates the output amount against a user-specified minimum.
|
||||
* This function performs a transferFrom to retrieve tokens from the caller.
|
||||
*
|
||||
* @dev
|
||||
* - If `wrapEth` is true, the contract wraps the provided native ETH into WETH and uses it as the sell token.
|
||||
@@ -346,7 +327,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard {
|
||||
address receiver,
|
||||
bytes calldata swapData
|
||||
) public payable whenNotPaused nonReentrant returns (uint256 amountOut) {
|
||||
IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
|
||||
return _singleSwap(
|
||||
amountIn,
|
||||
tokenIn,
|
||||
@@ -395,15 +375,9 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard {
|
||||
bytes calldata signature,
|
||||
bytes calldata swapData
|
||||
) external payable whenNotPaused nonReentrant returns (uint256 amountOut) {
|
||||
// For native ETH, assume funds already in our router. Else, transfer and handle approval.
|
||||
// For native ETH, assume funds already in our router. Else, handle approval.
|
||||
if (tokenIn != address(0)) {
|
||||
permit2.permit(msg.sender, permitSingle, signature);
|
||||
permit2.transferFrom(
|
||||
msg.sender,
|
||||
address(this),
|
||||
uint160(amountIn),
|
||||
permitSingle.details.token
|
||||
);
|
||||
}
|
||||
|
||||
return _singleSwap(
|
||||
@@ -449,23 +423,7 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard {
|
||||
_wrapETH(amountIn);
|
||||
tokenIn = address(_weth);
|
||||
}
|
||||
|
||||
uint256 initialBalance = tokenIn == address(0)
|
||||
? address(this).balance
|
||||
: IERC20(tokenIn).balanceOf(address(this));
|
||||
|
||||
amountOut = _splitSwap(amountIn, nTokens, swaps);
|
||||
uint256 currentBalance = tokenIn == address(0)
|
||||
? address(this).balance
|
||||
: IERC20(tokenIn).balanceOf(address(this));
|
||||
|
||||
uint256 amountConsumed = initialBalance - currentBalance;
|
||||
|
||||
if (tokenIn != tokenOut && amountConsumed != amountIn) {
|
||||
revert TychoRouter__AmountInDiffersFromConsumed(
|
||||
amountIn, amountConsumed
|
||||
);
|
||||
}
|
||||
|
||||
if (amountOut < minAmountOut) {
|
||||
revert TychoRouter__NegativeSlippage(amountOut, minAmountOut);
|
||||
@@ -512,25 +470,10 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard {
|
||||
tokenIn = address(_weth);
|
||||
}
|
||||
|
||||
uint256 initialBalance = tokenIn == address(0)
|
||||
? address(this).balance
|
||||
: IERC20(tokenIn).balanceOf(address(this));
|
||||
|
||||
(address executor, bytes calldata protocolData) =
|
||||
swap_.decodeSingleSwap();
|
||||
|
||||
amountOut = _callExecutor(executor, amountIn, protocolData);
|
||||
uint256 currentBalance = tokenIn == address(0)
|
||||
? address(this).balance
|
||||
: IERC20(tokenIn).balanceOf(address(this));
|
||||
|
||||
uint256 amountConsumed = initialBalance - currentBalance;
|
||||
|
||||
if (amountConsumed != amountIn) {
|
||||
revert TychoRouter__AmountInDiffersFromConsumed(
|
||||
amountIn, amountConsumed
|
||||
);
|
||||
}
|
||||
|
||||
if (amountOut < minAmountOut) {
|
||||
revert TychoRouter__NegativeSlippage(amountOut, minAmountOut);
|
||||
@@ -577,10 +520,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard {
|
||||
tokenIn = address(_weth);
|
||||
}
|
||||
|
||||
uint256 initialBalance = tokenIn == address(0)
|
||||
? address(this).balance
|
||||
: IERC20(tokenIn).balanceOf(address(this));
|
||||
|
||||
amountOut = _sequentialSwap(amountIn, swaps);
|
||||
|
||||
uint256 currentBalance = tokenIn == address(0)
|
||||
|
||||
@@ -16,9 +16,17 @@ contract TokenTransfer {
|
||||
// Assume funds are in the TychoRouter - transfer into the pool
|
||||
TRANSFER,
|
||||
// Assume funds are in msg.sender's wallet - transferFrom into the pool
|
||||
TRANSFERFROM,
|
||||
TRANSFER_FROM,
|
||||
// Assume funds are in msg.sender's wallet - permit2TransferFrom into the pool
|
||||
TRANSFERPERMIT2,
|
||||
TRANSFER_PERMIT2,
|
||||
// Assume funds are in msg.sender's wallet - but the pool requires it to be
|
||||
// in the router contract when calling swap - transferFrom into the router
|
||||
// contract
|
||||
TRANSFER_TO_ROUTER,
|
||||
// Assume funds are in msg.sender's wallet - but the pool requires it to be
|
||||
// in the router contract when calling swap - transferFrom into the router
|
||||
// contract using permit2
|
||||
TRANSFER_PERMIT2_TO_ROUTER,
|
||||
// Assume funds have already been transferred into the pool. Do nothing.
|
||||
NONE
|
||||
}
|
||||
@@ -31,21 +39,31 @@ contract TokenTransfer {
|
||||
}
|
||||
|
||||
function _transfer(
|
||||
IERC20 tokenIn,
|
||||
address tokenIn,
|
||||
address sender,
|
||||
address receiver,
|
||||
uint256 amount,
|
||||
TransferType transferType
|
||||
) internal {
|
||||
if (transferType == TransferType.TRANSFER) {
|
||||
tokenIn.safeTransfer(receiver, amount);
|
||||
} else if (transferType == TransferType.TRANSFERFROM) {
|
||||
if (tokenIn == address(0)) {
|
||||
payable(receiver).transfer(amount);
|
||||
} else {
|
||||
IERC20(tokenIn).safeTransfer(receiver, amount);
|
||||
}
|
||||
} else if (transferType == TransferType.TRANSFER_FROM) {
|
||||
// slither-disable-next-line arbitrary-send-erc20
|
||||
tokenIn.safeTransferFrom(sender, receiver, amount);
|
||||
} else if (transferType == TransferType.TRANSFERPERMIT2) {
|
||||
IERC20(tokenIn).safeTransferFrom(sender, receiver, amount);
|
||||
} else if (transferType == TransferType.TRANSFER_PERMIT2) {
|
||||
// Permit2.permit is already called from the TychoRouter
|
||||
permit2.transferFrom(sender, receiver, uint160(amount), tokenIn);
|
||||
} else if (transferType == TransferType.TRANSFER_TO_ROUTER) {
|
||||
// slither-disable-next-line arbitrary-send-erc20
|
||||
IERC20(tokenIn).safeTransferFrom(sender, address(this), amount);
|
||||
} else if (transferType == TransferType.TRANSFER_PERMIT2_TO_ROUTER) {
|
||||
// Permit2.permit is already called from the TychoRouter
|
||||
permit2.transferFrom(
|
||||
sender, receiver, uint160(amount), address(tokenIn)
|
||||
sender, address(this), uint160(amount), tokenIn
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,9 @@ contract UniswapV2Executor is IExecutor, TokenTransfer {
|
||||
_verifyPairAddress(target);
|
||||
|
||||
calculatedAmount = _getAmountOut(target, givenAmount, zeroForOne);
|
||||
_transfer(tokenIn, msg.sender, target, givenAmount, transferType);
|
||||
_transfer(
|
||||
address(tokenIn), msg.sender, target, givenAmount, transferType
|
||||
);
|
||||
|
||||
IUniswapV2Pair pool = IUniswapV2Pair(target);
|
||||
if (zeroForOne) {
|
||||
|
||||
@@ -111,7 +111,7 @@ contract UniswapV3Executor is IExecutor, ICallback, TokenTransfer {
|
||||
uint256 amountOwed =
|
||||
amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);
|
||||
|
||||
_transfer(IERC20(tokenIn), sender, msg.sender, amountOwed, transferType);
|
||||
_transfer(tokenIn, sender, msg.sender, amountOwed, transferType);
|
||||
|
||||
return abi.encode(amountOwed, tokenIn);
|
||||
}
|
||||
|
||||
@@ -17,10 +17,11 @@ import {Actions} from "@uniswap/v4-periphery/src/libraries/Actions.sol";
|
||||
import {IV4Router} from "@uniswap/v4-periphery/src/interfaces/IV4Router.sol";
|
||||
import {PathKey} from "@uniswap/v4-periphery/src/libraries/PathKey.sol";
|
||||
import {ICallback} from "@interfaces/ICallback.sol";
|
||||
import {TokenTransfer} from "./TokenTransfer.sol";
|
||||
|
||||
error UniswapV4Executor__InvalidDataLength();
|
||||
|
||||
contract UniswapV4Executor is IExecutor, V4Router, ICallback {
|
||||
contract UniswapV4Executor is IExecutor, V4Router, ICallback, TokenTransfer {
|
||||
using SafeERC20 for IERC20;
|
||||
using CurrencyLibrary for Currency;
|
||||
|
||||
@@ -30,7 +31,10 @@ contract UniswapV4Executor is IExecutor, V4Router, ICallback {
|
||||
int24 tickSpacing;
|
||||
}
|
||||
|
||||
constructor(IPoolManager _poolManager) V4Router(_poolManager) {}
|
||||
constructor(IPoolManager _poolManager, address _permit2)
|
||||
V4Router(_poolManager)
|
||||
TokenTransfer(_permit2)
|
||||
{}
|
||||
|
||||
function swap(uint256 amountIn, bytes calldata data)
|
||||
external
|
||||
@@ -41,9 +45,19 @@ contract UniswapV4Executor is IExecutor, V4Router, ICallback {
|
||||
address tokenIn,
|
||||
address tokenOut,
|
||||
bool zeroForOne,
|
||||
TransferType transferType,
|
||||
UniswapV4Executor.UniswapV4Pool[] memory pools
|
||||
) = _decodeData(data);
|
||||
|
||||
// TODO move this into callback when we implement callback transfer type support
|
||||
_transfer(
|
||||
tokenIn,
|
||||
msg.sender,
|
||||
address(this), // irrelevant attribute
|
||||
amountIn,
|
||||
transferType
|
||||
);
|
||||
|
||||
bytes memory swapData;
|
||||
if (pools.length == 1) {
|
||||
PoolKey memory key = PoolKey({
|
||||
@@ -138,6 +152,7 @@ contract UniswapV4Executor is IExecutor, V4Router, ICallback {
|
||||
address tokenIn,
|
||||
address tokenOut,
|
||||
bool zeroForOne,
|
||||
TransferType transferType,
|
||||
UniswapV4Pool[] memory pools
|
||||
)
|
||||
{
|
||||
@@ -148,10 +163,11 @@ contract UniswapV4Executor is IExecutor, V4Router, ICallback {
|
||||
tokenIn = address(bytes20(data[0:20]));
|
||||
tokenOut = address(bytes20(data[20:40]));
|
||||
zeroForOne = (data[40] != 0);
|
||||
transferType = TransferType(uint8(data[41]));
|
||||
|
||||
uint256 poolsLength = (data.length - 41) / 26; // 26 bytes per pool object
|
||||
uint256 poolsLength = (data.length - 42) / 26; // 26 bytes per pool object
|
||||
pools = new UniswapV4Pool[](poolsLength);
|
||||
bytes memory poolsData = data[41:];
|
||||
bytes memory poolsData = data[42:];
|
||||
uint256 offset = 0;
|
||||
for (uint256 i = 0; i < poolsLength; i++) {
|
||||
address intermediaryToken;
|
||||
|
||||
@@ -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"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000008f1d5c1cae37400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000059005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000"
|
||||
hex"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000008f1d5c1cae37400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000059005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d01395000100000000000000"
|
||||
);
|
||||
|
||||
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"7c553846000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330000000000000000000000000000000000000000005064ff624d54346285543f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000681f1d6200000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f7976a0000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000416af8ab519cbe8f466aed6188c8966ca4910d72d40d2f4360f62dbe75864b77ce5ec168870bb1540673b3f720c4f2bfaa5de2a79813c857ad5cc49b20217c65041c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007800760001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb486982508145454ce325ddbe47a25d4ec3d2311933000000000000000000000000000000000000000000000bb800003c6982508145454ce325ddbe47a25d4ec3d23119330061a80001f40000000000000000"
|
||||
hex"7c553846000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330000000000000000000000000000000000000000005064ff624d54346285543f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000682163b600000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9ddbe000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041e9e58e3facf99cd2c64b834d3b646b8cf9377c47540d65b5e180a06bca6f42851cf320a205cf466c7943abe45c2998afa6fd3d870043a108578e71256831ca1c1c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d008b0001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb486982508145454ce325ddbe47a25d4ec3d231193300f62849f9a0b5bf2913b396098f7c7019b51a820a040000000000000000000000000000000000000000000bb800003c6982508145454ce325ddbe47a25d4ec3d23119330061a80001f400000000000000000000000000000000000000"
|
||||
);
|
||||
|
||||
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"7c5538460000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d2311933000000000000000000000000000000000000000000c87c939ae635f92dc2379c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000681f1d7100000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f79779000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041c9ad125cc7c7188d1f0cd61dd8ee0d752d45c89ade1df275c5e0ce17525c6ff137bd976ebd0d17223c007e1f0a2806d086b4c7015460ebd21fef8a6caf8368d51c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005e005c0001000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d2311933016982508145454ce325ddbe47a25d4ec3d23119330061a80001f40000"
|
||||
hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d2311933000000000000000000000000000000000000000000c87c939ae635f92dc2379c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006821689800000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9e2a00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000412da8d5aab101bbdf256d785a42db176328e8298ee6d0906e0ef1998cfcaa332460f8409d9b298dff73c947796a22c8de21caa17405ea157ced090da2b6cb27431c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007300710001000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d231193301f62849f9a0b5bf2913b396098f7c7019b51a820a056982508145454ce325ddbe47a25d4ec3d23119330061a80001f400000000000000000000000000"
|
||||
);
|
||||
|
||||
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"7c55384600000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f81490b4f29aade000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000b2d05e0000000000000000000000000000000000000000000000000000000000681f1d7e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f797860000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000412beedebe0200a3d4ca03f34697af8ec027fe6c164e3d3b78e17d1c327dcfc8241ce8bda513f092e54b35856637e5e485a06cc8c1c6287f15f469d47e84fd91341b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005e005c0001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000000000000000000000000000bb800003c0000"
|
||||
hex"7c55384600000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f81490b4f29aade000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000b2d05e0000000000000000000000000000000000000000000000000000000000682163ee00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9ddf60000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000416056d925e7906c11b865992ac5c853532f5058bb57b67cd000a53b899503dd8a6fd4c0e5ea44c1ca4137753589bf89f66824796e719e807adee7567a707ee6681b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007300710001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a040000000000000000000000000000000000000000000bb800003c00000000000000000000000000"
|
||||
);
|
||||
|
||||
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"7c5538460000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000903146e5f6c59c064b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000681e435000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f6bd580000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000415563c90eb0f8a79e234e300520b50879242b42622cabd5d01c19e67aba4854a723e0bd8333774062ae03a22b8c5de4a0dfd70bffd9197f56b2063f390610e5891b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000059005700020000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000"
|
||||
hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000903146e5f6c59c064b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006821640400000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9de0c000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041b34e1f3d4e78942b2429b776073a5dfab1420f763de7d7e2a2296ca8abf684f923f7ae7945e824d8a084b9610d33ed49246a36e8e0efbce8ae210b0474f9fe3a1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000059005700020000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000"
|
||||
);
|
||||
|
||||
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"7c5538460000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000a2a15d09519be0000000000000000000000000000000000000000000000000000000000000681e436b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f6bd730000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000411150ac5d21c61fcd35b486034a433e44d045950a52e991a7ad4035f3ad52beee5d9ecbc5ed9c370730cd2631a050fbe1219dd606e39c8aca40d588aa3eab03411c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000059005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fa478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d01395010000000000000000"
|
||||
hex"7c5538460000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000a2a15d09519be00000000000000000000000000000000000000000000000000000000000006821641200000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9de1a00000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004181d23336d0cacd47a4d228590a825a1d92a48378cd481ff308b6d235e14b925c584f31e420682879bea58363ca4aa44a3b79557b15a9f73078a4696e00f55f911b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000059005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fa478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d01395010200000000000000"
|
||||
);
|
||||
|
||||
vm.stopPrank();
|
||||
@@ -183,7 +183,7 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup {
|
||||
IERC20(WETH_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
||||
// Encoded solution generated using `test_split_swap_strategy_encoder_complex`
|
||||
(bool success,) = tychoRouterAddr.call(
|
||||
hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000681e2d8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f6a793000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041e9868ce97a4c09488710ce748362ca38418bda44148bb5faf7820445d47efaff66f8f3667a0b3091c9d67d240db4cc2c95db27bdf019e4d5ff76b7b6620514691b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164005700028000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d013950000005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d013950000005702030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fae461ca67b15dc8dc81ce7615e0320da1a9ab8d53ede3eca2a72b3aecc820e955b36f38437d013950100005701030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a4163ede3eca2a72b3aecc820e955b36f38437d01395010000000000000000000000000000000000000000000000000000000000"
|
||||
hex"7c5538460000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006821643700000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9de3f00000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004112f41a590796702b322fa5a9ee1602daef9b22d732e4fd8f122f072b65dda325271f630759db500db8a42bd4f41ddc18ddda63650deaf36228dca702e28eefd31b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164005700028000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d013950002005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d013950002005702030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fae461ca67b15dc8dc81ce7615e0320da1a9ab8d53ede3eca2a72b3aecc820e955b36f38437d013950100005701030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a4163ede3eca2a72b3aecc820e955b36f38437d01395010000000000000000000000000000000000000000000000000000000000"
|
||||
);
|
||||
|
||||
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"51bcc7b60000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000681e493d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f6c34500000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000004189757b528c9874627ca7ecd64bd662db5fd7855837ec98cca5cff2cbd599f9af15baff1d389b5de4ca0dc1106b9d3795a1695934cd5fa1158fffcc8d6495dfaa1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d01395000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a4163ede3eca2a72b3aecc820e955b36f38437d013950100000000000000000000000000000000000000000000000000"
|
||||
hex"51bcc7b60000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006821644a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9de5200000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041530bdcde0c687eacb51a339f30c7b3eff7c078a3bbd4bc852519568dcdf271bb4c6ac05583f32c4a8d1a99be3a2817fe86c15ad2a06c5cf938bde9c22bc80f301c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d01395000200525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a4163ede3eca2a72b3aecc820e955b36f38437d013950100000000000000000000000000000000000000000000000000"
|
||||
);
|
||||
|
||||
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"e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d01395000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a4163ede3eca2a72b3aecc820e955b36f38437d013950100000000000000000000000000000000000000000000000000"
|
||||
hex"e8a980d70000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000a800525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d01395000100525615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a4163ede3eca2a72b3aecc820e955b36f38437d013950100000000000000000000000000000000000000000000000000"
|
||||
);
|
||||
|
||||
vm.stopPrank();
|
||||
@@ -254,7 +254,7 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup {
|
||||
IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
||||
// Encoded solution generated using `test_cyclic_sequential_swap`
|
||||
(bool success,) = tychoRouterAddr.call(
|
||||
hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f4308e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000681e4a0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f6c40a0000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000416a11f27f0546e9cc9d27e4383a3f860d9822f0d7d0117e73abbf03007b3e235b36c2288ff083a04f51285092ff23422b3e00a5a292d5627172dfd031308fc3a11b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0006e00010000002e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400100006e01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d80000"
|
||||
hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f4308e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006821647000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9de780000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000413c8b048dc7b7614106a5aa1fa13e48c02a6a9714dfa07d2c424f68b81a5f828c39ace62f2dd57d7bfad10910ae44f77d68aec5c079fce456028b1bd7f72053151c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0006e00010000002e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400102006e01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d80000"
|
||||
);
|
||||
|
||||
assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99889294);
|
||||
@@ -270,7 +270,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"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005ef619b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000681e2d1600000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f6a71e00000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004129478d2bffac3e378054d024ca3461f61e55552e2e8b0c7e0869f38ee834462f157f761e1a67c713f5749a6f6210dc4ac998a0521dda8dcb780b35d774250a141c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139006e00019999992e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400100006e00010000002e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d80100005701000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2b4e16d0168e52d35cacd2c6185b44281ec28c9dc3ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000"
|
||||
hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005ef619b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000006821659d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9dfa5000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041dd84c5cdc51719e377598eccd8eac0aae036e7e0745a7c65b5d44cc817071a7460ccc73934363f33cc7af71dc07545aeff1d92f8c2f0b2973e1fc37e7b2de3551c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139006e00019999992e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400102006e00010000002e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d80102005701000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2b4e16d0168e52d35cacd2c6185b44281ec28c9dc3ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000"
|
||||
);
|
||||
|
||||
assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99574171);
|
||||
@@ -286,7 +286,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"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005eea514000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000681e2d3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f6a738000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041196745237299bfab79f038c0c12decec9c46b264621e1f00bbef32b15a22f15543defe95694dd1616aa8785bbb6f91a1557eebc97c0f5ca968c99f250da1b2ce1c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48b4e16d0168e52d35cacd2c6185b44281ec28c9dc3ede3eca2a72b3aecc820e955b36f38437d013950100006e01009999992e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400000006e01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d8000000000000000000"
|
||||
hex"7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005eea514000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000682165ac00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9dfb400000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004107f2b0f9c2e4e308ab43b288d69de30d84b10c8075e4dd9a2cf66594f97a52fb34de2534b89bf1887da74c92fd03464f45baff700dd32e213e3add1a3f351e891b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48b4e16d0168e52d35cacd2c6185b44281ec28c9dc3ede3eca2a72b3aecc820e955b36f38437d013950102006e01009999992e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400000006e01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d8000000000000000000"
|
||||
);
|
||||
|
||||
assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99525908);
|
||||
|
||||
@@ -8,23 +8,38 @@ import "./executors/UniswapV4Utils.sol";
|
||||
import {SafeCallback} from "@uniswap/v4-periphery/src/base/SafeCallback.sol";
|
||||
|
||||
contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
||||
function _getSequentialSwaps() internal view returns (bytes[] memory) {
|
||||
function _getSequentialSwaps(bool permit2)
|
||||
internal
|
||||
view
|
||||
returns (bytes[] memory)
|
||||
{
|
||||
// Trade 1 WETH for USDC through DAI with 2 swaps on Uniswap V2
|
||||
// 1 WETH -> DAI -> USDC
|
||||
// (univ2) (univ2)
|
||||
|
||||
TokenTransfer.TransferType transferType = permit2
|
||||
? TokenTransfer.TransferType.TRANSFER_PERMIT2
|
||||
: TokenTransfer.TransferType.TRANSFER_FROM;
|
||||
|
||||
bytes[] memory swaps = new bytes[](2);
|
||||
// WETH -> DAI
|
||||
swaps[0] = encodeSequentialSwap(
|
||||
address(usv2Executor),
|
||||
encodeUniswapV2Swap(
|
||||
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
|
||||
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false, transferType
|
||||
)
|
||||
);
|
||||
|
||||
// DAI -> USDC
|
||||
swaps[1] = encodeSequentialSwap(
|
||||
address(usv2Executor),
|
||||
encodeUniswapV2Swap(DAI_ADDR, DAI_USDC_POOL, tychoRouterAddr, true)
|
||||
encodeUniswapV2Swap(
|
||||
DAI_ADDR,
|
||||
DAI_USDC_POOL,
|
||||
tychoRouterAddr,
|
||||
true,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
)
|
||||
);
|
||||
return swaps;
|
||||
}
|
||||
@@ -32,10 +47,13 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
||||
function testSequentialSwapInternalMethod() public {
|
||||
// Trade 1 WETH for USDC through DAI - see _getSequentialSwaps for more info
|
||||
uint256 amountIn = 1 ether;
|
||||
deal(WETH_ADDR, tychoRouterAddr, amountIn);
|
||||
deal(WETH_ADDR, ALICE, amountIn);
|
||||
vm.startPrank(ALICE);
|
||||
IERC20(WETH_ADDR).approve(tychoRouterAddr, amountIn);
|
||||
|
||||
bytes[] memory swaps = _getSequentialSwaps();
|
||||
bytes[] memory swaps = _getSequentialSwaps(false);
|
||||
tychoRouter.exposedSequentialSwap(amountIn, pleEncode(swaps));
|
||||
vm.stopPrank();
|
||||
|
||||
uint256 usdcBalance = IERC20(USDC_ADDR).balanceOf(tychoRouterAddr);
|
||||
assertEq(usdcBalance, 2644659787);
|
||||
@@ -53,7 +71,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
||||
bytes memory signature
|
||||
) = handlePermit2Approval(WETH_ADDR, tychoRouterAddr, amountIn);
|
||||
|
||||
bytes[] memory swaps = _getSequentialSwaps();
|
||||
bytes[] memory swaps = _getSequentialSwaps(true);
|
||||
tychoRouter.sequentialSwapPermit2(
|
||||
amountIn,
|
||||
WETH_ADDR,
|
||||
@@ -80,7 +98,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
||||
vm.startPrank(ALICE);
|
||||
IERC20(WETH_ADDR).approve(tychoRouterAddr, amountIn);
|
||||
|
||||
bytes[] memory swaps = _getSequentialSwaps();
|
||||
bytes[] memory swaps = _getSequentialSwaps(false);
|
||||
tychoRouter.sequentialSwap(
|
||||
amountIn,
|
||||
WETH_ADDR,
|
||||
@@ -105,7 +123,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
||||
vm.startPrank(ALICE);
|
||||
IERC20(WETH_ADDR).approve(tychoRouterAddr, amountIn);
|
||||
|
||||
bytes[] memory swaps = _getSequentialSwaps();
|
||||
bytes[] memory swaps = _getSequentialSwaps(false);
|
||||
vm.expectRevert(TychoRouter__UndefinedMinAmountOut.selector);
|
||||
tychoRouter.sequentialSwap(
|
||||
amountIn,
|
||||
@@ -127,7 +145,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
||||
vm.startPrank(ALICE);
|
||||
IERC20(WETH_ADDR).approve(tychoRouterAddr, amountIn - 1);
|
||||
|
||||
bytes[] memory swaps = _getSequentialSwaps();
|
||||
bytes[] memory swaps = _getSequentialSwaps(false);
|
||||
vm.expectRevert();
|
||||
tychoRouter.sequentialSwap(
|
||||
amountIn,
|
||||
@@ -152,7 +170,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
||||
bytes memory signature
|
||||
) = handlePermit2Approval(WETH_ADDR, tychoRouterAddr, amountIn);
|
||||
|
||||
bytes[] memory swaps = _getSequentialSwaps();
|
||||
bytes[] memory swaps = _getSequentialSwaps(true);
|
||||
|
||||
uint256 minAmountOut = 3000 * 1e18;
|
||||
|
||||
@@ -195,7 +213,30 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
||||
sigDeadline: 0
|
||||
});
|
||||
|
||||
bytes[] memory swaps = _getSequentialSwaps();
|
||||
bytes[] memory swaps = new bytes[](2);
|
||||
// WETH -> DAI
|
||||
swaps[0] = encodeSequentialSwap(
|
||||
address(usv2Executor),
|
||||
encodeUniswapV2Swap(
|
||||
WETH_ADDR,
|
||||
WETH_DAI_POOL,
|
||||
tychoRouterAddr,
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
)
|
||||
);
|
||||
|
||||
// DAI -> USDC
|
||||
swaps[1] = encodeSequentialSwap(
|
||||
address(usv2Executor),
|
||||
encodeUniswapV2Swap(
|
||||
DAI_ADDR,
|
||||
DAI_USDC_POOL,
|
||||
tychoRouterAddr,
|
||||
true,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
)
|
||||
);
|
||||
|
||||
uint256 amountOut = tychoRouter.sequentialSwapPermit2{value: amountIn}(
|
||||
amountIn,
|
||||
@@ -237,14 +278,24 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
||||
swaps[0] = encodeSequentialSwap(
|
||||
address(usv2Executor),
|
||||
encodeUniswapV2Swap(
|
||||
USDC_ADDR, DAI_USDC_POOL, tychoRouterAddr, false
|
||||
USDC_ADDR,
|
||||
DAI_USDC_POOL,
|
||||
tychoRouterAddr,
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER_PERMIT2
|
||||
)
|
||||
);
|
||||
|
||||
// DAI -> WETH
|
||||
swaps[1] = encodeSequentialSwap(
|
||||
address(usv2Executor),
|
||||
encodeUniswapV2Swap(DAI_ADDR, WETH_DAI_POOL, tychoRouterAddr, true)
|
||||
encodeUniswapV2Swap(
|
||||
DAI_ADDR,
|
||||
WETH_DAI_POOL,
|
||||
tychoRouterAddr,
|
||||
true,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
)
|
||||
);
|
||||
|
||||
uint256 amountOut = tychoRouter.sequentialSwapPermit2(
|
||||
@@ -275,11 +326,21 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
||||
deal(USDC_ADDR, tychoRouterAddr, amountIn);
|
||||
|
||||
bytes memory usdcWethV3Pool1ZeroOneData = encodeUniswapV3Swap(
|
||||
USDC_ADDR, WETH_ADDR, tychoRouterAddr, USDC_WETH_USV3, true
|
||||
USDC_ADDR,
|
||||
WETH_ADDR,
|
||||
tychoRouterAddr,
|
||||
USDC_WETH_USV3,
|
||||
true,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
);
|
||||
|
||||
bytes memory usdcWethV3Pool2OneZeroData = encodeUniswapV3Swap(
|
||||
WETH_ADDR, USDC_ADDR, tychoRouterAddr, USDC_WETH_USV3_2, false
|
||||
WETH_ADDR,
|
||||
USDC_ADDR,
|
||||
tychoRouterAddr,
|
||||
USDC_WETH_USV3_2,
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
);
|
||||
|
||||
bytes[] memory swaps = new bytes[](2);
|
||||
|
||||
@@ -22,7 +22,11 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup {
|
||||
) = handlePermit2Approval(WETH_ADDR, tychoRouterAddr, amountIn);
|
||||
|
||||
bytes memory protocolData = encodeUniswapV2Swap(
|
||||
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
|
||||
WETH_ADDR,
|
||||
WETH_DAI_POOL,
|
||||
tychoRouterAddr,
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER_PERMIT2
|
||||
);
|
||||
|
||||
bytes memory swap =
|
||||
@@ -59,7 +63,11 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup {
|
||||
IERC20(WETH_ADDR).approve(address(tychoRouterAddr), amountIn);
|
||||
|
||||
bytes memory protocolData = encodeUniswapV2Swap(
|
||||
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
|
||||
WETH_ADDR,
|
||||
WETH_DAI_POOL,
|
||||
tychoRouterAddr,
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER_FROM
|
||||
);
|
||||
|
||||
bytes memory swap =
|
||||
@@ -96,7 +104,11 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup {
|
||||
IERC20(WETH_ADDR).approve(address(tychoRouterAddr), amountIn);
|
||||
|
||||
bytes memory protocolData = encodeUniswapV2Swap(
|
||||
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
|
||||
WETH_ADDR,
|
||||
WETH_DAI_POOL,
|
||||
tychoRouterAddr,
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER_FROM
|
||||
);
|
||||
|
||||
bytes memory swap =
|
||||
@@ -118,7 +130,11 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup {
|
||||
IERC20(WETH_ADDR).approve(address(tychoRouterAddr), amountIn - 1);
|
||||
|
||||
bytes memory protocolData = encodeUniswapV2Swap(
|
||||
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
|
||||
WETH_ADDR,
|
||||
WETH_DAI_POOL,
|
||||
tychoRouterAddr,
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER_FROM
|
||||
);
|
||||
|
||||
bytes memory swap =
|
||||
@@ -149,7 +165,11 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup {
|
||||
IERC20(WETH_ADDR).approve(address(tychoRouterAddr), amountIn);
|
||||
|
||||
bytes memory protocolData = encodeUniswapV2Swap(
|
||||
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
|
||||
WETH_ADDR,
|
||||
WETH_DAI_POOL,
|
||||
tychoRouterAddr,
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER_FROM
|
||||
);
|
||||
|
||||
bytes memory swap =
|
||||
@@ -194,7 +214,11 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup {
|
||||
});
|
||||
|
||||
bytes memory protocolData = encodeUniswapV2Swap(
|
||||
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
|
||||
WETH_ADDR,
|
||||
WETH_DAI_POOL,
|
||||
tychoRouterAddr,
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
);
|
||||
|
||||
bytes memory swap =
|
||||
@@ -232,8 +256,13 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup {
|
||||
bytes memory signature
|
||||
) = handlePermit2Approval(DAI_ADDR, tychoRouterAddr, amountIn);
|
||||
|
||||
bytes memory protocolData =
|
||||
encodeUniswapV2Swap(DAI_ADDR, WETH_DAI_POOL, tychoRouterAddr, true);
|
||||
bytes memory protocolData = encodeUniswapV2Swap(
|
||||
DAI_ADDR,
|
||||
WETH_DAI_POOL,
|
||||
tychoRouterAddr,
|
||||
true,
|
||||
TokenTransfer.TransferType.TRANSFER_PERMIT2
|
||||
);
|
||||
|
||||
bytes memory swap =
|
||||
encodeSingleSwap(address(usv2Executor), protocolData);
|
||||
@@ -267,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"20144a070000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000008f1d5c1cae3740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d0139500000000000000000000000000000000"
|
||||
hex"20144a070000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000008f1d5c1cae3740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d0139500010000000000000000000000000000"
|
||||
);
|
||||
|
||||
vm.stopPrank();
|
||||
@@ -286,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"30ace1b10000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000903146e5f6c59c064b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006817833200000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067effd3a00000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000417efea09004d5d40d8d072e1ce0a425507717ea485c765eb90c170859197d362b502fb039b4f5cdce57318ecfe3ab276d1ac87771eb5d017b253a8f4107e6a20b1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d0139500000000000000000000000000000000"
|
||||
hex"30ace1b10000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000903146e5f6c59c064b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000682169c100000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067f9e3c900000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000412d3f0fee3fc61987512f024f20b1448eb934f82105a91653dd169179c693aaf95d09ef666ce1d38be70b8156fa6e4ea3e8717204e02fe7ba99a1fc4e5a26e6e11b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000525615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d0139500020000000000000000000000000000"
|
||||
);
|
||||
|
||||
vm.stopPrank();
|
||||
|
||||
@@ -8,13 +8,22 @@ import "./executors/UniswapV4Utils.sol";
|
||||
import {SafeCallback} from "@uniswap/v4-periphery/src/base/SafeCallback.sol";
|
||||
|
||||
contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
function _getSplitSwaps() private view returns (bytes[] memory) {
|
||||
function _getSplitSwaps(bool permit2)
|
||||
private
|
||||
view
|
||||
returns (bytes[] memory)
|
||||
{
|
||||
// Trade 1 WETH for USDC through DAI and WBTC with 4 swaps on Uniswap V2
|
||||
// -> DAI ->
|
||||
// 1 WETH USDC
|
||||
// -> WBTC ->
|
||||
// (univ2) (univ2)
|
||||
bytes[] memory swaps = new bytes[](4);
|
||||
|
||||
TokenTransfer.TransferType inTransferType = permit2
|
||||
? TokenTransfer.TransferType.TRANSFER_PERMIT2
|
||||
: TokenTransfer.TransferType.TRANSFER_FROM;
|
||||
|
||||
// WETH -> WBTC (60%)
|
||||
swaps[0] = encodeSplitSwap(
|
||||
uint8(0),
|
||||
@@ -22,7 +31,11 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
(0xffffff * 60) / 100, // 60%
|
||||
address(usv2Executor),
|
||||
encodeUniswapV2Swap(
|
||||
WETH_ADDR, WETH_WBTC_POOL, tychoRouterAddr, false
|
||||
WETH_ADDR,
|
||||
WETH_WBTC_POOL,
|
||||
tychoRouterAddr,
|
||||
false,
|
||||
inTransferType
|
||||
)
|
||||
);
|
||||
// WBTC -> USDC
|
||||
@@ -32,7 +45,11 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
uint24(0),
|
||||
address(usv2Executor),
|
||||
encodeUniswapV2Swap(
|
||||
WBTC_ADDR, USDC_WBTC_POOL, tychoRouterAddr, true
|
||||
WBTC_ADDR,
|
||||
USDC_WBTC_POOL,
|
||||
tychoRouterAddr,
|
||||
true,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
)
|
||||
);
|
||||
// WETH -> DAI
|
||||
@@ -42,7 +59,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
uint24(0),
|
||||
address(usv2Executor),
|
||||
encodeUniswapV2Swap(
|
||||
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
|
||||
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false, inTransferType
|
||||
)
|
||||
);
|
||||
|
||||
@@ -52,7 +69,13 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
uint8(2),
|
||||
uint24(0),
|
||||
address(usv2Executor),
|
||||
encodeUniswapV2Swap(DAI_ADDR, DAI_USDC_POOL, tychoRouterAddr, true)
|
||||
encodeUniswapV2Swap(
|
||||
DAI_ADDR,
|
||||
DAI_USDC_POOL,
|
||||
tychoRouterAddr,
|
||||
true,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
)
|
||||
);
|
||||
|
||||
return swaps;
|
||||
@@ -62,9 +85,12 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
// Trade 1 WETH for USDC through DAI and WBTC - see _getSplitSwaps for more info
|
||||
|
||||
uint256 amountIn = 1 ether;
|
||||
deal(WETH_ADDR, tychoRouterAddr, amountIn);
|
||||
bytes[] memory swaps = _getSplitSwaps();
|
||||
deal(WETH_ADDR, ALICE, amountIn);
|
||||
vm.startPrank(ALICE);
|
||||
IERC20(WETH_ADDR).approve(address(tychoRouterAddr), amountIn);
|
||||
bytes[] memory swaps = _getSplitSwaps(false);
|
||||
tychoRouter.exposedSplitSwap(amountIn, 4, pleEncode(swaps));
|
||||
vm.stopPrank();
|
||||
|
||||
uint256 usdcBalance = IERC20(USDC_ADDR).balanceOf(tychoRouterAddr);
|
||||
assertEq(usdcBalance, 2615491639);
|
||||
@@ -83,7 +109,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
bytes memory signature
|
||||
) = handlePermit2Approval(WETH_ADDR, tychoRouterAddr, amountIn);
|
||||
|
||||
bytes[] memory swaps = _getSplitSwaps();
|
||||
bytes[] memory swaps = _getSplitSwaps(true);
|
||||
|
||||
tychoRouter.splitSwapPermit2(
|
||||
amountIn,
|
||||
@@ -112,7 +138,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
vm.startPrank(ALICE);
|
||||
IERC20(WETH_ADDR).approve(address(tychoRouterAddr), amountIn);
|
||||
|
||||
bytes[] memory swaps = _getSplitSwaps();
|
||||
bytes[] memory swaps = _getSplitSwaps(false);
|
||||
|
||||
tychoRouter.splitSwap(
|
||||
amountIn,
|
||||
@@ -139,7 +165,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
vm.startPrank(ALICE);
|
||||
IERC20(WETH_ADDR).approve(address(tychoRouterAddr), amountIn);
|
||||
|
||||
bytes[] memory swaps = _getSplitSwaps();
|
||||
bytes[] memory swaps = _getSplitSwaps(false);
|
||||
|
||||
vm.expectRevert(TychoRouter__UndefinedMinAmountOut.selector);
|
||||
tychoRouter.splitSwap(
|
||||
@@ -164,7 +190,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
vm.startPrank(ALICE);
|
||||
// Approve less than the amountIn
|
||||
IERC20(WETH_ADDR).approve(address(tychoRouterAddr), amountIn - 1);
|
||||
bytes[] memory swaps = _getSplitSwaps();
|
||||
bytes[] memory swaps = _getSplitSwaps(false);
|
||||
|
||||
vm.expectRevert();
|
||||
tychoRouter.splitSwap(
|
||||
@@ -193,7 +219,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
bytes memory signature
|
||||
) = handlePermit2Approval(WETH_ADDR, tychoRouterAddr, amountIn);
|
||||
|
||||
bytes[] memory swaps = _getSplitSwaps();
|
||||
bytes[] memory swaps = _getSplitSwaps(true);
|
||||
|
||||
uint256 minAmountOut = 3000 * 1e18;
|
||||
|
||||
@@ -240,7 +266,11 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
sigDeadline: 0
|
||||
});
|
||||
bytes memory protocolData = encodeUniswapV2Swap(
|
||||
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
|
||||
WETH_ADDR,
|
||||
WETH_DAI_POOL,
|
||||
tychoRouterAddr,
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
);
|
||||
|
||||
bytes memory swap = encodeSplitSwap(
|
||||
@@ -284,8 +314,13 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
bytes memory signature
|
||||
) = handlePermit2Approval(DAI_ADDR, tychoRouterAddr, amountIn);
|
||||
|
||||
bytes memory protocolData =
|
||||
encodeUniswapV2Swap(DAI_ADDR, WETH_DAI_POOL, tychoRouterAddr, true);
|
||||
bytes memory protocolData = encodeUniswapV2Swap(
|
||||
DAI_ADDR,
|
||||
WETH_DAI_POOL,
|
||||
tychoRouterAddr,
|
||||
true,
|
||||
TokenTransfer.TransferType.TRANSFER_PERMIT2
|
||||
);
|
||||
|
||||
bytes memory swap = encodeSplitSwap(
|
||||
uint8(0), uint8(1), uint24(0), address(usv2Executor), protocolData
|
||||
@@ -330,7 +365,12 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
uint256 expAmountOut = 1205_128428842122129186; //Swap 1 WETH for 1205.12 DAI
|
||||
bool zeroForOne = false;
|
||||
bytes memory protocolData = encodeUniswapV3Swap(
|
||||
WETH_ADDR, DAI_ADDR, tychoRouterAddr, DAI_WETH_USV3, zeroForOne
|
||||
WETH_ADDR,
|
||||
DAI_ADDR,
|
||||
tychoRouterAddr,
|
||||
DAI_WETH_USV3,
|
||||
zeroForOne,
|
||||
TokenTransfer.TransferType.TRANSFER_PERMIT2
|
||||
);
|
||||
bytes memory swap = encodeSplitSwap(
|
||||
uint8(0), uint8(1), uint24(0), address(usv3Executor), protocolData
|
||||
@@ -366,59 +406,6 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
tychoRouter.exposedSplitSwap(amountIn, 2, swaps);
|
||||
}
|
||||
|
||||
function testSplitSwapAmountInNotFullySpent() public {
|
||||
// Trade 1 WETH for DAI with 1 swap on Uniswap V2
|
||||
// Has invalid data as input! There is only one swap with 60% of the input amount
|
||||
uint256 amountIn = 1 ether;
|
||||
deal(WETH_ADDR, ALICE, amountIn);
|
||||
|
||||
vm.startPrank(ALICE);
|
||||
|
||||
(
|
||||
IAllowanceTransfer.PermitSingle memory permitSingle,
|
||||
bytes memory signature
|
||||
) = handlePermit2Approval(WETH_ADDR, tychoRouterAddr, amountIn);
|
||||
|
||||
bytes memory protocolData = encodeUniswapV2Swap(
|
||||
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
|
||||
);
|
||||
|
||||
bytes memory swap = encodeSplitSwap(
|
||||
uint8(0),
|
||||
uint8(1),
|
||||
(0xffffff * 60) / 100, // 60%
|
||||
address(usv2Executor),
|
||||
protocolData
|
||||
);
|
||||
|
||||
bytes[] memory swaps = new bytes[](1);
|
||||
swaps[0] = swap;
|
||||
|
||||
vm.expectRevert(
|
||||
abi.encodeWithSelector(
|
||||
TychoRouter__AmountInDiffersFromConsumed.selector,
|
||||
1000000000000000000,
|
||||
600000000000000000
|
||||
)
|
||||
);
|
||||
|
||||
tychoRouter.splitSwapPermit2(
|
||||
amountIn,
|
||||
WETH_ADDR,
|
||||
DAI_ADDR,
|
||||
1,
|
||||
false,
|
||||
false,
|
||||
2,
|
||||
ALICE,
|
||||
permitSingle,
|
||||
signature,
|
||||
pleEncode(swaps)
|
||||
);
|
||||
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
function testSplitSwapSingleUSV4CallbackPermit2() public {
|
||||
vm.startPrank(ALICE);
|
||||
uint256 amountIn = 100 ether;
|
||||
@@ -436,8 +423,13 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
tickSpacing: int24(1)
|
||||
});
|
||||
|
||||
bytes memory protocolData =
|
||||
UniswapV4Utils.encodeExactInput(USDE_ADDR, USDT_ADDR, true, pools);
|
||||
bytes memory protocolData = UniswapV4Utils.encodeExactInput(
|
||||
USDE_ADDR,
|
||||
USDT_ADDR,
|
||||
true,
|
||||
TokenTransfer.TransferType.TRANSFER_PERMIT2_TO_ROUTER,
|
||||
pools
|
||||
);
|
||||
|
||||
bytes memory swap = encodeSplitSwap(
|
||||
uint8(0), uint8(1), uint24(0), address(usv4Executor), protocolData
|
||||
@@ -483,8 +475,13 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
tickSpacing: int24(60)
|
||||
});
|
||||
|
||||
bytes memory protocolData =
|
||||
UniswapV4Utils.encodeExactInput(USDE_ADDR, WBTC_ADDR, true, pools);
|
||||
bytes memory protocolData = UniswapV4Utils.encodeExactInput(
|
||||
USDE_ADDR,
|
||||
WBTC_ADDR,
|
||||
true,
|
||||
TokenTransfer.TransferType.NONE,
|
||||
pools
|
||||
);
|
||||
|
||||
bytes memory swap = encodeSplitSwap(
|
||||
uint8(0), uint8(1), uint24(0), address(usv4Executor), protocolData
|
||||
@@ -507,18 +504,35 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
// │ │
|
||||
// └─ (USV3, 40% split) ──> WETH ─┘
|
||||
uint256 amountIn = 100 * 10 ** 6;
|
||||
deal(USDC_ADDR, tychoRouterAddr, amountIn);
|
||||
deal(USDC_ADDR, ALICE, amountIn);
|
||||
vm.startPrank(ALICE);
|
||||
// Approve the TychoRouter to spend USDC
|
||||
IERC20(USDC_ADDR).approve(tychoRouterAddr, amountIn);
|
||||
|
||||
bytes memory usdcWethV3Pool1ZeroOneData = encodeUniswapV3Swap(
|
||||
USDC_ADDR, WETH_ADDR, tychoRouterAddr, USDC_WETH_USV3, true
|
||||
USDC_ADDR,
|
||||
WETH_ADDR,
|
||||
tychoRouterAddr,
|
||||
USDC_WETH_USV3,
|
||||
true,
|
||||
TokenTransfer.TransferType.TRANSFER_FROM
|
||||
);
|
||||
|
||||
bytes memory usdcWethV3Pool2ZeroOneData = encodeUniswapV3Swap(
|
||||
USDC_ADDR, WETH_ADDR, tychoRouterAddr, USDC_WETH_USV3_2, true
|
||||
USDC_ADDR,
|
||||
WETH_ADDR,
|
||||
tychoRouterAddr,
|
||||
USDC_WETH_USV3_2,
|
||||
true,
|
||||
TokenTransfer.TransferType.TRANSFER_FROM
|
||||
);
|
||||
|
||||
bytes memory wethUsdcV2OneZeroData = encodeUniswapV2Swap(
|
||||
WETH_ADDR, USDC_WETH_USV2, tychoRouterAddr, false
|
||||
WETH_ADDR,
|
||||
USDC_WETH_USV2,
|
||||
tychoRouterAddr,
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
);
|
||||
|
||||
bytes[] memory swaps = new bytes[](3);
|
||||
@@ -547,6 +561,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
wethUsdcV2OneZeroData
|
||||
);
|
||||
tychoRouter.exposedSplitSwap(amountIn, 2, pleEncode(swaps));
|
||||
vm.stopPrank();
|
||||
assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 99574171);
|
||||
}
|
||||
|
||||
@@ -563,15 +578,29 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
deal(USDC_ADDR, tychoRouterAddr, amountIn);
|
||||
|
||||
bytes memory usdcWethV2Data = encodeUniswapV2Swap(
|
||||
USDC_ADDR, USDC_WETH_USV2, tychoRouterAddr, true
|
||||
USDC_ADDR,
|
||||
USDC_WETH_USV2,
|
||||
tychoRouterAddr,
|
||||
true,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
);
|
||||
|
||||
bytes memory usdcWethV3Pool1OneZeroData = encodeUniswapV3Swap(
|
||||
WETH_ADDR, USDC_ADDR, tychoRouterAddr, USDC_WETH_USV3, false
|
||||
WETH_ADDR,
|
||||
USDC_ADDR,
|
||||
tychoRouterAddr,
|
||||
USDC_WETH_USV3,
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
);
|
||||
|
||||
bytes memory usdcWethV3Pool2OneZeroData = encodeUniswapV3Swap(
|
||||
WETH_ADDR, USDC_ADDR, tychoRouterAddr, USDC_WETH_USV3_2, false
|
||||
WETH_ADDR,
|
||||
USDC_ADDR,
|
||||
tychoRouterAddr,
|
||||
USDC_WETH_USV3_2,
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
);
|
||||
|
||||
bytes[] memory swaps = new bytes[](3);
|
||||
@@ -610,7 +639,11 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
deal(BASE_USDC, tychoRouterAddr, amountIn);
|
||||
|
||||
bytes memory protocolData = encodeUniswapV2Swap(
|
||||
BASE_USDC, USDC_MAG7_POOL, tychoRouterAddr, true
|
||||
BASE_USDC,
|
||||
USDC_MAG7_POOL,
|
||||
tychoRouterAddr,
|
||||
true,
|
||||
TokenTransfer.TransferType.TRANSFER_FROM
|
||||
);
|
||||
|
||||
bytes memory swap = encodeSplitSwap(
|
||||
|
||||
@@ -102,7 +102,7 @@ contract TychoRouterTestSetup is Constants, Permit2TestHelper {
|
||||
new UniswapV2Executor(factoryV2, initCodeV2, PERMIT2_ADDRESS);
|
||||
usv3Executor =
|
||||
new UniswapV3Executor(factoryV3, initCodeV3, PERMIT2_ADDRESS);
|
||||
usv4Executor = new UniswapV4Executor(poolManager);
|
||||
usv4Executor = new UniswapV4Executor(poolManager, PERMIT2_ADDRESS);
|
||||
pancakev3Executor = new UniswapV3Executor(
|
||||
factoryPancakeV3, initCodePancakeV3, PERMIT2_ADDRESS
|
||||
);
|
||||
@@ -178,15 +178,11 @@ contract TychoRouterTestSetup is Constants, Permit2TestHelper {
|
||||
address tokenIn,
|
||||
address target,
|
||||
address receiver,
|
||||
bool zero2one
|
||||
bool zero2one,
|
||||
TokenTransfer.TransferType transferType
|
||||
) internal pure returns (bytes memory) {
|
||||
return abi.encodePacked(
|
||||
tokenIn,
|
||||
target,
|
||||
receiver,
|
||||
zero2one,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
);
|
||||
return
|
||||
abi.encodePacked(tokenIn, target, receiver, zero2one, transferType);
|
||||
}
|
||||
|
||||
function encodeUniswapV3Swap(
|
||||
@@ -194,7 +190,8 @@ contract TychoRouterTestSetup is Constants, Permit2TestHelper {
|
||||
address tokenOut,
|
||||
address receiver,
|
||||
address target,
|
||||
bool zero2one
|
||||
bool zero2one,
|
||||
TokenTransfer.TransferType transferType
|
||||
) internal view returns (bytes memory) {
|
||||
IUniswapV3Pool pool = IUniswapV3Pool(target);
|
||||
return abi.encodePacked(
|
||||
@@ -204,7 +201,7 @@ contract TychoRouterTestSetup is Constants, Permit2TestHelper {
|
||||
receiver,
|
||||
target,
|
||||
zero2one,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
transferType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ contract UniswapV2ExecutorTest is Test, Constants, Permit2TestHelper {
|
||||
WETH_DAI_POOL,
|
||||
BOB,
|
||||
zeroForOne,
|
||||
uint8(TokenTransfer.TransferType.TRANSFERFROM)
|
||||
uint8(TokenTransfer.TransferType.TRANSFER_FROM)
|
||||
);
|
||||
|
||||
deal(WETH_ADDR, address(this), amountIn);
|
||||
@@ -197,7 +197,7 @@ contract UniswapV2ExecutorTest is Test, Constants, Permit2TestHelper {
|
||||
WETH_DAI_POOL,
|
||||
ALICE,
|
||||
zeroForOne,
|
||||
uint8(TokenTransfer.TransferType.TRANSFERPERMIT2)
|
||||
uint8(TokenTransfer.TransferType.TRANSFER_PERMIT2)
|
||||
);
|
||||
|
||||
deal(WETH_ADDR, ALICE, amountIn);
|
||||
|
||||
@@ -7,9 +7,12 @@ import "@src/executors/UniswapV4Executor.sol";
|
||||
import {Constants} from "../Constants.sol";
|
||||
import {Test} from "../../lib/forge-std/src/Test.sol";
|
||||
import {SafeCallback} from "@uniswap/v4-periphery/src/base/SafeCallback.sol";
|
||||
import "@src/executors/TokenTransfer.sol";
|
||||
|
||||
contract UniswapV4ExecutorExposed is UniswapV4Executor {
|
||||
constructor(IPoolManager _poolManager) UniswapV4Executor(_poolManager) {}
|
||||
constructor(IPoolManager _poolManager, address _permit2)
|
||||
UniswapV4Executor(_poolManager, _permit2)
|
||||
{}
|
||||
|
||||
function decodeData(bytes calldata data)
|
||||
external
|
||||
@@ -18,6 +21,7 @@ contract UniswapV4ExecutorExposed is UniswapV4Executor {
|
||||
address tokenIn,
|
||||
address tokenOut,
|
||||
bool zeroForOne,
|
||||
TokenTransfer.TransferType transferType,
|
||||
UniswapV4Pool[] memory pools
|
||||
)
|
||||
{
|
||||
@@ -36,8 +40,9 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
||||
function setUp() public {
|
||||
uint256 forkBlock = 21817316;
|
||||
vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock);
|
||||
uniswapV4Exposed =
|
||||
new UniswapV4ExecutorExposed(IPoolManager(poolManager));
|
||||
uniswapV4Exposed = new UniswapV4ExecutorExposed(
|
||||
IPoolManager(poolManager), PERMIT2_ADDRESS
|
||||
);
|
||||
}
|
||||
|
||||
function testDecodeParams() public view {
|
||||
@@ -46,6 +51,8 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
||||
int24 tickSpacing1 = 60;
|
||||
uint24 pool2Fee = 1000;
|
||||
int24 tickSpacing2 = -10;
|
||||
TokenTransfer.TransferType transferType =
|
||||
TokenTransfer.TransferType.TRANSFER_FROM;
|
||||
|
||||
UniswapV4Executor.UniswapV4Pool[] memory pools =
|
||||
new UniswapV4Executor.UniswapV4Pool[](2);
|
||||
@@ -61,19 +68,21 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
||||
});
|
||||
|
||||
bytes memory data = UniswapV4Utils.encodeExactInput(
|
||||
USDE_ADDR, USDT_ADDR, zeroForOne, pools
|
||||
USDE_ADDR, USDT_ADDR, zeroForOne, transferType, pools
|
||||
);
|
||||
|
||||
(
|
||||
address tokenIn,
|
||||
address tokenOut,
|
||||
bool zeroForOneDecoded,
|
||||
TokenTransfer.TransferType transferTypeDecoded,
|
||||
UniswapV4Executor.UniswapV4Pool[] memory decodedPools
|
||||
) = uniswapV4Exposed.decodeData(data);
|
||||
|
||||
assertEq(tokenIn, USDE_ADDR);
|
||||
assertEq(tokenOut, USDT_ADDR);
|
||||
assertEq(zeroForOneDecoded, zeroForOne);
|
||||
assertEq(uint8(transferTypeDecoded), uint8(transferType));
|
||||
assertEq(decodedPools.length, 2);
|
||||
assertEq(decodedPools[0].intermediaryToken, USDT_ADDR);
|
||||
assertEq(decodedPools[0].fee, pool1Fee);
|
||||
@@ -98,8 +107,13 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
||||
tickSpacing: int24(1)
|
||||
});
|
||||
|
||||
bytes memory data =
|
||||
UniswapV4Utils.encodeExactInput(USDE_ADDR, USDT_ADDR, true, pools);
|
||||
bytes memory data = UniswapV4Utils.encodeExactInput(
|
||||
USDE_ADDR,
|
||||
USDT_ADDR,
|
||||
true,
|
||||
TokenTransfer.TransferType.NONE,
|
||||
pools
|
||||
);
|
||||
|
||||
uint256 amountOut = uniswapV4Exposed.swap(amountIn, data);
|
||||
assertEq(USDE.balanceOf(poolManager), usdeBalanceBeforePool + amountIn);
|
||||
@@ -114,7 +128,7 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
||||
// USDE -> USDT
|
||||
// Generated by the Tycho swap encoder - test_encode_uniswap_v4_simple_swap
|
||||
bytes memory protocolData =
|
||||
hex"4c9edd5852cd905f086c759e8383e09bff1e68b3dac17f958d2ee523a2206206994597c13d831ec701dac17f958d2ee523a2206206994597c13d831ec7000064000001";
|
||||
hex"4c9edd5852cd905f086c759e8383e09bff1e68b3dac17f958d2ee523a2206206994597c13d831ec701f62849f9a0b5bf2913b396098f7c7019b51a820a00dac17f958d2ee523a2206206994597c13d831ec7000064000001";
|
||||
uint256 amountIn = 100 ether;
|
||||
deal(USDE_ADDR, address(uniswapV4Exposed), amountIn);
|
||||
uint256 usdeBalanceBeforePool = USDE.balanceOf(poolManager);
|
||||
@@ -151,8 +165,13 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
||||
tickSpacing: int24(60)
|
||||
});
|
||||
|
||||
bytes memory data =
|
||||
UniswapV4Utils.encodeExactInput(USDE_ADDR, WBTC_ADDR, true, pools);
|
||||
bytes memory data = UniswapV4Utils.encodeExactInput(
|
||||
USDE_ADDR,
|
||||
WBTC_ADDR,
|
||||
true,
|
||||
TokenTransfer.TransferType.NONE,
|
||||
pools
|
||||
);
|
||||
|
||||
uint256 amountOut = uniswapV4Exposed.swap(amountIn, data);
|
||||
assertEq(USDE.balanceOf(poolManager), usdeBalanceBeforePool + amountIn);
|
||||
@@ -170,7 +189,7 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
||||
// Generated by the Tycho swap encoder - test_encode_uniswap_v4_sequential_swap
|
||||
|
||||
bytes memory protocolData =
|
||||
hex"4c9edd5852cd905f086c759e8383e09bff1e68b32260fac5e5542a773aa44fbcfedf7c193bc2c59901dac17f958d2ee523a2206206994597c13d831ec70000640000012260fac5e5542a773aa44fbcfedf7c193bc2c599000bb800003c";
|
||||
hex"4c9edd5852cd905f086c759e8383e09bff1e68b32260fac5e5542a773aa44fbcfedf7c193bc2c59901f62849f9a0b5bf2913b396098f7c7019b51a820a00dac17f958d2ee523a2206206994597c13d831ec70000640000012260fac5e5542a773aa44fbcfedf7c193bc2c599000bb800003c";
|
||||
|
||||
uint256 amountIn = 100 ether;
|
||||
deal(USDE_ADDR, address(uniswapV4Exposed), amountIn);
|
||||
|
||||
@@ -8,6 +8,7 @@ library UniswapV4Utils {
|
||||
address tokenIn,
|
||||
address tokenOut,
|
||||
bool zeroForOne,
|
||||
UniswapV4Executor.TransferType transferType,
|
||||
UniswapV4Executor.UniswapV4Pool[] memory pools
|
||||
) public pure returns (bytes memory) {
|
||||
bytes memory encodedPools;
|
||||
@@ -21,6 +22,12 @@ library UniswapV4Utils {
|
||||
);
|
||||
}
|
||||
|
||||
return abi.encodePacked(tokenIn, tokenOut, zeroForOne, encodedPools);
|
||||
return abi.encodePacked(
|
||||
tokenIn,
|
||||
tokenOut,
|
||||
zeroForOne,
|
||||
transferType,
|
||||
encodedPools
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,3 +26,14 @@ pub static IN_TRANSFER_OPTIMIZABLE_PROTOCOLS: LazyLock<HashSet<&'static str>> =
|
||||
set.insert("uniswap_v3");
|
||||
set
|
||||
});
|
||||
|
||||
/// These protocols expect funds to be in the router at the time of swap.
|
||||
pub static PROTOCOLS_EXPECTING_FUNDS_IN_ROUTER: LazyLock<HashSet<&'static str>> =
|
||||
LazyLock::new(|| {
|
||||
let mut set = HashSet::new();
|
||||
set.insert("curve");
|
||||
set.insert("balancer_v2");
|
||||
// TODO remove uniswap_v4 when we add callback support for transfer optimizations
|
||||
set.insert("uniswap_v4");
|
||||
set
|
||||
});
|
||||
|
||||
@@ -39,6 +39,7 @@ pub struct SingleSwapStrategyEncoder {
|
||||
swap_encoder_registry: SwapEncoderRegistry,
|
||||
permit2: Option<Permit2>,
|
||||
selector: String,
|
||||
native_address: Bytes,
|
||||
router_address: Bytes,
|
||||
}
|
||||
|
||||
@@ -57,7 +58,13 @@ impl SingleSwapStrategyEncoder {
|
||||
"singleSwap(uint256,address,address,uint256,bool,bool,address,bytes)".to_string(),
|
||||
)
|
||||
};
|
||||
Ok(Self { permit2, selector, swap_encoder_registry, router_address })
|
||||
Ok(Self {
|
||||
permit2,
|
||||
selector,
|
||||
swap_encoder_registry,
|
||||
native_address: chain.native_token()?,
|
||||
router_address,
|
||||
})
|
||||
}
|
||||
|
||||
/// Encodes information necessary for performing a single hop against a given executor for
|
||||
@@ -117,6 +124,7 @@ impl StrategyEncoder for SingleSwapStrategyEncoder {
|
||||
let transfer_type = self.get_transfer_method(
|
||||
swap.clone(),
|
||||
solution.given_token.clone(),
|
||||
self.native_address.clone(),
|
||||
self.permit2.clone().is_some(),
|
||||
);
|
||||
|
||||
@@ -289,6 +297,7 @@ impl StrategyEncoder for SequentialSwapStrategyEncoder {
|
||||
let transfer_type = self.get_transfer_method(
|
||||
swap.clone(),
|
||||
solution.given_token.clone(),
|
||||
self.native_address.clone(),
|
||||
self.permit2.clone().is_some(),
|
||||
);
|
||||
|
||||
@@ -515,6 +524,7 @@ impl StrategyEncoder for SplitSwapStrategyEncoder {
|
||||
let transfer_type = self.get_transfer_method(
|
||||
swap.clone(),
|
||||
solution.given_token.clone(),
|
||||
self.native_address.clone(),
|
||||
self.permit2.clone().is_some(),
|
||||
);
|
||||
|
||||
@@ -857,6 +867,7 @@ mod tests {
|
||||
"0000000000000000000000000000", // padding
|
||||
));
|
||||
let hex_calldata = encode(&calldata);
|
||||
println!("{}", hex_calldata);
|
||||
|
||||
assert_eq!(hex_calldata[..456], expected_input);
|
||||
assert_eq!(hex_calldata[1224..], expected_swap);
|
||||
@@ -1354,9 +1365,9 @@ mod tests {
|
||||
|
||||
let expected_swaps = String::from(concat!(
|
||||
// length of ple encoded swaps without padding
|
||||
"0000000000000000000000000000000000000000000000000000000000000078",
|
||||
"0000000000000000000000000000000000000000000000000000000000000079",
|
||||
// ple encoded swaps
|
||||
"0076", // Swap length
|
||||
"0077", // Swap length
|
||||
"00", // token in index
|
||||
"01", // token out index
|
||||
"000000", // split
|
||||
@@ -1366,6 +1377,7 @@ mod tests {
|
||||
"a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // group token in
|
||||
"6982508145454ce325ddbe47a25d4ec3d2311933", // group token in
|
||||
"00", // zero2one
|
||||
"04", // transfer type (transfer to router)
|
||||
// First pool params
|
||||
"0000000000000000000000000000000000000000", // intermediary token (ETH)
|
||||
"000bb8", // fee
|
||||
@@ -1374,7 +1386,7 @@ mod tests {
|
||||
"6982508145454ce325ddbe47a25d4ec3d2311933", // intermediary token (PEPE)
|
||||
"0061a8", // fee
|
||||
"0001f4", // tick spacing
|
||||
"0000000000000000" // padding
|
||||
"00000000000000" // padding
|
||||
));
|
||||
|
||||
let hex_calldata = encode(&calldata);
|
||||
|
||||
@@ -1,26 +1,47 @@
|
||||
use tycho_common::Bytes;
|
||||
|
||||
use crate::encoding::{
|
||||
evm::constants::IN_TRANSFER_OPTIMIZABLE_PROTOCOLS,
|
||||
evm::constants::{IN_TRANSFER_OPTIMIZABLE_PROTOCOLS, PROTOCOLS_EXPECTING_FUNDS_IN_ROUTER},
|
||||
models::{Swap, TransferType},
|
||||
};
|
||||
|
||||
/// A trait that defines how the tokens will be transferred into the given pool given the solution.
|
||||
pub trait TransferOptimization {
|
||||
/// Returns the transfer method that should be used for the given swap and solution.
|
||||
///
|
||||
/// If the swap is for the in token of the solution and the protocol supports transferring
|
||||
/// straight from the user, it will return `TransferType::Permit2Transfer` or
|
||||
/// `TransferType::TransferFrom`.
|
||||
fn get_transfer_method(&self, swap: Swap, given_token: Bytes, permit2: bool) -> TransferType {
|
||||
let optimize_in_transfer =
|
||||
fn get_transfer_method(
|
||||
&self,
|
||||
swap: Swap,
|
||||
given_token: Bytes,
|
||||
native_token: Bytes,
|
||||
permit2: bool,
|
||||
) -> TransferType {
|
||||
let send_funds_to_pool: bool =
|
||||
IN_TRANSFER_OPTIMIZABLE_PROTOCOLS.contains(&swap.component.protocol_system.as_str());
|
||||
if (swap.token_in == given_token) && optimize_in_transfer {
|
||||
if permit2 {
|
||||
let funds_expected_in_router: bool =
|
||||
PROTOCOLS_EXPECTING_FUNDS_IN_ROUTER.contains(&swap.component.protocol_system.as_str());
|
||||
|
||||
if (swap.token_in == given_token) && send_funds_to_pool {
|
||||
if swap.token_in == native_token {
|
||||
// Funds are already in router. Transfer from router to pool.
|
||||
TransferType::Transfer
|
||||
} else if permit2 {
|
||||
// Transfer from swapper to pool using permit2.
|
||||
TransferType::Permit2Transfer
|
||||
} else {
|
||||
// Transfer from swapper to pool.
|
||||
TransferType::TransferFrom
|
||||
}
|
||||
} else if (swap.token_in == given_token) && funds_expected_in_router {
|
||||
if swap.token_in == native_token {
|
||||
// Funds already in router. Do nothing.
|
||||
TransferType::None
|
||||
} else if permit2 {
|
||||
// Transfer from swapper to router using permit2.
|
||||
TransferType::Permit2TransferToRouter
|
||||
} else {
|
||||
// Transfer from swapper to router.
|
||||
TransferType::TransferToRouter
|
||||
}
|
||||
} else {
|
||||
TransferType::Transfer
|
||||
}
|
||||
@@ -41,6 +62,10 @@ mod tests {
|
||||
Bytes::from(hex!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2").to_vec())
|
||||
}
|
||||
|
||||
fn eth() -> Bytes {
|
||||
Bytes::from(hex!("0000000000000000000000000000000000000000").to_vec())
|
||||
}
|
||||
|
||||
fn dai() -> Bytes {
|
||||
Bytes::from(hex!("6b175474e89094c44da98b954eedeac495271d0f").to_vec())
|
||||
}
|
||||
@@ -57,7 +82,7 @@ mod tests {
|
||||
split: 0f64,
|
||||
};
|
||||
let strategy = MockStrategy {};
|
||||
let transfer_method = strategy.get_transfer_method(swap.clone(), weth(), true);
|
||||
let transfer_method = strategy.get_transfer_method(swap.clone(), weth(), eth(), true);
|
||||
assert_eq!(transfer_method, TransferType::Permit2Transfer);
|
||||
}
|
||||
|
||||
@@ -73,7 +98,7 @@ mod tests {
|
||||
split: 0f64,
|
||||
};
|
||||
let strategy = MockStrategy {};
|
||||
let transfer_method = strategy.get_transfer_method(swap.clone(), weth(), false);
|
||||
let transfer_method = strategy.get_transfer_method(swap.clone(), weth(), eth(), false);
|
||||
assert_eq!(transfer_method, TransferType::TransferFrom);
|
||||
}
|
||||
|
||||
@@ -89,7 +114,7 @@ mod tests {
|
||||
split: 0f64,
|
||||
};
|
||||
let strategy = MockStrategy {};
|
||||
let transfer_method = strategy.get_transfer_method(swap.clone(), dai(), false);
|
||||
let transfer_method = strategy.get_transfer_method(swap.clone(), dai(), eth(), false);
|
||||
assert_eq!(transfer_method, TransferType::Transfer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,7 +202,13 @@ impl SwapEncoder for UniswapV4SwapEncoder {
|
||||
let pool_params =
|
||||
(token_out_address, pool_fee_u24, pool_tick_spacing_u24).abi_encode_packed();
|
||||
|
||||
let args = (group_token_in_address, group_token_out_address, zero_to_one, pool_params);
|
||||
let args = (
|
||||
group_token_in_address,
|
||||
group_token_out_address,
|
||||
zero_to_one,
|
||||
(encoding_context.transfer_type as u8).to_be_bytes(),
|
||||
pool_params,
|
||||
);
|
||||
|
||||
Ok(args.abi_encode_packed())
|
||||
}
|
||||
@@ -786,6 +792,8 @@ mod tests {
|
||||
"dac17f958d2ee523a2206206994597c13d831ec7",
|
||||
// zero for one
|
||||
"01",
|
||||
// transfer type
|
||||
"00",
|
||||
// pool params:
|
||||
// - intermediary token
|
||||
"dac17f958d2ee523a2206206994597c13d831ec7",
|
||||
@@ -942,6 +950,7 @@ mod tests {
|
||||
let combined_hex =
|
||||
format!("{}{}", encode(&initial_encoded_swap), encode(&second_encoded_swap));
|
||||
|
||||
println!("{}", combined_hex);
|
||||
assert_eq!(
|
||||
combined_hex,
|
||||
String::from(concat!(
|
||||
@@ -951,6 +960,8 @@ mod tests {
|
||||
"2260fac5e5542a773aa44fbcfedf7c193bc2c599",
|
||||
// zero for one
|
||||
"01",
|
||||
// transfer type
|
||||
"00",
|
||||
// pool params:
|
||||
// - intermediary token USDT
|
||||
"dac17f958d2ee523a2206206994597c13d831ec7",
|
||||
|
||||
@@ -1048,6 +1048,8 @@ mod tests {
|
||||
"6982508145454ce325ddbe47a25d4ec3d2311933",
|
||||
// zero for one
|
||||
"00",
|
||||
// transfer type
|
||||
"00",
|
||||
// first pool intermediary token (ETH)
|
||||
"0000000000000000000000000000000000000000",
|
||||
// fee
|
||||
|
||||
@@ -103,6 +103,8 @@ pub struct Transaction {
|
||||
/// * `Transfer`: Transfer the token from the router into the pool.
|
||||
/// * `TransferFrom`: Transfer the token from the swapper to the pool.
|
||||
/// * `Permit2Transfer`: Transfer the token from the sender to the pool using Permit2.
|
||||
/// * `TransferToRouter`: Transfer the token from the swapper to the router.
|
||||
/// * `Permit2TransferToRouter`: Transfer the token from the swapper to the router using Permit2.
|
||||
/// * `None`: No transfer is needed. Tokens are already in the pool.
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
@@ -110,7 +112,9 @@ pub enum TransferType {
|
||||
Transfer = 0,
|
||||
TransferFrom = 1,
|
||||
Permit2Transfer = 2,
|
||||
None = 3,
|
||||
TransferToRouter = 3,
|
||||
Permit2TransferToRouter = 4,
|
||||
None = 5,
|
||||
}
|
||||
|
||||
/// Represents necessary attributes for encoding an order.
|
||||
|
||||
Reference in New Issue
Block a user