diff --git a/foundry/src/executors/UniswapV4Executor.sol b/foundry/src/executors/UniswapV4Executor.sol index 56bacf5..ad15503 100644 --- a/foundry/src/executors/UniswapV4Executor.sol +++ b/foundry/src/executors/UniswapV4Executor.sol @@ -80,18 +80,6 @@ contract UniswapV4Executor is address receiver, 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({ @@ -106,6 +94,8 @@ contract UniswapV4Executor is key, zeroForOne, amountIn, + msg.sender, + transferType, receiver, bytes("") ); @@ -127,6 +117,8 @@ contract UniswapV4Executor is currencyIn, path, amountIn, + msg.sender, + transferType, receiver ); } @@ -240,6 +232,8 @@ contract UniswapV4Executor is * @param poolKey The key of the pool to swap in. * @param zeroForOne Whether the swap is from token0 to token1 (true) or vice versa (false). * @param amountIn The amount of tokens to swap in. + * @param sender The address of the sender. + * @param transferType The type of transfer in to use. * @param receiver The address of the receiver. * @param hookData Additional data for hook contracts. */ @@ -247,6 +241,8 @@ contract UniswapV4Executor is PoolKey memory poolKey, bool zeroForOne, uint128 amountIn, + address sender, + TransferType transferType, address receiver, bytes calldata hookData ) external returns (uint128) { @@ -259,7 +255,7 @@ contract UniswapV4Executor is if (amount > amountIn) { revert UniswapV4Executor__V4TooMuchRequested(amountIn, amount); } - _settle(currencyIn, address(this), amount); + _settle(currencyIn, amount, sender, transferType); Currency currencyOut = zeroForOne ? poolKey.currency1 : poolKey.currency0; @@ -272,12 +268,16 @@ contract UniswapV4Executor is * @param currencyIn The currency of the input token. * @param path The path to swap along. * @param amountIn The amount of tokens to swap in. + * @param sender The address of the sender. + * @param transferType The type of transfer in to use. * @param receiver The address of the receiver. */ function swapExactInput( Currency currencyIn, PathKey[] calldata path, uint128 amountIn, + address sender, + TransferType transferType, address receiver ) external returns (uint128) { uint128 amountOut = 0; @@ -308,7 +308,7 @@ contract UniswapV4Executor is if (amount > amountIn) { revert UniswapV4Executor__V4TooMuchRequested(amountIn, amount); } - _settle(currencyIn, address(this), amount); + _settle(currencyIn, amount, sender, transferType); _take( swapCurrencyIn, // at the end of the loop this is actually currency out @@ -379,32 +379,35 @@ contract UniswapV4Executor is * @notice Pays and settles a currency to the pool manager. * @dev The implementing contract must ensure that the `payer` is a secure address. * @param currency The currency to settle. - * @param payer The address of the payer. * @param amount The amount to send. + * @param sender The address of the payer. + * @param transferType The type of transfer to use. * @dev Returns early if the amount is 0. */ - function _settle(Currency currency, address payer, uint256 amount) - internal - { + function _settle( + Currency currency, + uint256 amount, + address sender, + TransferType transferType + ) internal { if (amount == 0) return; - poolManager.sync(currency); if (currency.isAddressZero()) { // slither-disable-next-line unused-return poolManager.settle{value: amount}(); } else { - _pay(currency, payer, amount); + _transfer( + Currency.unwrap(currency), + sender, + address(poolManager), + amount, + transferType + ); // slither-disable-next-line unused-return poolManager.settle(); } } - function _pay(Currency token, address, uint256 amount) internal { - IERC20(Currency.unwrap(token)).safeTransfer( - address(poolManager), amount - ); - } - /** * @notice Takes an amount of currency out of the pool manager. * @param currency The currency to take. diff --git a/foundry/test/TychoRouterIntegration.t.sol b/foundry/test/TychoRouterIntegration.t.sol new file mode 100644 index 0000000..e69de29 diff --git a/foundry/test/TychoRouterSplitSwap.t.sol b/foundry/test/TychoRouterSplitSwap.t.sol index b086c6e..b26e16e 100644 --- a/foundry/test/TychoRouterSplitSwap.t.sol +++ b/foundry/test/TychoRouterSplitSwap.t.sol @@ -427,7 +427,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { USDE_ADDR, USDT_ADDR, true, - TokenTransfer.TransferType.TRANSFER_PERMIT2_TO_ROUTER, + TokenTransfer.TransferType.TRANSFER_PERMIT2_TO_PROTOCOL, ALICE, pools ); @@ -480,7 +480,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { USDE_ADDR, WBTC_ADDR, true, - TokenTransfer.TransferType.NONE, + TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL, ALICE, pools ); diff --git a/foundry/test/executors/UniswapV4Executor.t.sol b/foundry/test/executors/UniswapV4Executor.t.sol index 9ff7f72..17acd0a 100644 --- a/foundry/test/executors/UniswapV4Executor.t.sol +++ b/foundry/test/executors/UniswapV4Executor.t.sol @@ -114,7 +114,7 @@ contract UniswapV4ExecutorTest is Test, Constants { USDE_ADDR, USDT_ADDR, true, - TokenTransfer.TransferType.NONE, + TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL, ALICE, pools ); @@ -172,7 +172,7 @@ contract UniswapV4ExecutorTest is Test, Constants { USDE_ADDR, WBTC_ADDR, true, - TokenTransfer.TransferType.NONE, + TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL, ALICE, pools ); diff --git a/src/encoding/evm/constants.rs b/src/encoding/evm/constants.rs index 1ac6bb3..d4a4863 100644 --- a/src/encoding/evm/constants.rs +++ b/src/encoding/evm/constants.rs @@ -28,6 +28,7 @@ pub static IN_TRANSFER_REQUIRED_PROTOCOLS: LazyLock> = Laz set.insert("pancakeswap_v2"); set.insert("uniswap_v3"); set.insert("pancakeswap_v3"); + set.insert("uniswap_v4"); set.insert("ekubo_v2"); set }); diff --git a/src/encoding/evm/strategy_encoder/strategy_encoders.rs b/src/encoding/evm/strategy_encoder/strategy_encoders.rs index 950c721..7dd7afd 100644 --- a/src/encoding/evm/strategy_encoder/strategy_encoders.rs +++ b/src/encoding/evm/strategy_encoder/strategy_encoders.rs @@ -2314,7 +2314,7 @@ mod tests { "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // group token in "6982508145454ce325ddbe47a25d4ec3d2311933", // group token in "00", // zero2one - "04", // transfer type (transfer to router) + "02", // transfer type (transfer to router) "cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // receiver // First pool params "0000000000000000000000000000000000000000", // intermediary token (ETH)