From 373f95b630c8cf0a2563508f52376907547645ea Mon Sep 17 00:00:00 2001 From: Alice Henshaw Date: Tue, 30 Jul 2024 19:13:20 +0100 Subject: [PATCH 1/3] batch permit decode in calldata --- contracts/base/Dispatcher.sol | 6 ++- .../__snapshots__/Payments.gas.test.ts.snap | 10 ++-- .../__snapshots__/Uniswap.gas.test.ts.snap | 52 +++++++++---------- .../UniversalRouter.gas.test.ts.snap | 2 +- .../UniversalVSSwapRouter.gas.test.ts.snap | 20 +++---- 5 files changed, 46 insertions(+), 44 deletions(-) diff --git a/contracts/base/Dispatcher.sol b/contracts/base/Dispatcher.sol index 84869d06..bf4d837d 100644 --- a/contracts/base/Dispatcher.sol +++ b/contracts/base/Dispatcher.sol @@ -86,8 +86,10 @@ abstract contract Dispatcher is Payments, V2SwapRouter, V3SwapRouter, V3ToV4Migr } permit2TransferFrom(token, _msgSender(), map(recipient), amount); } else if (command == Commands.PERMIT2_PERMIT_BATCH) { - (IAllowanceTransfer.PermitBatch memory permitBatch,) = - abi.decode(inputs, (IAllowanceTransfer.PermitBatch, bytes)); + IAllowanceTransfer.PermitBatch calldata permitBatch; + assembly { + permitBatch := add(inputs.offset, calldataload(inputs.offset)) + } bytes calldata data = inputs.toBytes(1); PERMIT2.permit(_msgSender(), permitBatch, data); } else if (command == Commands.SWEEP) { 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 84b16c78..1c309e5a 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 @@ -3,28 +3,28 @@ exports[`Payments Gas Tests Individual Command Tests gas: SWEEP with ERC20 1`] = ` Object { "calldataByteLength": 356, - "gasUsed": 37013, + "gasUsed": 36960, } `; exports[`Payments Gas Tests Individual Command Tests gas: SWEEP_WITH_FEE 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 65690, + "gasUsed": 65584, } `; exports[`Payments Gas Tests Individual Command Tests gas: TRANSFER with ERC20 1`] = ` Object { "calldataByteLength": 356, - "gasUsed": 36038, + "gasUsed": 35985, } `; exports[`Payments Gas Tests Individual Command Tests gas: TRANSFER with ETH 1`] = ` Object { "calldataByteLength": 356, - "gasUsed": 31609, + "gasUsed": 31556, } `; @@ -38,7 +38,7 @@ Object { exports[`Payments Gas Tests Individual Command Tests gas: UNWRAP_WETH_WITH_FEE 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 50905, + "gasUsed": 50799, } `; 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 0c4c7a73..ba20269c 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 @@ -3,49 +3,49 @@ exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Batch reverts gas: 2 sub-plans, both fail but the transaction succeeds 1`] = ` Object { "calldataByteLength": 1764, - "gasUsed": 269421, + "gasUsed": 269286, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Batch reverts gas: 2 sub-plans, neither fails 1`] = ` Object { "calldataByteLength": 1764, - "gasUsed": 245148, + "gasUsed": 245013, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Batch reverts gas: 2 sub-plans, second sub plan fails 1`] = ` Object { "calldataByteLength": 1764, - "gasUsed": 245148, + "gasUsed": 245013, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Batch reverts gas: 2 sub-plans, the first fails 1`] = ` Object { "calldataByteLength": 1764, - "gasUsed": 269421, + "gasUsed": 269286, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Interleaving routes gas: V2, then V3 1`] = ` Object { "calldataByteLength": 836, - "gasUsed": 189470, + "gasUsed": 189429, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Interleaving routes gas: V3, then V2 1`] = ` Object { "calldataByteLength": 836, - "gasUsed": 177054, + "gasUsed": 177013, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Split routes gas: ERC20 --> ERC20 split V2 and V2 different routes, different input tokens, each two hop, with batch permit 1`] = ` Object { "calldataByteLength": 1540, - "gasUsed": 298488, + "gasUsed": 297045, } `; @@ -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": 309785, + "gasUsed": 309749, } `; @@ -73,35 +73,35 @@ Object { exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Split routes gas: ERC20 --> ERC20 split V2 and V3, one hop 1`] = ` Object { "calldataByteLength": 996, - "gasUsed": 176845, + "gasUsed": 176751, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Split routes gas: ERC20 --> ERC20 split V2 and V3, one hop, ADDRESS_THIS flag 1`] = ` Object { "calldataByteLength": 996, - "gasUsed": 176620, + "gasUsed": 176526, } `; 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": 194645, + "gasUsed": 194604, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Split routes gas: ERC20 --> ETH split V2 and V3, one hop 1`] = ` Object { "calldataByteLength": 964, - "gasUsed": 184716, + "gasUsed": 184675, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Split routes gas: ETH --> ERC20 split V2 and V3, one hop 1`] = ` Object { "calldataByteLength": 1124, - "gasUsed": 191723, + "gasUsed": 191629, } `; @@ -143,7 +143,7 @@ Object { exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactIn trade, where an output fee is taken 1`] = ` Object { "calldataByteLength": 836, - "gasUsed": 126565, + "gasUsed": 126459, } `; @@ -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": 128329, + "gasUsed": 128276, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ETH gas: exactOut, with ETH fee 1`] = ` Object { "calldataByteLength": 964, - "gasUsed": 136301, + "gasUsed": 136195, } `; @@ -283,69 +283,69 @@ Object { exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, one hop 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 105541, + "gasUsed": 105500, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, three hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 254014, + "gasUsed": 253891, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, two hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 177164, + "gasUsed": 177082, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, one hop 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 115071, + "gasUsed": 115030, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, three hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 251172, + "gasUsed": 251049, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, two hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 174826, + "gasUsed": 174744, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ETH gas: exactIn swap 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 121815, + "gasUsed": 121774, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ETH gas: exactOut swap 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 131417, + "gasUsed": 131376, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ETH --> ERC20 gas: exactIn swap 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 215384, + "gasUsed": 215343, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ETH --> ERC20 gas: exactOut swap 1`] = ` Object { "calldataByteLength": 772, - "gasUsed": 126560, + "gasUsed": 126519, } `; 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 05636a62..d060e8ad 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`] = `14355`; +exports[`UniversalRouter Gas Tests gas: bytecode size 1`] = `14018`; diff --git a/test/integration-tests/gas-tests/__snapshots__/UniversalVSSwapRouter.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/UniversalVSSwapRouter.gas.test.ts.snap index a719e820..bf913bb9 100644 --- a/test/integration-tests/gas-tests/__snapshots__/UniversalVSSwapRouter.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/UniversalVSSwapRouter.gas.test.ts.snap @@ -7,32 +7,32 @@ Object { } `; -exports[`Uniswap UX Tests gas: Comparisons Casual Swapper - 3 swaps Permit2 Max Approval Swap 1`] = `1104509`; +exports[`Uniswap UX Tests gas: Comparisons Casual Swapper - 3 swaps Permit2 Max Approval Swap 1`] = `1104105`; -exports[`Uniswap UX Tests gas: Comparisons Casual Swapper - 3 swaps Permit2 Sign Per Swap 1`] = `1138923`; +exports[`Uniswap UX Tests gas: Comparisons Casual Swapper - 3 swaps Permit2 Sign Per Swap 1`] = `1138531`; exports[`Uniswap UX Tests gas: Comparisons Casual Swapper - 3 swaps SwapRouter02 1`] = `1124979`; -exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper - 10 swaps Permit2 Max Approval Swap 1`] = `3082245`; +exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper - 10 swaps Permit2 Max Approval Swap 1`] = `3081021`; -exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper - 10 swaps Permit2 Sign Per Swap 1`] = `3235804`; +exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper - 10 swaps Permit2 Sign Per Swap 1`] = `3234634`; exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper - 10 swaps SwapRouter02 1`] = `3195011`; -exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper across 3 swap router versions - 15 swaps across 3 versions Permit2 Max Approval Swap 1`] = `4104504`; +exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper across 3 swap router versions - 15 swaps across 3 versions Permit2 Max Approval Swap 1`] = `4102882`; -exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper across 3 swap router versions - 15 swaps across 3 versions Permit2 Sign Per Swap 1`] = `4308542`; +exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper across 3 swap router versions - 15 swaps across 3 versions Permit2 Sign Per Swap 1`] = `4306992`; exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper across 3 swap router versions - 15 swaps across 3 versions SwapRouter02 1`] = `4282374`; -exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Complex Swap Permit2 Max Approval Swap 1`] = `508881`; +exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Complex Swap Permit2 Max Approval Swap 1`] = `508723`; -exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Complex Swap Permit2 Sign Per Swap 1`] = `509199`; +exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Complex Swap Permit2 Sign Per Swap 1`] = `509041`; exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Complex Swap SwapRouter02 1`] = `500008`; -exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Simple Swap Permit2 Max Approval Swap 1`] = `299727`; +exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Simple Swap Permit2 Max Approval Swap 1`] = `299651`; -exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Simple Swap Permit2 Sign Per Swap 1`] = `299663`; +exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Simple Swap Permit2 Sign Per Swap 1`] = `299587`; exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Simple Swap SwapRouter02 1`] = `270033`; From c853d4eef1f394c922f764511db6c6c8e4c3f8f2 Mon Sep 17 00:00:00 2001 From: Alice Henshaw Date: Tue, 30 Jul 2024 19:29:01 +0100 Subject: [PATCH 2/3] 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`; From 0d81bcaa816248b2143ab1704f8a6e2dbdbe8dce Mon Sep 17 00:00:00 2001 From: Alice Henshaw Date: Fri, 2 Aug 2024 23:27:05 +0100 Subject: [PATCH 3/3] PR comment --- .../modules/uniswap/v2/UniswapV2Library.sol | 2 +- .../CheckOwnership.gas.test.ts.snap | 2 +- .../__snapshots__/Payments.gas.test.ts.snap | 14 ++-- .../__snapshots__/Uniswap.gas.test.ts.snap | 78 +++++++++---------- .../UniversalRouter.gas.test.ts.snap | 2 +- .../UniversalVSSwapRouter.gas.test.ts.snap | 20 ++--- .../V3ToV4Migration.gas.test.ts.snap | 8 +- 7 files changed, 63 insertions(+), 63 deletions(-) diff --git a/contracts/modules/uniswap/v2/UniswapV2Library.sol b/contracts/modules/uniswap/v2/UniswapV2Library.sol index 936d7cd1..3b89e482 100644 --- a/contracts/modules/uniswap/v2/UniswapV2Library.sol +++ b/contracts/modules/uniswap/v2/UniswapV2Library.sol @@ -122,7 +122,7 @@ library UniswapV2Library { /// @param path The path of the multi-hop trade /// @return amount The input amount of the input token /// @return pair The first pair in the trade - function getAmountInMultihop(address factory, bytes32 initCodeHash, uint256 amountOut, address[] memory path) + function getAmountInMultihop(address factory, bytes32 initCodeHash, uint256 amountOut, address[] calldata path) internal view returns (uint256 amount, address pair) 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 d5544ff7..591d189f 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": 37692, + "gasUsed": 37639, } `; 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 88ffee07..1d211df7 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 @@ -3,48 +3,48 @@ exports[`Payments Gas Tests Individual Command Tests gas: SWEEP with ERC20 1`] = ` Object { "calldataByteLength": 356, - "gasUsed": 36960, + "gasUsed": 36947, } `; exports[`Payments Gas Tests Individual Command Tests gas: SWEEP_WITH_FEE 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 65584, + "gasUsed": 65568, } `; exports[`Payments Gas Tests Individual Command Tests gas: TRANSFER with ERC20 1`] = ` Object { "calldataByteLength": 356, - "gasUsed": 35985, + "gasUsed": 35972, } `; exports[`Payments Gas Tests Individual Command Tests gas: TRANSFER with ETH 1`] = ` Object { "calldataByteLength": 356, - "gasUsed": 31553, + "gasUsed": 31543, } `; exports[`Payments Gas Tests Individual Command Tests gas: UNWRAP_WETH 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 44577, + "gasUsed": 44505, } `; exports[`Payments Gas Tests Individual Command Tests gas: UNWRAP_WETH_WITH_FEE 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 50799, + "gasUsed": 50721, } `; exports[`Payments Gas Tests Individual Command Tests gas: WRAP_ETH 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 53402, + "gasUsed": 53344, } `; 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 34ae5b44..b673ae91 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 @@ -3,105 +3,105 @@ exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Batch reverts gas: 2 sub-plans, both fail but the transaction succeeds 1`] = ` Object { "calldataByteLength": 1764, - "gasUsed": 269286, + "gasUsed": 269232, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Batch reverts gas: 2 sub-plans, neither fails 1`] = ` Object { "calldataByteLength": 1764, - "gasUsed": 245013, + "gasUsed": 244951, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Batch reverts gas: 2 sub-plans, second sub plan fails 1`] = ` Object { "calldataByteLength": 1764, - "gasUsed": 245013, + "gasUsed": 244951, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Batch reverts gas: 2 sub-plans, the first fails 1`] = ` Object { "calldataByteLength": 1764, - "gasUsed": 269286, + "gasUsed": 269232, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Interleaving routes gas: V2, then V3 1`] = ` Object { "calldataByteLength": 836, - "gasUsed": 189429, + "gasUsed": 189398, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Interleaving routes gas: V3, then V2 1`] = ` Object { "calldataByteLength": 836, - "gasUsed": 177013, + "gasUsed": 176982, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Split routes gas: ERC20 --> ERC20 split V2 and V2 different routes, different input tokens, each two hop, with batch permit 1`] = ` Object { "calldataByteLength": 1540, - "gasUsed": 297045, + "gasUsed": 297014, } `; 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 1`] = ` Object { "calldataByteLength": 1220, - "gasUsed": 307720, + "gasUsed": 307686, } `; 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": 308988, + "gasUsed": 308921, } `; 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, without explicit permit 1`] = ` Object { "calldataByteLength": 900, - "gasUsed": 304268, + "gasUsed": 304240, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Split routes gas: ERC20 --> ERC20 split V2 and V3, one hop 1`] = ` Object { "calldataByteLength": 996, - "gasUsed": 176751, + "gasUsed": 176717, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Split routes gas: ERC20 --> ERC20 split V2 and V3, one hop, ADDRESS_THIS flag 1`] = ` Object { "calldataByteLength": 996, - "gasUsed": 176526, + "gasUsed": 176492, } `; 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": 194568, + "gasUsed": 194045, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Split routes gas: ERC20 --> ETH split V2 and V3, one hop 1`] = ` Object { "calldataByteLength": 964, - "gasUsed": 184675, + "gasUsed": 184582, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Split routes gas: ETH --> ERC20 split V2 and V3, one hop 1`] = ` Object { "calldataByteLength": 1124, - "gasUsed": 191629, + "gasUsed": 191533, } `; @@ -143,98 +143,98 @@ Object { exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactIn trade, where an output fee is taken 1`] = ` Object { "calldataByteLength": 836, - "gasUsed": 126459, + "gasUsed": 126434, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, one hop 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 106820, + "gasUsed": 106801, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, three hops 1`] = ` Object { "calldataByteLength": 580, - "gasUsed": 241426, + "gasUsed": 241407, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, three hops, no deadline 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 241168, + "gasUsed": 241149, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, two hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 174169, + "gasUsed": 174149, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, two hops, MSG_SENDER flag 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 174169, + "gasUsed": 174149, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, one hop 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 106890, + "gasUsed": 106435, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, three hops 1`] = ` Object { "calldataByteLength": 580, - "gasUsed": 246791, + "gasUsed": 246271, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, two hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 176914, + "gasUsed": 176427, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ETH gas: exactIn, one trade, one hop 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 123046, + "gasUsed": 122965, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ETH gas: exactOut, one trade, one hop 1`] = ` Object { "calldataByteLength": 804, - "gasUsed": 128240, + "gasUsed": 127720, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ETH gas: exactOut, with ETH fee 1`] = ` Object { "calldataByteLength": 964, - "gasUsed": 136159, + "gasUsed": 135636, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ETH --> ERC20 gas: exactIn, one trade, one hop 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 106657, + "gasUsed": 106576, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ETH --> ERC20 gas: exactOut, one trade, one hop 1`] = ` Object { "calldataByteLength": 772, - "gasUsed": 125498, + "gasUsed": 124919, } `; @@ -283,69 +283,69 @@ Object { exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, one hop 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 105500, + "gasUsed": 105478, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, three hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 253891, + "gasUsed": 253863, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, two hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 177082, + "gasUsed": 177056, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, one hop 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 115030, + "gasUsed": 115014, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, three hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 251049, + "gasUsed": 251027, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, two hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 174744, + "gasUsed": 174725, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ETH gas: exactIn swap 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 121774, + "gasUsed": 121690, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ETH gas: exactOut swap 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 131376, + "gasUsed": 131298, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ETH --> ERC20 gas: exactIn swap 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 215343, + "gasUsed": 215259, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ETH --> ERC20 gas: exactOut swap 1`] = ` Object { "calldataByteLength": 772, - "gasUsed": 126519, + "gasUsed": 126379, } `; 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 f74fed7b..e140cb8a 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`] = `13879`; +exports[`UniversalRouter Gas Tests gas: bytecode size 1`] = `13736`; diff --git a/test/integration-tests/gas-tests/__snapshots__/UniversalVSSwapRouter.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/UniversalVSSwapRouter.gas.test.ts.snap index bf913bb9..23508d23 100644 --- a/test/integration-tests/gas-tests/__snapshots__/UniversalVSSwapRouter.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/UniversalVSSwapRouter.gas.test.ts.snap @@ -7,32 +7,32 @@ Object { } `; -exports[`Uniswap UX Tests gas: Comparisons Casual Swapper - 3 swaps Permit2 Max Approval Swap 1`] = `1104105`; +exports[`Uniswap UX Tests gas: Comparisons Casual Swapper - 3 swaps Permit2 Max Approval Swap 1`] = `1103919`; -exports[`Uniswap UX Tests gas: Comparisons Casual Swapper - 3 swaps Permit2 Sign Per Swap 1`] = `1138531`; +exports[`Uniswap UX Tests gas: Comparisons Casual Swapper - 3 swaps Permit2 Sign Per Swap 1`] = `1138221`; exports[`Uniswap UX Tests gas: Comparisons Casual Swapper - 3 swaps SwapRouter02 1`] = `1124979`; -exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper - 10 swaps Permit2 Max Approval Swap 1`] = `3081021`; +exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper - 10 swaps Permit2 Max Approval Swap 1`] = `3080584`; -exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper - 10 swaps Permit2 Sign Per Swap 1`] = `3234634`; +exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper - 10 swaps Permit2 Sign Per Swap 1`] = `3233639`; exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper - 10 swaps SwapRouter02 1`] = `3195011`; -exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper across 3 swap router versions - 15 swaps across 3 versions Permit2 Max Approval Swap 1`] = `4102882`; +exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper across 3 swap router versions - 15 swaps across 3 versions Permit2 Max Approval Swap 1`] = `4102191`; -exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper across 3 swap router versions - 15 swaps across 3 versions Permit2 Sign Per Swap 1`] = `4306992`; +exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper across 3 swap router versions - 15 swaps across 3 versions Permit2 Sign Per Swap 1`] = `4305557`; exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper across 3 swap router versions - 15 swaps across 3 versions SwapRouter02 1`] = `4282374`; -exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Complex Swap Permit2 Max Approval Swap 1`] = `508723`; +exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Complex Swap Permit2 Max Approval Swap 1`] = `508612`; -exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Complex Swap Permit2 Sign Per Swap 1`] = `509041`; +exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Complex Swap Permit2 Sign Per Swap 1`] = `508930`; exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Complex Swap SwapRouter02 1`] = `500008`; -exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Simple Swap Permit2 Max Approval Swap 1`] = `299651`; +exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Simple Swap Permit2 Max Approval Swap 1`] = `299563`; -exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Simple Swap Permit2 Sign Per Swap 1`] = `299587`; +exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Simple Swap Permit2 Sign Per Swap 1`] = `299499`; exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Simple Swap SwapRouter02 1`] = `270033`; diff --git a/test/integration-tests/gas-tests/__snapshots__/V3ToV4Migration.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/V3ToV4Migration.gas.test.ts.snap index e53be141..f23a584c 100644 --- a/test/integration-tests/gas-tests/__snapshots__/V3ToV4Migration.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/V3ToV4Migration.gas.test.ts.snap @@ -3,27 +3,27 @@ exports[`V3 to V4 Migration Gas Tests Migrator burn gas: erc721permit + decreaseLiquidity + collect + burn 1`] = ` Object { "calldataByteLength": 1092, - "gasUsed": 255774, + "gasUsed": 255766, } `; exports[`V3 to V4 Migration Gas Tests Migrator collect gas: erc721permit + decreaseLiquidity + collect 1`] = ` Object { "calldataByteLength": 964, - "gasUsed": 223466, + "gasUsed": 223456, } `; exports[`V3 to V4 Migration Gas Tests Migrator decrease liquidity gas: erc721permit + decreaseLiquidity 1`] = ` Object { "calldataByteLength": 740, - "gasUsed": 201904, + "gasUsed": 201894, } `; exports[`V3 to V4 Migration Gas Tests Migrator erc721permit gas: erc721permit 1`] = ` Object { "calldataByteLength": 484, - "gasUsed": 65914, + "gasUsed": 65904, } `;