From c853d4eef1f394c922f764511db6c6c8e4c3f8f2 Mon Sep 17 00:00:00 2001 From: Alice Henshaw Date: Tue, 30 Jul 2024 19:29:01 +0100 Subject: [PATCH] array of structs --- contracts/base/Dispatcher.sol | 10 ++++++++-- contracts/modules/Permit2Payments.sol | 2 +- .../CheckOwnership.gas.test.ts.snap | 2 +- .../__snapshots__/Payments.gas.test.ts.snap | 2 +- .../__snapshots__/Uniswap.gas.test.ts.snap | 16 ++++++++-------- .../UniversalRouter.gas.test.ts.snap | 2 +- 6 files changed, 20 insertions(+), 14 deletions(-) diff --git a/contracts/base/Dispatcher.sol b/contracts/base/Dispatcher.sol index bf4d837d..b0113bf1 100644 --- a/contracts/base/Dispatcher.sol +++ b/contracts/base/Dispatcher.sol @@ -88,6 +88,8 @@ abstract contract Dispatcher is Payments, V2SwapRouter, V3SwapRouter, V3ToV4Migr } else if (command == Commands.PERMIT2_PERMIT_BATCH) { IAllowanceTransfer.PermitBatch calldata permitBatch; assembly { + // this is a variable length struct, so calldataload(inputs.offset) contains the + // offset from inputs.offset at which the struct begins permitBatch := add(inputs.offset, calldataload(inputs.offset)) } bytes calldata data = inputs.toBytes(1); @@ -190,8 +192,12 @@ abstract contract Dispatcher is Payments, V2SwapRouter, V3SwapRouter, V3ToV4Migr } Payments.unwrapWETH9(map(recipient), amountMin); } else if (command == Commands.PERMIT2_TRANSFER_FROM_BATCH) { - (IAllowanceTransfer.AllowanceTransferDetails[] memory batchDetails) = - abi.decode(inputs, (IAllowanceTransfer.AllowanceTransferDetails[])); + IAllowanceTransfer.AllowanceTransferDetails[] calldata batchDetails; + (uint256 length, uint256 offset) = inputs.toLengthOffset(0); + assembly { + batchDetails.length := length + batchDetails.offset := offset + } permit2TransferFrom(batchDetails, _msgSender()); } else if (command == Commands.BALANCE_CHECK_ERC20) { // equivalent: abi.decode(inputs, (address, address, uint256)) diff --git a/contracts/modules/Permit2Payments.sol b/contracts/modules/Permit2Payments.sol index 49f70b01..ea01cdfb 100644 --- a/contracts/modules/Permit2Payments.sol +++ b/contracts/modules/Permit2Payments.sol @@ -23,7 +23,7 @@ abstract contract Permit2Payments is Payments { /// @notice Performs a batch transferFrom on Permit2 /// @param batchDetails An array detailing each of the transfers that should occur - function permit2TransferFrom(IAllowanceTransfer.AllowanceTransferDetails[] memory batchDetails, address owner) + function permit2TransferFrom(IAllowanceTransfer.AllowanceTransferDetails[] calldata batchDetails, address owner) internal { uint256 batchLength = batchDetails.length; diff --git a/test/integration-tests/gas-tests/__snapshots__/CheckOwnership.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/CheckOwnership.gas.test.ts.snap index 361b3d6d..d5544ff7 100644 --- a/test/integration-tests/gas-tests/__snapshots__/CheckOwnership.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/CheckOwnership.gas.test.ts.snap @@ -3,6 +3,6 @@ exports[`Check Ownership Gas gas: balance check ERC20 1`] = ` Object { "calldataByteLength": 356, - "gasUsed": 37644, + "gasUsed": 37692, } `; diff --git a/test/integration-tests/gas-tests/__snapshots__/Payments.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/Payments.gas.test.ts.snap index 1c309e5a..88ffee07 100644 --- a/test/integration-tests/gas-tests/__snapshots__/Payments.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/Payments.gas.test.ts.snap @@ -24,7 +24,7 @@ Object { exports[`Payments Gas Tests Individual Command Tests gas: TRANSFER with ETH 1`] = ` Object { "calldataByteLength": 356, - "gasUsed": 31556, + "gasUsed": 31553, } `; diff --git a/test/integration-tests/gas-tests/__snapshots__/Uniswap.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/Uniswap.gas.test.ts.snap index ba20269c..34ae5b44 100644 --- a/test/integration-tests/gas-tests/__snapshots__/Uniswap.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/Uniswap.gas.test.ts.snap @@ -59,7 +59,7 @@ Object { exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Split routes gas: ERC20 --> ERC20 split V2 and V2 different routes, each two hop, with explicit permit transfer from batch 1`] = ` Object { "calldataByteLength": 1284, - "gasUsed": 309749, + "gasUsed": 308988, } `; @@ -87,7 +87,7 @@ Object { exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Split routes gas: ERC20 --> ETH split V2 and V3, exactOut, one hop 1`] = ` Object { "calldataByteLength": 964, - "gasUsed": 194604, + "gasUsed": 194568, } `; @@ -185,21 +185,21 @@ Object { exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, one hop 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 106926, + "gasUsed": 106890, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, three hops 1`] = ` Object { "calldataByteLength": 580, - "gasUsed": 246827, + "gasUsed": 246791, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, two hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 176950, + "gasUsed": 176914, } `; @@ -213,14 +213,14 @@ Object { exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ETH gas: exactOut, one trade, one hop 1`] = ` Object { "calldataByteLength": 804, - "gasUsed": 128276, + "gasUsed": 128240, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ETH gas: exactOut, with ETH fee 1`] = ` Object { "calldataByteLength": 964, - "gasUsed": 136195, + "gasUsed": 136159, } `; @@ -234,7 +234,7 @@ Object { exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ETH --> ERC20 gas: exactOut, one trade, one hop 1`] = ` Object { "calldataByteLength": 772, - "gasUsed": 125534, + "gasUsed": 125498, } `; diff --git a/test/integration-tests/gas-tests/__snapshots__/UniversalRouter.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/UniversalRouter.gas.test.ts.snap index d060e8ad..f74fed7b 100644 --- a/test/integration-tests/gas-tests/__snapshots__/UniversalRouter.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/UniversalRouter.gas.test.ts.snap @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`UniversalRouter Gas Tests gas: bytecode size 1`] = `14018`; +exports[`UniversalRouter Gas Tests gas: bytecode size 1`] = `13879`;