Merge pull request #158 from propeller-heads/encodig/tnl/ENG-4313-transfer-in
feat: Optimize transfer to first pool in encoding
This commit is contained in:
@@ -58,9 +58,6 @@ import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
|
||||
error TychoRouter__AddressZero();
|
||||
error TychoRouter__EmptySwaps();
|
||||
error TychoRouter__NegativeSlippage(uint256 amount, uint256 minAmount);
|
||||
error TychoRouter__AmountInDiffersFromConsumed(
|
||||
uint256 amountIn, uint256 amountConsumed
|
||||
);
|
||||
error TychoRouter__MessageValueMismatch(uint256 value, uint256 amount);
|
||||
error TychoRouter__InvalidDataLength();
|
||||
error TychoRouter__UndefinedMinAmountOut();
|
||||
@@ -99,7 +96,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 +127,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 +179,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 +200,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 +229,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 +277,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 +297,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 +324,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 +372,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 +420,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 +467,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,24 +517,8 @@ 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)
|
||||
? 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);
|
||||
}
|
||||
|
||||
@@ -10,14 +10,17 @@ import {
|
||||
import {IAsset} from "@balancer-labs/v2-interfaces/contracts/vault/IAsset.sol";
|
||||
// slither-disable-next-line solc-version
|
||||
import {IVault} from "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol";
|
||||
import {TokenTransfer} from "./TokenTransfer.sol";
|
||||
|
||||
error BalancerV2Executor__InvalidDataLength();
|
||||
|
||||
contract BalancerV2Executor is IExecutor {
|
||||
contract BalancerV2Executor is IExecutor, TokenTransfer {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
address private constant VAULT = 0xBA12222222228d8Ba445958a75a0704d566BF2C8;
|
||||
|
||||
constructor(address _permit2) TokenTransfer(_permit2) {}
|
||||
|
||||
// slither-disable-next-line locked-ether
|
||||
function swap(uint256 givenAmount, bytes calldata data)
|
||||
external
|
||||
@@ -29,9 +32,20 @@ contract BalancerV2Executor is IExecutor {
|
||||
IERC20 tokenOut,
|
||||
bytes32 poolId,
|
||||
address receiver,
|
||||
bool needsApproval
|
||||
bool needsApproval,
|
||||
TransferType transferType
|
||||
) = _decodeData(data);
|
||||
|
||||
_transfer(
|
||||
address(tokenIn),
|
||||
msg.sender,
|
||||
// Receiver can never be the pool, since the pool expects funds in the router contract
|
||||
// Thus, this call will only ever be used to transfer funds from the user into the router.
|
||||
address(this),
|
||||
givenAmount,
|
||||
transferType
|
||||
);
|
||||
|
||||
if (needsApproval) {
|
||||
// slither-disable-next-line unused-return
|
||||
tokenIn.approve(VAULT, type(uint256).max);
|
||||
@@ -67,10 +81,11 @@ contract BalancerV2Executor is IExecutor {
|
||||
IERC20 tokenOut,
|
||||
bytes32 poolId,
|
||||
address receiver,
|
||||
bool needsApproval
|
||||
bool needsApproval,
|
||||
TransferType transferType
|
||||
)
|
||||
{
|
||||
if (data.length != 93) {
|
||||
if (data.length != 94) {
|
||||
revert BalancerV2Executor__InvalidDataLength();
|
||||
}
|
||||
|
||||
@@ -79,5 +94,6 @@ contract BalancerV2Executor is IExecutor {
|
||||
poolId = bytes32(data[40:72]);
|
||||
receiver = address(bytes20(data[72:92]));
|
||||
needsApproval = uint8(data[92]) > 0;
|
||||
transferType = TransferType(uint8(data[93]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@ pragma solidity ^0.8.26;
|
||||
|
||||
import "@interfaces/IExecutor.sol";
|
||||
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
||||
import "./TokenTransfer.sol";
|
||||
|
||||
error CurveExecutor__AddressZero();
|
||||
error CurveExecutor__InvalidDataLength();
|
||||
|
||||
interface CryptoPool {
|
||||
// slither-disable-next-line naming-convention
|
||||
@@ -32,12 +34,14 @@ interface CryptoPoolETH {
|
||||
// slither-disable-end naming-convention
|
||||
}
|
||||
|
||||
contract CurveExecutor is IExecutor {
|
||||
contract CurveExecutor is IExecutor, TokenTransfer {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
address public immutable nativeToken;
|
||||
|
||||
constructor(address _nativeToken) {
|
||||
constructor(address _nativeToken, address _permit2)
|
||||
TokenTransfer(_permit2)
|
||||
{
|
||||
if (_nativeToken == address(0)) {
|
||||
revert CurveExecutor__AddressZero();
|
||||
}
|
||||
@@ -50,6 +54,8 @@ contract CurveExecutor is IExecutor {
|
||||
payable
|
||||
returns (uint256)
|
||||
{
|
||||
if (data.length != 65) revert CurveExecutor__InvalidDataLength();
|
||||
|
||||
(
|
||||
address tokenIn,
|
||||
address tokenOut,
|
||||
@@ -57,9 +63,20 @@ contract CurveExecutor is IExecutor {
|
||||
uint8 poolType,
|
||||
int128 i,
|
||||
int128 j,
|
||||
bool tokenApprovalNeeded
|
||||
bool tokenApprovalNeeded,
|
||||
TransferType transferType
|
||||
) = _decodeData(data);
|
||||
|
||||
_transfer(
|
||||
tokenIn,
|
||||
msg.sender,
|
||||
// Receiver can never be the pool, since the pool expects funds in the router contract
|
||||
// Thus, this call will only ever be used to transfer funds from the user into the router.
|
||||
address(this),
|
||||
amountIn,
|
||||
transferType
|
||||
);
|
||||
|
||||
if (tokenApprovalNeeded && tokenIn != nativeToken) {
|
||||
// slither-disable-next-line unused-return
|
||||
IERC20(tokenIn).approve(address(pool), type(uint256).max);
|
||||
@@ -105,7 +122,8 @@ contract CurveExecutor is IExecutor {
|
||||
uint8 poolType,
|
||||
int128 i,
|
||||
int128 j,
|
||||
bool tokenApprovalNeeded
|
||||
bool tokenApprovalNeeded,
|
||||
TransferType transferType
|
||||
)
|
||||
{
|
||||
tokenIn = address(bytes20(data[0:20]));
|
||||
@@ -115,6 +133,7 @@ contract CurveExecutor is IExecutor {
|
||||
i = int128(uint128(uint8(data[61])));
|
||||
j = int128(uint128(uint8(data[62])));
|
||||
tokenApprovalNeeded = data[63] != 0;
|
||||
transferType = TransferType(uint8(data[64]));
|
||||
}
|
||||
|
||||
receive() external payable {
|
||||
|
||||
@@ -14,11 +14,19 @@ contract TokenTransfer {
|
||||
|
||||
enum TransferType {
|
||||
// Assume funds are in the TychoRouter - transfer into the pool
|
||||
TRANSFER,
|
||||
TRANSFER_TO_PROTOCOL,
|
||||
// Assume funds are in msg.sender's wallet - transferFrom into the pool
|
||||
TRANSFERFROM,
|
||||
TRANSFER_FROM_TO_PROTOCOL,
|
||||
// Assume funds are in msg.sender's wallet - permit2TransferFrom into the pool
|
||||
TRANSFERPERMIT2,
|
||||
TRANSFER_PERMIT2_TO_PROTOCOL,
|
||||
// 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_FROM_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 (transferType == TransferType.TRANSFER_TO_PROTOCOL) {
|
||||
if (tokenIn == address(0)) {
|
||||
payable(receiver).transfer(amount);
|
||||
} else {
|
||||
IERC20(tokenIn).safeTransfer(receiver, amount);
|
||||
}
|
||||
} else if (transferType == TransferType.TRANSFER_FROM_TO_PROTOCOL) {
|
||||
// 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_TO_PROTOCOL) {
|
||||
// Permit2.permit is already called from the TychoRouter
|
||||
permit2.transferFrom(sender, receiver, uint160(amount), tokenIn);
|
||||
} else if (transferType == TransferType.TRANSFER_FROM_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,21 @@ 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,
|
||||
// Receiver can never be the pool, since the pool expects funds in the router contract
|
||||
// Thus, this call will only ever be used to transfer funds from the user into the router.
|
||||
address(this),
|
||||
amountIn,
|
||||
transferType
|
||||
);
|
||||
|
||||
bytes memory swapData;
|
||||
if (pools.length == 1) {
|
||||
PoolKey memory key = PoolKey({
|
||||
@@ -138,6 +154,7 @@ contract UniswapV4Executor is IExecutor, V4Router, ICallback {
|
||||
address tokenIn,
|
||||
address tokenOut,
|
||||
bool zeroForOne,
|
||||
TransferType transferType,
|
||||
UniswapV4Pool[] memory pools
|
||||
)
|
||||
{
|
||||
@@ -148,10 +165,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"7c553846000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330000000000000000000000000000000000000000005064ff624d54346285543f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000006824c2ae00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fd3cb6000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041850e1add80e90f19d7b1ac70721b5dec8a6bdcb57999ea957f831ea57c4ce1a116bec18d2cae2559421ead48186b6985176fee7f8d2e3452c1518dc2635224b41c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007900770001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb486982508145454ce325ddbe47a25d4ec3d231193300040000000000000000000000000000000000000000000bb800003c6982508145454ce325ddbe47a25d4ec3d23119330061a80001f400000000000000"
|
||||
);
|
||||
|
||||
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"7c5538460000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d2311933000000000000000000000000000000000000000000c87c939ae635f92dc2379c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006824c2cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fd3cd3000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041a97e156e8c7a48a968efe2f057700ce8458ecfbfb53e0319fc9223b2364aba20227d2ee00226b42e2f28aeb002a242576d75152b270d73a8926f595190828f3d1c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005f005d0001000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000006982508145454ce325ddbe47a25d4ec3d231193301056982508145454ce325ddbe47a25d4ec3d23119330061a80001f400"
|
||||
);
|
||||
|
||||
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"7c55384600000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f81490b4f29aade000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000000000000000000000000000000000006824c2da00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067fd3ce20000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000416b224d97fe1a35f2698380969c22854cf7ed92881ea484df7adb438f8d8e78e66c8617131f6712c5f3b4fa07725725081b2ebe27cd44acd11332a4a72bded96c1b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005f005d0001000000f62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000040000000000000000000000000000000000000000000bb800003c00"
|
||||
);
|
||||
|
||||
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,9 +254,10 @@ 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"
|
||||
);
|
||||
|
||||
assertTrue(success, "Call Failed");
|
||||
assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99889294);
|
||||
|
||||
vm.stopPrank();
|
||||
@@ -270,9 +271,10 @@ 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"
|
||||
);
|
||||
|
||||
assertTrue(success, "Call Failed");
|
||||
assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99574171);
|
||||
|
||||
vm.stopPrank();
|
||||
@@ -286,9 +288,10 @@ 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"
|
||||
);
|
||||
|
||||
assertTrue(success, "Call Failed");
|
||||
assertEq(IERC20(USDC_ADDR).balanceOf(ALICE), 99525908);
|
||||
|
||||
vm.stopPrank();
|
||||
@@ -301,9 +304,10 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup {
|
||||
IERC20(UWU_ADDR).approve(tychoRouterAddr, type(uint256).max);
|
||||
// Encoded solution generated using `test_split_encoding_strategy_curve`
|
||||
(bool success,) = tychoRouterAddr.call(
|
||||
hex"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000055c08ca52497e2f1534b59e2917bf524d4765257000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000005b005900010000001d1499e622d69689cdf9004d05ec547d650ff21155c08ca52497e2f1534b59e2917bf524d4765257c02aaa39b223fe8d0a0e5c4f27ead9083c756cc277146b0a1d08b6844376df6d9da99ba7f1b19e71020100010000000000"
|
||||
hex"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000055c08ca52497e2f1534b59e2917bf524d4765257000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000005c005a00010000001d1499e622d69689cdf9004d05ec547d650ff21155c08ca52497e2f1534b59e2917bf524d4765257c02aaa39b223fe8d0a0e5c4f27ead9083c756cc277146b0a1d08b6844376df6d9da99ba7f1b19e71020100010300000000"
|
||||
);
|
||||
|
||||
assertTrue(success, "Call Failed");
|
||||
assertEq(IERC20(WETH_ADDR).balanceOf(ALICE), 4691958787921);
|
||||
|
||||
vm.stopPrank();
|
||||
@@ -315,9 +319,10 @@ contract TychoRouterTestIntegration is TychoRouterTestSetup {
|
||||
vm.startPrank(ALICE);
|
||||
// Encoded solution generated using `test_split_encoding_strategy_curve_st_eth`
|
||||
(bool success,) = tychoRouterAddr.call{value: 1 ether}(
|
||||
hex"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe840000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000005b005900010000001d1499e622d69689cdf9004d05ec547d650ff211eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeae7ab96520de3a18e5e111b5eaab095312d7fe84dc24316b9ae028f1497c275eb9192a3ea0f67022010001000000000000"
|
||||
hex"79b9b93b0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe840000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000005c005a00010000001d1499e622d69689cdf9004d05ec547d650ff211eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeae7ab96520de3a18e5e111b5eaab095312d7fe84dc24316b9ae028f1497c275eb9192a3ea0f67022010001000500000000"
|
||||
);
|
||||
|
||||
assertTrue(success, "Call Failed");
|
||||
assertEq(IERC20(STETH_ADDR).balanceOf(ALICE), 1000754689941529590);
|
||||
|
||||
vm.stopPrank();
|
||||
|
||||
@@ -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_TO_PROTOCOL
|
||||
: TokenTransfer.TransferType.TRANSFER_FROM_TO_PROTOCOL;
|
||||
|
||||
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_TO_PROTOCOL
|
||||
)
|
||||
);
|
||||
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_TO_PROTOCOL
|
||||
)
|
||||
);
|
||||
|
||||
// DAI -> USDC
|
||||
swaps[1] = encodeSequentialSwap(
|
||||
address(usv2Executor),
|
||||
encodeUniswapV2Swap(
|
||||
DAI_ADDR,
|
||||
DAI_USDC_POOL,
|
||||
tychoRouterAddr,
|
||||
true,
|
||||
TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL
|
||||
)
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
)
|
||||
);
|
||||
|
||||
// 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_TO_PROTOCOL
|
||||
)
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
: TokenTransfer.TransferType.TRANSFER_FROM_TO_PROTOCOL;
|
||||
|
||||
// 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_TO_PROTOCOL
|
||||
)
|
||||
);
|
||||
// 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_TO_PROTOCOL
|
||||
)
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
);
|
||||
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,9 @@ 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 +500,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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
bytes memory wethUsdcV2OneZeroData = encodeUniswapV2Swap(
|
||||
WETH_ADDR, USDC_WETH_USV2, tychoRouterAddr, false
|
||||
WETH_ADDR,
|
||||
USDC_WETH_USV2,
|
||||
tychoRouterAddr,
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL
|
||||
);
|
||||
|
||||
bytes[] memory swaps = new bytes[](3);
|
||||
@@ -547,6 +557,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
||||
wethUsdcV2OneZeroData
|
||||
);
|
||||
tychoRouter.exposedSplitSwap(amountIn, 2, pleEncode(swaps));
|
||||
vm.stopPrank();
|
||||
assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 99574171);
|
||||
}
|
||||
|
||||
@@ -563,15 +574,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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
bytes[] memory swaps = new bytes[](3);
|
||||
@@ -610,7 +635,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_TO_PROTOCOL
|
||||
);
|
||||
|
||||
bytes memory swap = encodeSplitSwap(
|
||||
|
||||
@@ -102,13 +102,13 @@ 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
|
||||
);
|
||||
balancerv2Executor = new BalancerV2Executor();
|
||||
balancerv2Executor = new BalancerV2Executor(PERMIT2_ADDRESS);
|
||||
ekuboExecutor = new EkuboExecutor(ekuboCore);
|
||||
curveExecutor = new CurveExecutor(ETH_ADDR_FOR_CURVE);
|
||||
curveExecutor = new CurveExecutor(ETH_ADDR_FOR_CURVE, PERMIT2_ADDRESS);
|
||||
|
||||
address[] memory executors = new address[](7);
|
||||
executors[0] = address(usv2Executor);
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import {Test} from "../../lib/forge-std/src/Test.sol";
|
||||
import {Constants} from "../Constants.sol";
|
||||
|
||||
contract BalancerV2ExecutorExposed is BalancerV2Executor {
|
||||
constructor(address _permit2) BalancerV2Executor(_permit2) {}
|
||||
|
||||
function decodeParams(bytes calldata data)
|
||||
external
|
||||
pure
|
||||
@@ -14,18 +16,15 @@ contract BalancerV2ExecutorExposed is BalancerV2Executor {
|
||||
IERC20 tokenOut,
|
||||
bytes32 poolId,
|
||||
address receiver,
|
||||
bool needsApproval
|
||||
bool needsApproval,
|
||||
TransferType transferType
|
||||
)
|
||||
{
|
||||
return _decodeData(data);
|
||||
}
|
||||
}
|
||||
|
||||
contract BalancerV2ExecutorTest is
|
||||
BalancerV2ExecutorExposed,
|
||||
Test,
|
||||
Constants
|
||||
{
|
||||
contract BalancerV2ExecutorTest is Test, Constants {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
BalancerV2ExecutorExposed balancerV2Exposed;
|
||||
@@ -37,12 +36,17 @@ contract BalancerV2ExecutorTest is
|
||||
function setUp() public {
|
||||
uint256 forkBlock = 17323404;
|
||||
vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock);
|
||||
balancerV2Exposed = new BalancerV2ExecutorExposed();
|
||||
balancerV2Exposed = new BalancerV2ExecutorExposed(PERMIT2_ADDRESS);
|
||||
}
|
||||
|
||||
function testDecodeParams() public view {
|
||||
bytes memory params = abi.encodePacked(
|
||||
WETH_ADDR, BAL_ADDR, WETH_BAL_POOL_ID, address(2), true
|
||||
WETH_ADDR,
|
||||
BAL_ADDR,
|
||||
WETH_BAL_POOL_ID,
|
||||
address(2),
|
||||
true,
|
||||
TokenTransfer.TransferType.NONE
|
||||
);
|
||||
|
||||
(
|
||||
@@ -50,7 +54,8 @@ contract BalancerV2ExecutorTest is
|
||||
IERC20 tokenOut,
|
||||
bytes32 poolId,
|
||||
address receiver,
|
||||
bool needsApproval
|
||||
bool needsApproval,
|
||||
TokenTransfer.TransferType transferType
|
||||
) = balancerV2Exposed.decodeParams(params);
|
||||
|
||||
assertEq(address(tokenIn), WETH_ADDR);
|
||||
@@ -58,6 +63,7 @@ contract BalancerV2ExecutorTest is
|
||||
assertEq(poolId, WETH_BAL_POOL_ID);
|
||||
assertEq(receiver, address(2));
|
||||
assertEq(needsApproval, true);
|
||||
assertEq(uint8(transferType), uint8(TokenTransfer.TransferType.NONE));
|
||||
}
|
||||
|
||||
function testDecodeParamsInvalidDataLength() public {
|
||||
@@ -70,8 +76,14 @@ contract BalancerV2ExecutorTest is
|
||||
|
||||
function testSwap() public {
|
||||
uint256 amountIn = 10 ** 18;
|
||||
bytes memory protocolData =
|
||||
abi.encodePacked(WETH_ADDR, BAL_ADDR, WETH_BAL_POOL_ID, BOB, true);
|
||||
bytes memory protocolData = abi.encodePacked(
|
||||
WETH_ADDR,
|
||||
BAL_ADDR,
|
||||
WETH_BAL_POOL_ID,
|
||||
BOB,
|
||||
true,
|
||||
TokenTransfer.TransferType.NONE
|
||||
);
|
||||
|
||||
deal(WETH_ADDR, address(balancerV2Exposed), amountIn);
|
||||
uint256 balanceBefore = BAL.balanceOf(BOB);
|
||||
@@ -86,14 +98,15 @@ contract BalancerV2ExecutorTest is
|
||||
function testDecodeIntegration() public view {
|
||||
// Generated by the SwapEncoder - test_encode_balancer_v2
|
||||
bytes memory protocolData =
|
||||
hex"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2ba100000625a3754423978a60c9317c58a424e3d5c6ee304399dbdb9c8ef030ab642b10820db8f560002000000000000000000141d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e01";
|
||||
hex"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2ba100000625a3754423978a60c9317c58a424e3d5c6ee304399dbdb9c8ef030ab642b10820db8f560002000000000000000000141d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e0105";
|
||||
|
||||
(
|
||||
IERC20 tokenIn,
|
||||
IERC20 tokenOut,
|
||||
bytes32 poolId,
|
||||
address receiver,
|
||||
bool needsApproval
|
||||
bool needsApproval,
|
||||
TokenTransfer.TransferType transferType
|
||||
) = balancerV2Exposed.decodeParams(protocolData);
|
||||
|
||||
assertEq(address(tokenIn), WETH_ADDR);
|
||||
@@ -101,12 +114,13 @@ contract BalancerV2ExecutorTest is
|
||||
assertEq(poolId, WETH_BAL_POOL_ID);
|
||||
assertEq(receiver, BOB);
|
||||
assertEq(needsApproval, true);
|
||||
assertEq(uint8(transferType), uint8(TokenTransfer.TransferType.NONE));
|
||||
}
|
||||
|
||||
function testSwapIntegration() public {
|
||||
// Generated by the SwapEncoder - test_encode_balancer_v2
|
||||
bytes memory protocolData =
|
||||
hex"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2ba100000625a3754423978a60c9317c58a424e3d5c6ee304399dbdb9c8ef030ab642b10820db8f560002000000000000000000141d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e01";
|
||||
hex"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2ba100000625a3754423978a60c9317c58a424e3d5c6ee304399dbdb9c8ef030ab642b10820db8f560002000000000000000000141d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e0105";
|
||||
|
||||
uint256 amountIn = 10 ** 18;
|
||||
deal(WETH_ADDR, address(balancerV2Exposed), amountIn);
|
||||
|
||||
@@ -22,7 +22,9 @@ interface MetaRegistry {
|
||||
}
|
||||
|
||||
contract CurveExecutorExposed is CurveExecutor {
|
||||
constructor(address _nativeToken) CurveExecutor(_nativeToken) {}
|
||||
constructor(address _nativeToken, address _permit2)
|
||||
CurveExecutor(_nativeToken, _permit2)
|
||||
{}
|
||||
|
||||
function decodeData(bytes calldata data)
|
||||
external
|
||||
@@ -34,7 +36,8 @@ contract CurveExecutorExposed is CurveExecutor {
|
||||
uint8 poolType,
|
||||
int128 i,
|
||||
int128 j,
|
||||
bool tokenApprovalNeeded
|
||||
bool tokenApprovalNeeded,
|
||||
TokenTransfer.TransferType transferType
|
||||
)
|
||||
{
|
||||
return _decodeData(data);
|
||||
@@ -50,7 +53,8 @@ contract CurveExecutorTest is Test, Constants {
|
||||
function setUp() public {
|
||||
uint256 forkBlock = 22031795;
|
||||
vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock);
|
||||
curveExecutorExposed = new CurveExecutorExposed(ETH_ADDR_FOR_CURVE);
|
||||
curveExecutorExposed =
|
||||
new CurveExecutorExposed(ETH_ADDR_FOR_CURVE, PERMIT2_ADDRESS);
|
||||
metaRegistry = MetaRegistry(CURVE_META_REGISTRY);
|
||||
}
|
||||
|
||||
@@ -62,7 +66,8 @@ contract CurveExecutorTest is Test, Constants {
|
||||
uint8(3),
|
||||
uint8(2),
|
||||
uint8(0),
|
||||
true
|
||||
true,
|
||||
TokenTransfer.TransferType.NONE
|
||||
);
|
||||
|
||||
(
|
||||
@@ -72,7 +77,8 @@ contract CurveExecutorTest is Test, Constants {
|
||||
uint8 poolType,
|
||||
int128 i,
|
||||
int128 j,
|
||||
bool tokenApprovalNeeded
|
||||
bool tokenApprovalNeeded,
|
||||
TokenTransfer.TransferType transferType
|
||||
) = curveExecutorExposed.decodeData(data);
|
||||
|
||||
assertEq(tokenIn, WETH_ADDR);
|
||||
@@ -82,6 +88,7 @@ contract CurveExecutorTest is Test, Constants {
|
||||
assertEq(i, 2);
|
||||
assertEq(j, 0);
|
||||
assertEq(tokenApprovalNeeded, true);
|
||||
assertEq(uint8(transferType), uint8(TokenTransfer.TransferType.NONE));
|
||||
}
|
||||
|
||||
function testTriPool() public {
|
||||
@@ -311,7 +318,8 @@ contract CurveExecutorTest is Test, Constants {
|
||||
poolType,
|
||||
uint8(uint256(uint128(i))),
|
||||
uint8(uint256(uint128(j))),
|
||||
true
|
||||
true,
|
||||
TokenTransfer.TransferType.NONE
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ contract UniswapV2ExecutorTest is Test, Constants, Permit2TestHelper {
|
||||
address(2),
|
||||
address(3),
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL
|
||||
);
|
||||
|
||||
(
|
||||
@@ -100,7 +100,8 @@ contract UniswapV2ExecutorTest is Test, Constants, Permit2TestHelper {
|
||||
assertEq(receiver, address(3));
|
||||
assertEq(zeroForOne, false);
|
||||
assertEq(
|
||||
uint8(TokenTransfer.TransferType.TRANSFER), uint8(transferType)
|
||||
uint8(TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL),
|
||||
uint8(transferType)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -157,7 +158,7 @@ contract UniswapV2ExecutorTest is Test, Constants, Permit2TestHelper {
|
||||
WETH_DAI_POOL,
|
||||
BOB,
|
||||
zeroForOne,
|
||||
uint8(TokenTransfer.TransferType.TRANSFER)
|
||||
uint8(TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL)
|
||||
);
|
||||
|
||||
deal(WETH_ADDR, address(uniswapV2Exposed), amountIn);
|
||||
@@ -176,7 +177,7 @@ contract UniswapV2ExecutorTest is Test, Constants, Permit2TestHelper {
|
||||
WETH_DAI_POOL,
|
||||
BOB,
|
||||
zeroForOne,
|
||||
uint8(TokenTransfer.TransferType.TRANSFERFROM)
|
||||
uint8(TokenTransfer.TransferType.TRANSFER_FROM_TO_PROTOCOL)
|
||||
);
|
||||
|
||||
deal(WETH_ADDR, address(this), amountIn);
|
||||
@@ -197,7 +198,7 @@ contract UniswapV2ExecutorTest is Test, Constants, Permit2TestHelper {
|
||||
WETH_DAI_POOL,
|
||||
ALICE,
|
||||
zeroForOne,
|
||||
uint8(TokenTransfer.TransferType.TRANSFERPERMIT2)
|
||||
uint8(TokenTransfer.TransferType.TRANSFER_PERMIT2_TO_PROTOCOL)
|
||||
);
|
||||
|
||||
deal(WETH_ADDR, ALICE, amountIn);
|
||||
@@ -283,7 +284,7 @@ contract UniswapV2ExecutorTest is Test, Constants, Permit2TestHelper {
|
||||
fakePool,
|
||||
BOB,
|
||||
zeroForOne,
|
||||
uint8(TokenTransfer.TransferType.TRANSFER)
|
||||
uint8(TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL)
|
||||
);
|
||||
|
||||
deal(WETH_ADDR, address(uniswapV2Exposed), amountIn);
|
||||
@@ -303,7 +304,7 @@ contract UniswapV2ExecutorTest is Test, Constants, Permit2TestHelper {
|
||||
USDC_MAG7_POOL,
|
||||
BOB,
|
||||
zeroForOne,
|
||||
uint8(TokenTransfer.TransferType.TRANSFER)
|
||||
uint8(TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL)
|
||||
);
|
||||
|
||||
deal(BASE_USDC, address(uniswapV2Exposed), amountIn);
|
||||
|
||||
@@ -71,7 +71,7 @@ contract UniswapV3ExecutorTest is Test, Constants, Permit2TestHelper {
|
||||
address(2),
|
||||
address(3),
|
||||
false,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL
|
||||
);
|
||||
|
||||
(
|
||||
@@ -91,7 +91,8 @@ contract UniswapV3ExecutorTest is Test, Constants, Permit2TestHelper {
|
||||
assertEq(target, address(3));
|
||||
assertEq(zeroForOne, false);
|
||||
assertEq(
|
||||
uint8(transferType), uint8(TokenTransfer.TransferType.TRANSFER)
|
||||
uint8(transferType),
|
||||
uint8(TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -123,7 +124,11 @@ contract UniswapV3ExecutorTest is Test, Constants, Permit2TestHelper {
|
||||
|
||||
vm.startPrank(DAI_WETH_USV3);
|
||||
bytes memory protocolData = abi.encodePacked(
|
||||
WETH_ADDR, DAI_ADDR, poolFee, TokenTransfer.TransferType.TRANSFER
|
||||
WETH_ADDR,
|
||||
DAI_ADDR,
|
||||
poolFee,
|
||||
TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL,
|
||||
address(uniswapV3Exposed)
|
||||
);
|
||||
uint256 dataOffset = 3; // some offset
|
||||
uint256 dataLength = protocolData.length;
|
||||
@@ -134,8 +139,7 @@ contract UniswapV3ExecutorTest is Test, Constants, Permit2TestHelper {
|
||||
int256(0), // amount1Delta
|
||||
dataOffset,
|
||||
dataLength,
|
||||
protocolData,
|
||||
address(uniswapV3Exposed) // transferFrom sender (irrelevant in this case)
|
||||
protocolData
|
||||
);
|
||||
uniswapV3Exposed.handleCallback(callbackData);
|
||||
vm.stopPrank();
|
||||
@@ -157,7 +161,7 @@ contract UniswapV3ExecutorTest is Test, Constants, Permit2TestHelper {
|
||||
address(this),
|
||||
fakePool,
|
||||
zeroForOne,
|
||||
TokenTransfer.TransferType.TRANSFER
|
||||
TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL
|
||||
);
|
||||
|
||||
vm.expectRevert(UniswapV3Executor__InvalidTarget.selector);
|
||||
|
||||
@@ -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_TO_PROTOCOL;
|
||||
|
||||
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,9 @@ 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 +124,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"4c9edd5852cd905f086c759e8383e09bff1e68b3dac17f958d2ee523a2206206994597c13d831ec70100dac17f958d2ee523a2206206994597c13d831ec7000064000001";
|
||||
uint256 amountIn = 100 ether;
|
||||
deal(USDE_ADDR, address(uniswapV4Exposed), amountIn);
|
||||
uint256 usdeBalanceBeforePool = USDE.balanceOf(poolManager);
|
||||
@@ -151,8 +161,9 @@ 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 +181,7 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
||||
// Generated by the Tycho swap encoder - test_encode_uniswap_v4_sequential_swap
|
||||
|
||||
bytes memory protocolData =
|
||||
hex"4c9edd5852cd905f086c759e8383e09bff1e68b32260fac5e5542a773aa44fbcfedf7c193bc2c59901dac17f958d2ee523a2206206994597c13d831ec70000640000012260fac5e5542a773aa44fbcfedf7c193bc2c599000bb800003c";
|
||||
hex"4c9edd5852cd905f086c759e8383e09bff1e68b32260fac5e5542a773aa44fbcfedf7c193bc2c5990100dac17f958d2ee523a2206206994597c13d831ec70000640000012260fac5e5542a773aa44fbcfedf7c193bc2c599000bb800003c";
|
||||
|
||||
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,8 @@ library UniswapV4Utils {
|
||||
);
|
||||
}
|
||||
|
||||
return abi.encodePacked(tokenIn, tokenOut, zeroForOne, encodedPools);
|
||||
return abi.encodePacked(
|
||||
tokenIn, tokenOut, zeroForOne, transferType, encodedPools
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,3 +17,23 @@ pub static GROUPABLE_PROTOCOLS: LazyLock<HashSet<&'static str>> = LazyLock::new(
|
||||
set.insert("ekubo_v2");
|
||||
set
|
||||
});
|
||||
|
||||
/// These protocols support the optimization of transferring straight from the user.
|
||||
pub static IN_TRANSFER_OPTIMIZABLE_PROTOCOLS: LazyLock<HashSet<&'static str>> =
|
||||
LazyLock::new(|| {
|
||||
let mut set = HashSet::new();
|
||||
set.insert("uniswap_v2");
|
||||
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("vm:curve");
|
||||
set.insert("balancer_v2");
|
||||
// TODO remove uniswap_v4 when we add callback support for transfer optimizations
|
||||
set.insert("uniswap_v4");
|
||||
set
|
||||
});
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
pub mod strategy_encoders;
|
||||
mod strategy_validators;
|
||||
|
||||
mod transfer_optimizations;
|
||||
|
||||
@@ -9,8 +9,9 @@ use crate::encoding::{
|
||||
evm::{
|
||||
approvals::permit2::Permit2,
|
||||
group_swaps::group_swaps,
|
||||
strategy_encoder::strategy_validators::{
|
||||
SequentialSwapValidator, SplitSwapValidator, SwapValidator,
|
||||
strategy_encoder::{
|
||||
strategy_validators::{SequentialSwapValidator, SplitSwapValidator, SwapValidator},
|
||||
transfer_optimizations::TransferOptimization,
|
||||
},
|
||||
swap_encoder::swap_encoder_registry::SwapEncoderRegistry,
|
||||
utils::{
|
||||
@@ -38,6 +39,8 @@ pub struct SingleSwapStrategyEncoder {
|
||||
swap_encoder_registry: SwapEncoderRegistry,
|
||||
permit2: Option<Permit2>,
|
||||
selector: String,
|
||||
native_address: Bytes,
|
||||
wrapped_address: Bytes,
|
||||
router_address: Bytes,
|
||||
}
|
||||
|
||||
@@ -56,7 +59,14 @@ 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()?,
|
||||
wrapped_address: chain.wrapped_token()?,
|
||||
router_address,
|
||||
})
|
||||
}
|
||||
|
||||
/// Encodes information necessary for performing a single hop against a given executor for
|
||||
@@ -69,6 +79,8 @@ impl SingleSwapStrategyEncoder {
|
||||
}
|
||||
}
|
||||
|
||||
impl TransferOptimization for SingleSwapStrategyEncoder {}
|
||||
|
||||
impl StrategyEncoder for SingleSwapStrategyEncoder {
|
||||
fn encode_strategy(&self, solution: Solution) -> Result<(Vec<u8>, Bytes), EncodingError> {
|
||||
let grouped_swaps = group_swaps(solution.clone().swaps);
|
||||
@@ -111,12 +123,22 @@ impl StrategyEncoder for SingleSwapStrategyEncoder {
|
||||
|
||||
let mut grouped_protocol_data: Vec<u8> = vec![];
|
||||
for swap in grouped_swap.swaps.iter() {
|
||||
let transfer_type = self.get_transfer_type(
|
||||
swap.clone(),
|
||||
solution.given_token.clone(),
|
||||
self.native_address.clone(),
|
||||
self.wrapped_address.clone(),
|
||||
self.permit2.clone().is_some(),
|
||||
wrap,
|
||||
);
|
||||
|
||||
let encoding_context = EncodingContext {
|
||||
receiver: self.router_address.clone(),
|
||||
exact_out: solution.exact_out,
|
||||
router_address: Some(self.router_address.clone()),
|
||||
group_token_in: grouped_swap.input_token.clone(),
|
||||
group_token_out: grouped_swap.output_token.clone(),
|
||||
transfer_type: transfer_type.clone(),
|
||||
};
|
||||
let protocol_data = swap_encoder.encode_swap(swap.clone(), encoding_context.clone())?;
|
||||
grouped_protocol_data.extend(protocol_data);
|
||||
@@ -199,6 +221,8 @@ pub struct SequentialSwapStrategyEncoder {
|
||||
sequential_swap_validator: SequentialSwapValidator,
|
||||
}
|
||||
|
||||
impl TransferOptimization for SequentialSwapStrategyEncoder {}
|
||||
|
||||
impl SequentialSwapStrategyEncoder {
|
||||
pub fn new(
|
||||
chain: Chain,
|
||||
@@ -274,12 +298,22 @@ impl StrategyEncoder for SequentialSwapStrategyEncoder {
|
||||
|
||||
let mut grouped_protocol_data: Vec<u8> = vec![];
|
||||
for swap in grouped_swap.swaps.iter() {
|
||||
let transfer_type = self.get_transfer_type(
|
||||
swap.clone(),
|
||||
solution.given_token.clone(),
|
||||
self.native_address.clone(),
|
||||
self.wrapped_address.clone(),
|
||||
self.permit2.clone().is_some(),
|
||||
wrap,
|
||||
);
|
||||
|
||||
let encoding_context = EncodingContext {
|
||||
receiver: self.router_address.clone(),
|
||||
exact_out: solution.exact_out,
|
||||
router_address: Some(self.router_address.clone()),
|
||||
group_token_in: grouped_swap.input_token.clone(),
|
||||
group_token_out: grouped_swap.output_token.clone(),
|
||||
transfer_type: transfer_type.clone(),
|
||||
};
|
||||
let protocol_data =
|
||||
swap_encoder.encode_swap(swap.clone(), encoding_context.clone())?;
|
||||
@@ -415,6 +449,8 @@ impl SplitSwapStrategyEncoder {
|
||||
}
|
||||
}
|
||||
|
||||
impl TransferOptimization for SplitSwapStrategyEncoder {}
|
||||
|
||||
impl StrategyEncoder for SplitSwapStrategyEncoder {
|
||||
fn encode_strategy(&self, solution: Solution) -> Result<(Vec<u8>, Bytes), EncodingError> {
|
||||
self.split_swap_validator
|
||||
@@ -491,12 +527,22 @@ impl StrategyEncoder for SplitSwapStrategyEncoder {
|
||||
|
||||
let mut grouped_protocol_data: Vec<u8> = vec![];
|
||||
for swap in grouped_swap.swaps.iter() {
|
||||
let transfer_type = self.get_transfer_type(
|
||||
swap.clone(),
|
||||
solution.given_token.clone(),
|
||||
self.native_address.clone(),
|
||||
self.wrapped_address.clone(),
|
||||
self.permit2.clone().is_some(),
|
||||
wrap,
|
||||
);
|
||||
|
||||
let encoding_context = EncodingContext {
|
||||
receiver: self.router_address.clone(),
|
||||
exact_out: solution.exact_out,
|
||||
router_address: Some(self.router_address.clone()),
|
||||
group_token_in: grouped_swap.input_token.clone(),
|
||||
group_token_out: grouped_swap.output_token.clone(),
|
||||
transfer_type: transfer_type.clone(),
|
||||
};
|
||||
let protocol_data =
|
||||
swap_encoder.encode_swap(swap.clone(), encoding_context.clone())?;
|
||||
@@ -722,7 +768,7 @@ mod tests {
|
||||
"a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id
|
||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver
|
||||
"00", // zero2one
|
||||
"00", // transfer type
|
||||
"02", // transfer type
|
||||
"00000000000000", // padding
|
||||
));
|
||||
let hex_calldata = encode(&calldata);
|
||||
@@ -825,11 +871,11 @@ mod tests {
|
||||
"a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id
|
||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver
|
||||
"00", // zero2one
|
||||
"00", // exact out
|
||||
"00", // transfer type
|
||||
"00000000000000000000000000", // padding
|
||||
"02", // transfer type
|
||||
"0000000000000000000000000000", // padding
|
||||
));
|
||||
let hex_calldata = encode(&calldata);
|
||||
println!("{}", hex_calldata);
|
||||
|
||||
assert_eq!(hex_calldata[..456], expected_input);
|
||||
assert_eq!(hex_calldata[1224..], expected_swap);
|
||||
@@ -1327,9 +1373,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
|
||||
@@ -1339,6 +1385,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
|
||||
@@ -1347,7 +1394,7 @@ mod tests {
|
||||
"6982508145454ce325ddbe47a25d4ec3d2311933", // intermediary token (PEPE)
|
||||
"0061a8", // fee
|
||||
"0001f4", // tick spacing
|
||||
"0000000000000000" // padding
|
||||
"00000000000000" // padding
|
||||
));
|
||||
|
||||
let hex_calldata = encode(&calldata);
|
||||
@@ -1484,9 +1531,8 @@ mod tests {
|
||||
"a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id
|
||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver
|
||||
"00", // zero2one
|
||||
"00", // exact out
|
||||
"00", // transfer type
|
||||
"00000000000000000000000000", // padding
|
||||
"01", // transfer type
|
||||
"0000000000000000000000000000", // padding
|
||||
]
|
||||
.join("");
|
||||
|
||||
@@ -1568,9 +1614,8 @@ mod tests {
|
||||
"a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id
|
||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver
|
||||
"00", // zero2one
|
||||
"00", // exact out
|
||||
"00", // transfer type
|
||||
"000000000000", // padding
|
||||
"01", // transfer type
|
||||
"00000000000000", // padding
|
||||
]
|
||||
.join("");
|
||||
|
||||
@@ -1821,7 +1866,7 @@ mod tests {
|
||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // router address
|
||||
"88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", // component id
|
||||
"01", // zero2one
|
||||
"00", // transfer type
|
||||
"02", // transfer type
|
||||
"006e", // ple encoded swaps
|
||||
"01", // token in index
|
||||
"00000000", // split
|
||||
@@ -1975,7 +2020,7 @@ mod tests {
|
||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // router address
|
||||
"88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", // component id
|
||||
"01", // zero2one
|
||||
"00", // transfer type
|
||||
"02", // transfer type
|
||||
"006e", // ple encoded swaps
|
||||
"00", // token in index
|
||||
"01", // token out index
|
||||
@@ -1987,7 +2032,7 @@ mod tests {
|
||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // router address
|
||||
"8ad599c3a0ff1de082011efddc58f1908eb6e6d8", // component id
|
||||
"01", // zero2one
|
||||
"00", // transfer type
|
||||
"02", // transfer type
|
||||
"0057", // ple encoded swaps
|
||||
"01", // token in index
|
||||
"00", // token out index
|
||||
@@ -2135,7 +2180,7 @@ mod tests {
|
||||
"b4e16d0168e52d35cacd2c6185b44281ec28c9dc", // component id
|
||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // router address
|
||||
"01", // zero2one
|
||||
"00", // transfer type
|
||||
"02", // transfer type
|
||||
"006e", // ple encoded swaps
|
||||
"01", // token in index
|
||||
"00", // token out index
|
||||
|
||||
173
src/encoding/evm/strategy_encoder/transfer_optimizations.rs
Normal file
173
src/encoding/evm/strategy_encoder/transfer_optimizations.rs
Normal file
@@ -0,0 +1,173 @@
|
||||
use tycho_common::Bytes;
|
||||
|
||||
use crate::encoding::{
|
||||
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.
|
||||
fn get_transfer_type(
|
||||
&self,
|
||||
swap: Swap,
|
||||
given_token: Bytes,
|
||||
native_token: Bytes,
|
||||
wrapped_token: Bytes,
|
||||
permit2: bool,
|
||||
wrap: bool,
|
||||
) -> TransferType {
|
||||
let send_funds_to_pool: bool =
|
||||
IN_TRANSFER_OPTIMIZABLE_PROTOCOLS.contains(&swap.component.protocol_system.as_str());
|
||||
let funds_expected_in_router: bool =
|
||||
PROTOCOLS_EXPECTING_FUNDS_IN_ROUTER.contains(&swap.component.protocol_system.as_str());
|
||||
|
||||
// In the case of wrapping, check if the swap's token in is the wrapped token to
|
||||
// determine if it's the first swap. Otherwise, compare to the given token.
|
||||
let is_first_swap =
|
||||
(swap.token_in == given_token) || ((swap.token_in == wrapped_token) && wrap);
|
||||
|
||||
if swap.token_in == native_token {
|
||||
// Funds are already in router. All protocols currently take care of native transfers.
|
||||
TransferType::None
|
||||
} else if is_first_swap && send_funds_to_pool {
|
||||
if permit2 {
|
||||
// Transfer from swapper to pool using permit2.
|
||||
TransferType::TransferPermit2ToProtocol
|
||||
} else {
|
||||
// Transfer from swapper to pool.
|
||||
TransferType::TransferFromToProtocol
|
||||
}
|
||||
} else if is_first_swap && funds_expected_in_router {
|
||||
if permit2 {
|
||||
// Transfer from swapper to router using permit2.
|
||||
TransferType::TransferPermit2ToRouter
|
||||
} else {
|
||||
// Transfer from swapper to router.
|
||||
TransferType::TransferFromToRouter
|
||||
}
|
||||
} else {
|
||||
TransferType::TransferToProtocol
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use alloy_primitives::hex;
|
||||
use tycho_common::{models::protocol::ProtocolComponent, Bytes};
|
||||
|
||||
use super::*;
|
||||
|
||||
struct MockStrategy {}
|
||||
impl TransferOptimization for MockStrategy {}
|
||||
|
||||
fn weth() -> Bytes {
|
||||
Bytes::from(hex!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2").to_vec())
|
||||
}
|
||||
|
||||
fn eth() -> Bytes {
|
||||
Bytes::from(hex!("0000000000000000000000000000000000000000").to_vec())
|
||||
}
|
||||
|
||||
fn dai() -> Bytes {
|
||||
Bytes::from(hex!("6b175474e89094c44da98b954eedeac495271d0f").to_vec())
|
||||
}
|
||||
|
||||
fn usdc() -> Bytes {
|
||||
Bytes::from(hex!("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48").to_vec())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_first_swap_transfer_from_permit2() {
|
||||
// The swap token is the same as the given token, which is not the native token
|
||||
let swap = Swap {
|
||||
component: ProtocolComponent {
|
||||
protocol_system: "uniswap_v2".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
token_in: weth(),
|
||||
token_out: dai(),
|
||||
split: 0f64,
|
||||
};
|
||||
let strategy = MockStrategy {};
|
||||
let transfer_method =
|
||||
strategy.get_transfer_type(swap.clone(), weth(), eth(), weth(), true, false);
|
||||
assert_eq!(transfer_method, TransferType::TransferPermit2ToProtocol);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_first_swap_transfer_from() {
|
||||
// The swap token is the same as the given token, which is not the native token
|
||||
let swap = Swap {
|
||||
component: ProtocolComponent {
|
||||
protocol_system: "uniswap_v2".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
token_in: weth(),
|
||||
token_out: dai(),
|
||||
split: 0f64,
|
||||
};
|
||||
let strategy = MockStrategy {};
|
||||
let transfer_method =
|
||||
strategy.get_transfer_type(swap.clone(), weth(), eth(), weth(), false, false);
|
||||
assert_eq!(transfer_method, TransferType::TransferFromToProtocol);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_first_swap_native() {
|
||||
// The swap token is the same as the given token, and it's the native token.
|
||||
// No transfer action is needed.
|
||||
let swap = Swap {
|
||||
component: ProtocolComponent {
|
||||
protocol_system: "uniswap_v2".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
token_in: eth(),
|
||||
token_out: dai(),
|
||||
split: 0f64,
|
||||
};
|
||||
let strategy = MockStrategy {};
|
||||
let transfer_method =
|
||||
strategy.get_transfer_type(swap.clone(), eth(), eth(), weth(), false, false);
|
||||
assert_eq!(transfer_method, TransferType::None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_first_swap_wrapped() {
|
||||
// The swap token is NOT the same as the given token, but we are wrapping.
|
||||
// Since the swap's token in is the wrapped token - this is the first swap.
|
||||
let swap = Swap {
|
||||
component: ProtocolComponent {
|
||||
protocol_system: "uniswap_v2".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
token_in: weth(),
|
||||
token_out: dai(),
|
||||
split: 0f64,
|
||||
};
|
||||
let strategy = MockStrategy {};
|
||||
let transfer_method =
|
||||
strategy.get_transfer_type(swap.clone(), eth(), eth(), weth(), false, true);
|
||||
assert_eq!(transfer_method, TransferType::TransferFromToProtocol);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_first_swap() {
|
||||
// The swap token is NOT the same as the given token, and we are NOT wrapping.
|
||||
// Thus, this is not the first swap.
|
||||
let swap = Swap {
|
||||
component: ProtocolComponent {
|
||||
protocol_system: "uniswap_v2".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
token_in: usdc(),
|
||||
token_out: dai(),
|
||||
split: 0f64,
|
||||
};
|
||||
let strategy = MockStrategy {};
|
||||
let transfer_method =
|
||||
strategy.get_transfer_type(swap.clone(), weth(), eth(), weth(), false, false);
|
||||
assert_eq!(transfer_method, TransferType::TransferToProtocol);
|
||||
}
|
||||
}
|
||||
@@ -22,15 +22,6 @@ use crate::encoding::{
|
||||
swap_encoder::SwapEncoder,
|
||||
};
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(u8)]
|
||||
pub enum TransferType {
|
||||
Transfer = 0,
|
||||
TransferFrom = 1,
|
||||
Permit2Transfer = 2,
|
||||
None = 3,
|
||||
}
|
||||
|
||||
/// Encodes a swap on a Uniswap V2 pool through the given executor address.
|
||||
///
|
||||
/// # Fields
|
||||
@@ -75,7 +66,7 @@ impl SwapEncoder for UniswapV2SwapEncoder {
|
||||
component_id,
|
||||
bytes_to_address(&encoding_context.receiver)?,
|
||||
zero_to_one,
|
||||
(TransferType::Transfer as u8).to_be_bytes(),
|
||||
(encoding_context.transfer_type as u8).to_be_bytes(),
|
||||
);
|
||||
|
||||
Ok(args.abi_encode_packed())
|
||||
@@ -138,7 +129,7 @@ impl SwapEncoder for UniswapV3SwapEncoder {
|
||||
bytes_to_address(&encoding_context.receiver)?,
|
||||
component_id,
|
||||
zero_to_one,
|
||||
(TransferType::Transfer as u8).to_be_bytes(),
|
||||
(encoding_context.transfer_type as u8).to_be_bytes(),
|
||||
);
|
||||
|
||||
Ok(args.abi_encode_packed())
|
||||
@@ -211,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())
|
||||
}
|
||||
@@ -284,6 +281,7 @@ impl SwapEncoder for BalancerV2SwapEncoder {
|
||||
component_id,
|
||||
bytes_to_address(&encoding_context.receiver)?,
|
||||
approval_needed,
|
||||
(encoding_context.transfer_type as u8).to_be_bytes(),
|
||||
);
|
||||
Ok(args.abi_encode_packed())
|
||||
}
|
||||
@@ -548,6 +546,7 @@ impl SwapEncoder for CurveSwapEncoder {
|
||||
i.to_be_bytes::<1>(),
|
||||
j.to_be_bytes::<1>(),
|
||||
approval_needed,
|
||||
(encoding_context.transfer_type as u8).to_be_bytes(),
|
||||
);
|
||||
|
||||
Ok(args.abi_encode_packed())
|
||||
@@ -573,6 +572,7 @@ mod tests {
|
||||
};
|
||||
|
||||
use super::*;
|
||||
use crate::encoding::models::TransferType;
|
||||
|
||||
#[test]
|
||||
fn test_encode_uniswap_v2() {
|
||||
@@ -595,6 +595,7 @@ mod tests {
|
||||
router_address: Some(Bytes::zero(20)),
|
||||
group_token_in: token_in.clone(),
|
||||
group_token_out: token_out.clone(),
|
||||
transfer_type: TransferType::TransferToProtocol,
|
||||
};
|
||||
let encoder = UniswapV2SwapEncoder::new(
|
||||
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
||||
@@ -648,6 +649,7 @@ mod tests {
|
||||
router_address: Some(Bytes::zero(20)),
|
||||
group_token_in: token_in.clone(),
|
||||
group_token_out: token_out.clone(),
|
||||
transfer_type: TransferType::TransferToProtocol,
|
||||
};
|
||||
let encoder = UniswapV3SwapEncoder::new(
|
||||
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
||||
@@ -702,6 +704,7 @@ mod tests {
|
||||
router_address: Some(Bytes::zero(20)),
|
||||
group_token_in: token_in.clone(),
|
||||
group_token_out: token_out.clone(),
|
||||
transfer_type: TransferType::None,
|
||||
};
|
||||
let encoder = BalancerV2SwapEncoder::new(
|
||||
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
||||
@@ -729,7 +732,9 @@ mod tests {
|
||||
// receiver
|
||||
"1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e",
|
||||
// approval needed
|
||||
"01"
|
||||
"01",
|
||||
// transfer type
|
||||
"05"
|
||||
))
|
||||
);
|
||||
}
|
||||
@@ -768,6 +773,7 @@ mod tests {
|
||||
|
||||
group_token_in: token_in.clone(),
|
||||
group_token_out: token_out.clone(),
|
||||
transfer_type: TransferType::TransferToProtocol,
|
||||
};
|
||||
let encoder = UniswapV4SwapEncoder::new(
|
||||
String::from("0xF62849F9A0B5Bf2913b396098F7c7019b51A820a"),
|
||||
@@ -790,6 +796,8 @@ mod tests {
|
||||
"dac17f958d2ee523a2206206994597c13d831ec7",
|
||||
// zero for one
|
||||
"01",
|
||||
// transfer type
|
||||
"00",
|
||||
// pool params:
|
||||
// - intermediary token
|
||||
"dac17f958d2ee523a2206206994597c13d831ec7",
|
||||
@@ -834,6 +842,7 @@ mod tests {
|
||||
group_token_in: group_token_in.clone(),
|
||||
// Token out is the same as the group token out
|
||||
group_token_out: token_out.clone(),
|
||||
transfer_type: TransferType::TransferToProtocol,
|
||||
};
|
||||
|
||||
let encoder = UniswapV4SwapEncoder::new(
|
||||
@@ -876,6 +885,7 @@ mod tests {
|
||||
router_address: Some(router_address.clone()),
|
||||
group_token_in: usde_address.clone(),
|
||||
group_token_out: wbtc_address.clone(),
|
||||
transfer_type: TransferType::TransferToProtocol,
|
||||
};
|
||||
|
||||
// Setup - First sequence: USDE -> USDT
|
||||
@@ -944,6 +954,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!(
|
||||
@@ -953,6 +964,8 @@ mod tests {
|
||||
"2260fac5e5542a773aa44fbcfedf7c193bc2c599",
|
||||
// zero for one
|
||||
"01",
|
||||
// transfer type
|
||||
"00",
|
||||
// pool params:
|
||||
// - intermediary token USDT
|
||||
"dac17f958d2ee523a2206206994597c13d831ec7",
|
||||
@@ -1004,6 +1017,7 @@ mod tests {
|
||||
group_token_out: token_out.clone(),
|
||||
exact_out: false,
|
||||
router_address: Some(Bytes::default()),
|
||||
transfer_type: TransferType::TransferToProtocol,
|
||||
};
|
||||
|
||||
let encoder =
|
||||
@@ -1046,6 +1060,7 @@ mod tests {
|
||||
group_token_out: group_token_out.clone(),
|
||||
exact_out: false,
|
||||
router_address: Some(Bytes::default()),
|
||||
transfer_type: TransferType::TransferToProtocol,
|
||||
};
|
||||
|
||||
let first_swap = Swap {
|
||||
@@ -1222,6 +1237,7 @@ mod tests {
|
||||
router_address: None,
|
||||
group_token_in: token_in.clone(),
|
||||
group_token_out: token_out.clone(),
|
||||
transfer_type: TransferType::None,
|
||||
};
|
||||
let encoder = CurveSwapEncoder::new(
|
||||
String::from("0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f"),
|
||||
@@ -1251,6 +1267,8 @@ mod tests {
|
||||
"01",
|
||||
// approval needed
|
||||
"01",
|
||||
// transfer type
|
||||
"05",
|
||||
))
|
||||
);
|
||||
}
|
||||
@@ -1287,6 +1305,7 @@ mod tests {
|
||||
router_address: None,
|
||||
group_token_in: token_in.clone(),
|
||||
group_token_out: token_out.clone(),
|
||||
transfer_type: TransferType::None,
|
||||
};
|
||||
let encoder = CurveSwapEncoder::new(
|
||||
String::from("0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f"),
|
||||
@@ -1316,6 +1335,8 @@ mod tests {
|
||||
"00",
|
||||
// approval needed
|
||||
"01",
|
||||
// transfer type
|
||||
"05",
|
||||
))
|
||||
);
|
||||
}
|
||||
@@ -1353,6 +1374,7 @@ mod tests {
|
||||
router_address: None,
|
||||
group_token_in: token_in.clone(),
|
||||
group_token_out: token_out.clone(),
|
||||
transfer_type: TransferType::None,
|
||||
};
|
||||
let encoder = CurveSwapEncoder::new(
|
||||
String::from("0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f"),
|
||||
@@ -1391,6 +1413,8 @@ mod tests {
|
||||
"01",
|
||||
// approval needed
|
||||
"01",
|
||||
// transfer type
|
||||
"05",
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::encoding::{
|
||||
},
|
||||
swap_encoder::swap_encoder_registry::SwapEncoderRegistry,
|
||||
},
|
||||
models::{Chain, EncodingContext, NativeAction, Solution, Transaction},
|
||||
models::{Chain, EncodingContext, NativeAction, Solution, Transaction, TransferType},
|
||||
strategy_encoder::StrategyEncoder,
|
||||
tycho_encoder::TychoEncoder,
|
||||
};
|
||||
@@ -201,9 +201,10 @@ impl TychoEncoder for TychoRouterEncoder {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an encoder for one swap to be executed directly against an Executor. This is useful
|
||||
/// when you want to bypass the Tycho Router, use your own Router contract and just need the
|
||||
/// calldata for a particular swap.
|
||||
/// Represents an encoder for one swap to be executed directly against an Executor.
|
||||
///
|
||||
/// This is useful when you want to bypass the Tycho Router, use your own Router contract and
|
||||
/// just need the calldata for a particular swap.
|
||||
///
|
||||
/// # Fields
|
||||
/// * `swap_encoder_registry`: Registry of swap encoders
|
||||
@@ -259,6 +260,7 @@ impl TychoExecutorEncoder {
|
||||
router_address: None,
|
||||
group_token_in: grouped_swap.input_token.clone(),
|
||||
group_token_out: grouped_swap.output_token.clone(),
|
||||
transfer_type: TransferType::TransferToProtocol,
|
||||
};
|
||||
let protocol_data = swap_encoder.encode_swap(swap.clone(), encoding_context.clone())?;
|
||||
grouped_protocol_data.extend(protocol_data);
|
||||
@@ -1046,6 +1048,8 @@ mod tests {
|
||||
"6982508145454ce325ddbe47a25d4ec3d2311933",
|
||||
// zero for one
|
||||
"00",
|
||||
// transfer type
|
||||
"00",
|
||||
// first pool intermediary token (ETH)
|
||||
"0000000000000000000000000000000000000000",
|
||||
// fee
|
||||
|
||||
@@ -96,6 +96,27 @@ pub struct Transaction {
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
/// Represents the type of transfer to be performed into the pool.
|
||||
///
|
||||
/// # Fields
|
||||
///
|
||||
/// * `TransferToProtocol`: Transfer the token from the router into the protocol.
|
||||
/// * `TransferFromToProtocol`: Transfer the token from the sender to the protocol.
|
||||
/// * `TransferPermit2ToProtocol`: Transfer the token from the sender to the protocol using Permit2.
|
||||
/// * `TransferFromToRouter`: Transfer the token from the sender to the router.
|
||||
/// * `TransferPermit2ToRouter`: Transfer the token from the sender to the router using Permit2.
|
||||
/// * `None`: No transfer is needed. Tokens are already in the pool.
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum TransferType {
|
||||
TransferToProtocol = 0,
|
||||
TransferFromToProtocol = 1,
|
||||
TransferPermit2ToProtocol = 2,
|
||||
TransferFromToRouter = 3,
|
||||
TransferPermit2ToRouter = 4,
|
||||
None = 5,
|
||||
}
|
||||
|
||||
/// Represents necessary attributes for encoding an order.
|
||||
///
|
||||
/// # Fields
|
||||
@@ -113,6 +134,7 @@ pub struct EncodingContext {
|
||||
pub router_address: Option<Bytes>,
|
||||
pub group_token_in: Bytes,
|
||||
pub group_token_out: Bytes,
|
||||
pub transfer_type: TransferType,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
|
||||
Reference in New Issue
Block a user