From 3dc057219444be7d1b59f0fc559d6d99299b17fa Mon Sep 17 00:00:00 2001 From: happenwah Date: Mon, 2 Jun 2025 12:45:52 +0100 Subject: [PATCH] chore: update interfaces to include off-chain code and emit in swap events --- src/swap-router/ValantisSwapRouter.sol | 148 +++++++++--------- .../interfaces/IValantisSwapRouter.sol | 6 +- .../structs/ValantisSwapRouterStructs.sol | 2 + test/SwapRouter.t.sol | 75 ++++++--- 4 files changed, 133 insertions(+), 98 deletions(-) diff --git a/src/swap-router/ValantisSwapRouter.sol b/src/swap-router/ValantisSwapRouter.sol index d8c246f..6ffa554 100644 --- a/src/swap-router/ValantisSwapRouter.sol +++ b/src/swap-router/ValantisSwapRouter.sol @@ -1,28 +1,28 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import { SafeCast } from '@valantis-core/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol'; -import { IERC20 } from '@valantis-core/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol'; -import { SafeERC20 } from '@valantis-core/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol'; -import { IUniversalPool } from '@valantis-core/src/pools/interfaces/IUniversalPool.sol'; -import { ISovereignPool } from '@valantis-core/src/pools/interfaces/ISovereignPool.sol'; +import {SafeCast} from "@valantis-core/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +import {IERC20} from "@valantis-core/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "@valantis-core/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IUniversalPool} from "@valantis-core/src/pools/interfaces/IUniversalPool.sol"; +import {ISovereignPool} from "@valantis-core/src/pools/interfaces/ISovereignPool.sol"; import { SovereignPoolSwapContextData, SovereignPoolSwapParams -} from '@valantis-core/src/pools/structs/SovereignPoolStructs.sol'; -import { SwapParams } from '@valantis-core/src/pools/structs/UniversalPoolStructs.sol'; -import { ReentrancyGuard } from '@valantis-core/src/utils/ReentrancyGuard.sol'; - -import { EIP712 } from './EIP712.sol'; -import { SignatureVerification } from './libraries/SignatureVerification.sol'; -import { IWETH9 } from './interfaces/IWETH9.sol'; -import { IProtocolFactory } from '../../lib/valantis-core/src/protocol-factory/interfaces/IProtocolFactory.sol'; -import { IAllowanceTransfer } from './interfaces/IAllowanceTransfer.sol'; -import { IValantisSwapRouter } from './interfaces/IValantisSwapRouter.sol'; -import { GaslessSwapIntentHash } from './libraries/GaslessSwapIntentHash.sol'; -import { GaslessSwap } from './libraries/GaslessSwap.sol'; -import { DirectSwap } from './libraries/DirectSwap.sol'; -import { NonceBitmap } from './libraries/NonceBitmap.sol'; +} from "@valantis-core/src/pools/structs/SovereignPoolStructs.sol"; +import {SwapParams} from "@valantis-core/src/pools/structs/UniversalPoolStructs.sol"; +import {ReentrancyGuard} from "@valantis-core/src/utils/ReentrancyGuard.sol"; + +import {EIP712} from "./EIP712.sol"; +import {SignatureVerification} from "./libraries/SignatureVerification.sol"; +import {IWETH9} from "./interfaces/IWETH9.sol"; +import {IProtocolFactory} from "../../lib/valantis-core/src/protocol-factory/interfaces/IProtocolFactory.sol"; +import {IAllowanceTransfer} from "./interfaces/IAllowanceTransfer.sol"; +import {IValantisSwapRouter} from "./interfaces/IValantisSwapRouter.sol"; +import {GaslessSwapIntentHash} from "./libraries/GaslessSwapIntentHash.sol"; +import {GaslessSwap} from "./libraries/GaslessSwap.sol"; +import {DirectSwap} from "./libraries/DirectSwap.sol"; +import {NonceBitmap} from "./libraries/NonceBitmap.sol"; import { GaslessSwapParams, GaslessSwapIntent, @@ -30,7 +30,7 @@ import { ExecuteSwapParams, UniversalPoolSwapPayload, SovereignPoolSwapPayload -} from './structs/ValantisSwapRouterStructs.sol'; +} from "./structs/ValantisSwapRouterStructs.sol"; contract ValantisSwapRouter is IValantisSwapRouter, EIP712, ReentrancyGuard { using GaslessSwapIntentHash for GaslessSwapIntent; @@ -172,11 +172,10 @@ contract ValantisSwapRouter is IValantisSwapRouter, EIP712, ReentrancyGuard { * @param _amountInUsed Amount of input token used. * @param _swapCallbackContext Bytes encoded data required to execute the callback. */ - function universalPoolSwapCallback( - address _tokenIn, - uint256 _amountInUsed, - bytes calldata _swapCallbackContext - ) external override { + function universalPoolSwapCallback(address _tokenIn, uint256 _amountInUsed, bytes calldata _swapCallbackContext) + external + override + { if (msg.sender != allowedUniversalPool) { revert ValantisSwapRouter__universalPoolSwapCallback_poolNotAllowed(); } @@ -197,11 +196,10 @@ contract ValantisSwapRouter is IValantisSwapRouter, EIP712, ReentrancyGuard { * @param _amountInUsed Amount of input token used. * @param _swapCallbackContext Bytes encoded data required to execute the callback. */ - function sovereignPoolSwapCallback( - address _tokenIn, - uint256 _amountInUsed, - bytes calldata _swapCallbackContext - ) external override { + function sovereignPoolSwapCallback(address _tokenIn, uint256 _amountInUsed, bytes calldata _swapCallbackContext) + external + override + { if (msg.sender != allowedSovereignPool) { revert ValantisSwapRouter__sovereignPoolSwapCallback_poolNotAllowed(); } @@ -225,11 +223,12 @@ contract ValantisSwapRouter is IValantisSwapRouter, EIP712, ReentrancyGuard { * @param _fee Fee to be charged for this transaction in feeToken. * @dev `_fee` must not exceed maxFee. */ - function gaslessSwap( - GaslessSwapParams calldata _gaslessSwapParams, - bytes calldata _ownerSignature, - uint128 _fee - ) external override nonReentrant returns (uint256 amountOut) { + function gaslessSwap(GaslessSwapParams calldata _gaslessSwapParams, bytes calldata _ownerSignature, uint128 _fee) + external + override + nonReentrant + returns (uint256 amountOut) + { amountOut = _gaslessSwap(_gaslessSwapParams, _ownerSignature, _fee); } @@ -248,15 +247,15 @@ contract ValantisSwapRouter is IValantisSwapRouter, EIP712, ReentrancyGuard { ) external override nonReentrant returns (uint256[] memory amountOutArray) { // Array length consistency if ( - _gaslessSwapParamsArray.length != _ownerSignaturesArray.length || - _ownerSignaturesArray.length != _feeArray.length + _gaslessSwapParamsArray.length != _ownerSignaturesArray.length + || _ownerSignaturesArray.length != _feeArray.length ) { revert ValantisSwapRouter__batchGaslessSwaps_invalidArrayLengths(); } uint256 length = _gaslessSwapParamsArray.length; amountOutArray = new uint256[](length); - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { amountOutArray[i] = _gaslessSwap(_gaslessSwapParamsArray[i], _ownerSignaturesArray[i], _feeArray[i]); unchecked { @@ -270,9 +269,13 @@ contract ValantisSwapRouter is IValantisSwapRouter, EIP712, ReentrancyGuard { * @param _directSwapParams Struct containing all relevant parameters to execute the swap(s). * @return amountOut Amount of output token. */ - function swap( - DirectSwapParams calldata _directSwapParams - ) external payable override nonReentrant returns (uint256 amountOut) { + function swap(DirectSwapParams calldata _directSwapParams) + external + payable + override + nonReentrant + returns (uint256 amountOut) + { // WETH related checks if (msg.value > 0 && _directSwapParams.tokenIn != WETH9) { revert ValantisSwapRouter__swap_invalidNativeTokenSwap(); @@ -302,11 +305,9 @@ contract ValantisSwapRouter is IValantisSwapRouter, EIP712, ReentrancyGuard { }) ); - amountOut = - IERC20(_directSwapParams.tokenOut).balanceOf( - _directSwapParams.isTokenOutEth ? address(this) : _directSwapParams.recipient - ) - - tokenOutPreBalance; + amountOut = IERC20(_directSwapParams.tokenOut).balanceOf( + _directSwapParams.isTokenOutEth ? address(this) : _directSwapParams.recipient + ) - tokenOutPreBalance; if (amountOut < _directSwapParams.amountOutMin || amountOutTotal < _directSwapParams.amountOutMin) { revert ValantisSwapRouter__swap_insufficientAmountOut(); @@ -329,7 +330,8 @@ contract ValantisSwapRouter is IValantisSwapRouter, EIP712, ReentrancyGuard { amountInTotal, amountOut, msg.value > 0, - _directSwapParams.isTokenOutEth + _directSwapParams.isTokenOutEth, + _directSwapParams.code ); } @@ -358,31 +360,33 @@ contract ValantisSwapRouter is IValantisSwapRouter, EIP712, ReentrancyGuard { * PRIVATE FUNCTIONS * */ - function _gaslessSwap( - GaslessSwapParams calldata gaslessSwapParams, - bytes calldata ownerSignature, - uint128 fee - ) private returns (uint256 amountOut) { + function _gaslessSwap(GaslessSwapParams calldata gaslessSwapParams, bytes calldata ownerSignature, uint128 fee) + private + returns (uint256 amountOut) + { if (gaslessSwapParams.intent.isTokenOutEth && gaslessSwapParams.intent.tokenOut != WETH9) { revert ValantisSwapRouter___gaslessSwap_tokenOutNotWeth(); } - uint256 tokenOutPreBalance = IERC20(gaslessSwapParams.intent.tokenOut).balanceOf( - gaslessSwapParams.intent.isTokenOutEth ? address(this) : gaslessSwapParams.intent.recipient - ); + uint256 amountInTotal; + uint256 amountOutTotal; + { + uint256 tokenOutPreBalance = IERC20(gaslessSwapParams.intent.tokenOut).balanceOf( + gaslessSwapParams.intent.isTokenOutEth ? address(this) : gaslessSwapParams.intent.recipient + ); - (uint256 amountInTotal, uint256 amountOutTotal) = _executeGaslessSwap(gaslessSwapParams, ownerSignature, fee); + (amountInTotal, amountOutTotal) = _executeGaslessSwap(gaslessSwapParams, ownerSignature, fee); - amountOut = - IERC20(gaslessSwapParams.intent.tokenOut).balanceOf( + amountOut = IERC20(gaslessSwapParams.intent.tokenOut).balanceOf( gaslessSwapParams.intent.isTokenOutEth ? address(this) : gaslessSwapParams.intent.recipient - ) - - tokenOutPreBalance; + ) - tokenOutPreBalance; - if ( - amountOut < gaslessSwapParams.intent.amountOutMin || amountOutTotal < gaslessSwapParams.intent.amountOutMin - ) { - revert ValantisSwapRouter___gaslessSwap_insufficientAmountOut(); + if ( + amountOut < gaslessSwapParams.intent.amountOutMin + || amountOutTotal < gaslessSwapParams.intent.amountOutMin + ) { + revert ValantisSwapRouter___gaslessSwap_insufficientAmountOut(); + } } if (gaslessSwapParams.intent.isTokenOutEth) { @@ -399,7 +403,8 @@ contract ValantisSwapRouter is IValantisSwapRouter, EIP712, ReentrancyGuard { gaslessSwapParams.intent.tokenOut, amountInTotal, amountOut, - gaslessSwapParams.intent.isTokenOutEth + gaslessSwapParams.intent.isTokenOutEth, + gaslessSwapParams.code ); } @@ -444,9 +449,10 @@ contract ValantisSwapRouter is IValantisSwapRouter, EIP712, ReentrancyGuard { } } - function _executeSwaps( - ExecuteSwapParams memory params - ) private returns (uint256 amountInTotal, uint256 amountOutTotal) { + function _executeSwaps(ExecuteSwapParams memory params) + private + returns (uint256 amountInTotal, uint256 amountOutTotal) + { uint256 amountOutSwap; // First swap's amountIn must be specified by owner @@ -454,7 +460,7 @@ contract ValantisSwapRouter is IValantisSwapRouter, EIP712, ReentrancyGuard { revert ValantisSwapRouter___executeSwaps_invalidAmountSpecifiedFirstSwap(); } - for (uint256 i; i < params.pools.length; ) { + for (uint256 i; i < params.pools.length;) { uint256 amountInUsed; address tokenOutSwap; (amountInUsed, tokenOutSwap, amountOutSwap) = params.isUniversalPool[i] @@ -563,7 +569,7 @@ contract ValantisSwapRouter is IValantisSwapRouter, EIP712, ReentrancyGuard { function _executeTransfer(address token, address payer, address recipient, uint256 amount) private { if (token == WETH9 && address(this).balance >= amount) { - IWETH9(WETH9).deposit{ value: amount }(); + IWETH9(WETH9).deposit{value: amount}(); IWETH9(WETH9).transfer(recipient, amount); } else if (payer == address(this)) { IERC20(token).safeTransfer(recipient, amount); @@ -574,7 +580,7 @@ contract ValantisSwapRouter is IValantisSwapRouter, EIP712, ReentrancyGuard { function _sendNativeToken(address recipient, uint256 amount) private { if (amount > 0) { - (bool success, ) = payable(recipient).call{ value: amount }(''); + (bool success,) = payable(recipient).call{value: amount}(""); if (!success) { revert ValantisSwapRouter___sendNativeToken_ethTransferFailed(); } diff --git a/src/swap-router/interfaces/IValantisSwapRouter.sol b/src/swap-router/interfaces/IValantisSwapRouter.sol index 56e5274..0f3244c 100644 --- a/src/swap-router/interfaces/IValantisSwapRouter.sol +++ b/src/swap-router/interfaces/IValantisSwapRouter.sol @@ -15,7 +15,8 @@ interface IValantisSwapRouter is ISovereignPoolSwapCallback, IUniversalPoolSwapC uint256 amountIn, uint256 amountOut, bool isTokenInEth, - bool isTokenOutEth + bool isTokenOutEth, + bytes32 code ); event GaslessSwapLog( @@ -26,7 +27,8 @@ interface IValantisSwapRouter is ISovereignPoolSwapCallback, IUniversalPoolSwapC address tokenOut, uint256 amountIn, uint256 amountOut, - bool isTokenOutEth + bool isTokenOutEth, + bytes32 code ); // solhint-disable-next-line func-name-mixedcase diff --git a/src/swap-router/structs/ValantisSwapRouterStructs.sol b/src/swap-router/structs/ValantisSwapRouterStructs.sol index 9728ea5..9a70ee7 100644 --- a/src/swap-router/structs/ValantisSwapRouterStructs.sol +++ b/src/swap-router/structs/ValantisSwapRouterStructs.sol @@ -10,6 +10,7 @@ struct GaslessSwapParams { uint256[] amountInSpecified; bytes[] payloads; GaslessSwapIntent intent; + bytes32 code; } /** @@ -44,6 +45,7 @@ struct DirectSwapParams { address recipient; uint256 amountOutMin; uint256 deadline; + bytes32 code; } /** diff --git a/test/SwapRouter.t.sol b/test/SwapRouter.t.sol index c3aedc4..2194ebd 100644 --- a/test/SwapRouter.t.sol +++ b/test/SwapRouter.t.sol @@ -46,7 +46,8 @@ contract SwapRouterTest is Test, DeployPermit2 { uint256 amountIn, uint256 amountOut, bool isTokenInEth, - bool isTokenOutEth + bool isTokenOutEth, + bytes32 code ); event GaslessSwapLog( @@ -57,7 +58,8 @@ contract SwapRouterTest is Test, DeployPermit2 { address tokenOut, uint256 amountIn, uint256 amountOut, - bool isTokenOutEth + bool isTokenOutEth, + bytes32 code ); IAllowanceTransfer public permit2; @@ -104,6 +106,7 @@ contract SwapRouterTest is Test, DeployPermit2 { // solhint-disable-next-line max-line-length "GaslessSwapIntent(bool isTokenOutEth,address tokenIn,address tokenOut,address owner,address recipient,address authorizedSender,address feeToken,uint256 amountIn,uint256 amountOutMin,uint128 maxFee,uint256 nonce,uint256 deadline)" ); + bytes32 public constant EMPTY_CODE = keccak256(""); address _owner; uint256 private constant _ownerPrivateKey = 0x12345; @@ -488,7 +491,8 @@ contract SwapRouterTest is Test, DeployPermit2 { tokenOut, recipient, amountOutMin, - deadline + deadline, + EMPTY_CODE ); token0.approve(address(swapRouter), amountIn); @@ -586,7 +590,8 @@ contract SwapRouterTest is Test, DeployPermit2 { tokenOut, recipient, amountOutMin, - deadline + deadline, + EMPTY_CODE ); // Should revert if swapParams.tokenIn is not WETH @@ -671,7 +676,8 @@ contract SwapRouterTest is Test, DeployPermit2 { tokenOut, recipient, amountOutMin, - deadline + deadline, + EMPTY_CODE ); weth.deposit{value: amountIn}(); @@ -733,7 +739,8 @@ contract SwapRouterTest is Test, DeployPermit2 { tokenOut, recipient, amountOutMin, - deadline + deadline, + EMPTY_CODE ); swapParams.tokenOut = tokenIn; @@ -814,7 +821,8 @@ contract SwapRouterTest is Test, DeployPermit2 { tokenOut, recipient, amountOutMin, - deadline + deadline, + EMPTY_CODE ); token0.approve(address(swapRouter), amountIn); @@ -891,7 +899,8 @@ contract SwapRouterTest is Test, DeployPermit2 { tokenOut, recipient, amountOutMin, - deadline + deadline, + EMPTY_CODE ); uint256 userPreBalance = address(this).balance; @@ -960,7 +969,8 @@ contract SwapRouterTest is Test, DeployPermit2 { tokenOut, recipient, amountOutMin, - deadline + deadline, + EMPTY_CODE ); weth.deposit{value: amountIn}(); @@ -1023,7 +1033,8 @@ contract SwapRouterTest is Test, DeployPermit2 { tokenOut, recipient, amountOutMin, - deadline + deadline, + EMPTY_CODE ); token0.approve(address(swapRouter), amountIn); @@ -1118,7 +1129,8 @@ contract SwapRouterTest is Test, DeployPermit2 { tokenOut, recipient, amountOutMin, - deadline + deadline, + EMPTY_CODE ); // Should revert if amountIn of first swap is 0 @@ -1221,7 +1233,8 @@ contract SwapRouterTest is Test, DeployPermit2 { tokenOut, recipient, amountOutMin, - deadline + deadline, + EMPTY_CODE ); uint256 userPreBalance = address(this).balance; @@ -1318,7 +1331,8 @@ contract SwapRouterTest is Test, DeployPermit2 { tokenOut, recipient, amountOutMin, - deadline + deadline, + EMPTY_CODE ); weth.deposit{value: amountIn}(); @@ -1427,7 +1441,8 @@ contract SwapRouterTest is Test, DeployPermit2 { tokenOut, recipient, amountOutMin, - deadline + deadline, + EMPTY_CODE ); token0.approve(address(swapRouter), amountIn); @@ -1444,7 +1459,9 @@ contract SwapRouterTest is Test, DeployPermit2 { assertEq(token3.balanceOf(recipient), 0); vm.expectEmit(false, false, false, true); - emit DirectSwapLog(address(this), recipient, tokenIn, tokenOut, amountIn, amountOut, false, false); + emit DirectSwapLog( + address(this), recipient, tokenIn, tokenOut, amountIn, amountOut, false, false, EMPTY_CODE + ); amountOut = swapRouter.swap(swapParams); assert(amountOut >= amountOutMin); assertEq(token3.balanceOf(recipient), amountOut); @@ -1551,7 +1568,7 @@ contract SwapRouterTest is Test, DeployPermit2 { (bytes memory ownerSignature,) = _getIntentsSignatureAndHash(_ownerPrivateKey, gaslessSwapIntent); GaslessSwapParams memory swapParams = - GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, gaslessSwapIntent); + GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, gaslessSwapIntent, EMPTY_CODE); vm.expectRevert(ValantisSwapRouter.ValantisSwapRouter___gaslessSwap_insufficientAmountOut.selector); swapRouter.gaslessSwap(swapParams, ownerSignature, gaslessSwapIntent.maxFee); @@ -1576,7 +1593,8 @@ contract SwapRouterTest is Test, DeployPermit2 { (ownerSignature,) = _getIntentsSignatureAndHash(_ownerPrivateKey, gaslessSwapIntent); - swapParams = GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, gaslessSwapIntent); + swapParams = + GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, gaslessSwapIntent, EMPTY_CODE); vm.chainId(123); @@ -1604,7 +1622,8 @@ contract SwapRouterTest is Test, DeployPermit2 { swapParams.intent.tokenOut, swapParams.intent.amountIn, amountOut, - false + false, + EMPTY_CODE ); amountOut = swapRouter.gaslessSwap(swapParams, ownerSignature, gaslessSwapIntent.maxFee); assertEq(token3.balanceOf(recipient), amountOut); @@ -1718,7 +1737,7 @@ contract SwapRouterTest is Test, DeployPermit2 { (bytes memory ownerSignature,) = _getIntentsSignatureAndHash(_ownerPrivateKey, gaslessSwapIntent); GaslessSwapParams memory swapParams = - GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, gaslessSwapIntent); + GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, gaslessSwapIntent, EMPTY_CODE); swapParams.intent.tokenOut = address(token2); // Should revert if tokenOut is not WETH @@ -1755,7 +1774,8 @@ contract SwapRouterTest is Test, DeployPermit2 { swapParams.intent.tokenOut, swapParams.intent.amountIn, amountOut, - true + true, + EMPTY_CODE ); amountOut = swapRouter.gaslessSwap(swapParams, ownerSignature, gaslessSwapIntent.maxFee); // Recipient must receive amountOut of ETH @@ -1833,8 +1853,10 @@ contract SwapRouterTest is Test, DeployPermit2 { bytes[] memory signatures = new bytes[](2); uint128[] memory fees = new uint128[](2); - params[0] = GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, firstGaslessSwapIntent); - params[1] = GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, secondGaslessSwapIntent); + params[0] = + GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, firstGaslessSwapIntent, EMPTY_CODE); + params[1] = + GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, secondGaslessSwapIntent, EMPTY_CODE); signatures[0] = firstSignature; signatures[1] = secondSignature; @@ -1849,8 +1871,10 @@ contract SwapRouterTest is Test, DeployPermit2 { signatures = new bytes[](2); fees = new uint128[](2); - params[0] = GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, firstGaslessSwapIntent); - params[1] = GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, secondGaslessSwapIntent); + params[0] = + GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, firstGaslessSwapIntent, EMPTY_CODE); + params[1] = + GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, secondGaslessSwapIntent, EMPTY_CODE); signatures[0] = firstSignature; signatures[1] = secondSignature; @@ -1859,7 +1883,8 @@ contract SwapRouterTest is Test, DeployPermit2 { swapRouter.batchGaslessSwaps(params, signatures, fees); firstGaslessSwapIntent.amountOutMin = amountOutMin; - params[0] = GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, firstGaslessSwapIntent); + params[0] = + GaslessSwapParams(isUniversalPool, pools, amountInSpecified, payloads, firstGaslessSwapIntent, EMPTY_CODE); (firstSignature,) = _getIntentsSignatureAndHash(_ownerPrivateKey, firstGaslessSwapIntent); signatures[0] = firstSignature;