feat: Support using the TransferType in uniswap v4

Update tests

--- don't change below this line ---
ENG-4437 Took 1 hour 3 minutes

Took 2 minutes
This commit is contained in:
Diana Carvalho
2025-04-17 17:06:29 +01:00
parent cd608cb8e9
commit 4a61de56b7
6 changed files with 35 additions and 31 deletions

View File

@@ -80,18 +80,6 @@ contract UniswapV4Executor is
address receiver, address receiver,
UniswapV4Executor.UniswapV4Pool[] memory pools UniswapV4Executor.UniswapV4Pool[] memory pools
) = _decodeData(data); ) = _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; bytes memory swapData;
if (pools.length == 1) { if (pools.length == 1) {
PoolKey memory key = PoolKey({ PoolKey memory key = PoolKey({
@@ -106,6 +94,8 @@ contract UniswapV4Executor is
key, key,
zeroForOne, zeroForOne,
amountIn, amountIn,
msg.sender,
transferType,
receiver, receiver,
bytes("") bytes("")
); );
@@ -127,6 +117,8 @@ contract UniswapV4Executor is
currencyIn, currencyIn,
path, path,
amountIn, amountIn,
msg.sender,
transferType,
receiver receiver
); );
} }
@@ -240,6 +232,8 @@ contract UniswapV4Executor is
* @param poolKey The key of the pool to swap in. * @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 zeroForOne Whether the swap is from token0 to token1 (true) or vice versa (false).
* @param amountIn The amount of tokens to swap in. * @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 receiver The address of the receiver.
* @param hookData Additional data for hook contracts. * @param hookData Additional data for hook contracts.
*/ */
@@ -247,6 +241,8 @@ contract UniswapV4Executor is
PoolKey memory poolKey, PoolKey memory poolKey,
bool zeroForOne, bool zeroForOne,
uint128 amountIn, uint128 amountIn,
address sender,
TransferType transferType,
address receiver, address receiver,
bytes calldata hookData bytes calldata hookData
) external returns (uint128) { ) external returns (uint128) {
@@ -259,7 +255,7 @@ contract UniswapV4Executor is
if (amount > amountIn) { if (amount > amountIn) {
revert UniswapV4Executor__V4TooMuchRequested(amountIn, amount); revert UniswapV4Executor__V4TooMuchRequested(amountIn, amount);
} }
_settle(currencyIn, address(this), amount); _settle(currencyIn, amount, sender, transferType);
Currency currencyOut = Currency currencyOut =
zeroForOne ? poolKey.currency1 : poolKey.currency0; zeroForOne ? poolKey.currency1 : poolKey.currency0;
@@ -272,12 +268,16 @@ contract UniswapV4Executor is
* @param currencyIn The currency of the input token. * @param currencyIn The currency of the input token.
* @param path The path to swap along. * @param path The path to swap along.
* @param amountIn The amount of tokens to swap in. * @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 receiver The address of the receiver.
*/ */
function swapExactInput( function swapExactInput(
Currency currencyIn, Currency currencyIn,
PathKey[] calldata path, PathKey[] calldata path,
uint128 amountIn, uint128 amountIn,
address sender,
TransferType transferType,
address receiver address receiver
) external returns (uint128) { ) external returns (uint128) {
uint128 amountOut = 0; uint128 amountOut = 0;
@@ -308,7 +308,7 @@ contract UniswapV4Executor is
if (amount > amountIn) { if (amount > amountIn) {
revert UniswapV4Executor__V4TooMuchRequested(amountIn, amount); revert UniswapV4Executor__V4TooMuchRequested(amountIn, amount);
} }
_settle(currencyIn, address(this), amount); _settle(currencyIn, amount, sender, transferType);
_take( _take(
swapCurrencyIn, // at the end of the loop this is actually currency out 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. * @notice Pays and settles a currency to the pool manager.
* @dev The implementing contract must ensure that the `payer` is a secure address. * @dev The implementing contract must ensure that the `payer` is a secure address.
* @param currency The currency to settle. * @param currency The currency to settle.
* @param payer The address of the payer.
* @param amount The amount to send. * @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. * @dev Returns early if the amount is 0.
*/ */
function _settle(Currency currency, address payer, uint256 amount) function _settle(
internal Currency currency,
{ uint256 amount,
address sender,
TransferType transferType
) internal {
if (amount == 0) return; if (amount == 0) return;
poolManager.sync(currency); poolManager.sync(currency);
if (currency.isAddressZero()) { if (currency.isAddressZero()) {
// slither-disable-next-line unused-return // slither-disable-next-line unused-return
poolManager.settle{value: amount}(); poolManager.settle{value: amount}();
} else { } else {
_pay(currency, payer, amount); _transfer(
Currency.unwrap(currency),
sender,
address(poolManager),
amount,
transferType
);
// slither-disable-next-line unused-return // slither-disable-next-line unused-return
poolManager.settle(); 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. * @notice Takes an amount of currency out of the pool manager.
* @param currency The currency to take. * @param currency The currency to take.

View File

@@ -427,7 +427,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
USDE_ADDR, USDE_ADDR,
USDT_ADDR, USDT_ADDR,
true, true,
TokenTransfer.TransferType.TRANSFER_PERMIT2_TO_ROUTER, TokenTransfer.TransferType.TRANSFER_PERMIT2_TO_PROTOCOL,
ALICE, ALICE,
pools pools
); );
@@ -480,7 +480,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
USDE_ADDR, USDE_ADDR,
WBTC_ADDR, WBTC_ADDR,
true, true,
TokenTransfer.TransferType.NONE, TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL,
ALICE, ALICE,
pools pools
); );

View File

@@ -114,7 +114,7 @@ contract UniswapV4ExecutorTest is Test, Constants {
USDE_ADDR, USDE_ADDR,
USDT_ADDR, USDT_ADDR,
true, true,
TokenTransfer.TransferType.NONE, TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL,
ALICE, ALICE,
pools pools
); );
@@ -172,7 +172,7 @@ contract UniswapV4ExecutorTest is Test, Constants {
USDE_ADDR, USDE_ADDR,
WBTC_ADDR, WBTC_ADDR,
true, true,
TokenTransfer.TransferType.NONE, TokenTransfer.TransferType.TRANSFER_TO_PROTOCOL,
ALICE, ALICE,
pools pools
); );

View File

@@ -28,6 +28,7 @@ pub static IN_TRANSFER_REQUIRED_PROTOCOLS: LazyLock<HashSet<&'static str>> = Laz
set.insert("pancakeswap_v2"); set.insert("pancakeswap_v2");
set.insert("uniswap_v3"); set.insert("uniswap_v3");
set.insert("pancakeswap_v3"); set.insert("pancakeswap_v3");
set.insert("uniswap_v4");
set.insert("ekubo_v2"); set.insert("ekubo_v2");
set set
}); });

View File

@@ -2314,7 +2314,7 @@ mod tests {
"a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // group token in "a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // group token in
"6982508145454ce325ddbe47a25d4ec3d2311933", // group token in "6982508145454ce325ddbe47a25d4ec3d2311933", // group token in
"00", // zero2one "00", // zero2one
"04", // transfer type (transfer to router) "02", // transfer type (transfer to router)
"cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // receiver "cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2", // receiver
// First pool params // First pool params
"0000000000000000000000000000000000000000", // intermediary token (ETH) "0000000000000000000000000000000000000000", // intermediary token (ETH)