diff --git a/contracts/modules/Permit2Payments.sol b/contracts/modules/Permit2Payments.sol index c547909f..cc5dfe40 100644 --- a/contracts/modules/Permit2Payments.sol +++ b/contracts/modules/Permit2Payments.sol @@ -28,8 +28,11 @@ abstract contract Permit2Payments is Payments { internal { uint256 batchLength = batchDetails.length; - for (uint256 i = 0; i < batchLength; ++i) { + for (uint256 i = 0; i < batchLength;) { if (batchDetails[i].from != owner) revert FromAddressIsNotOwner(); + unchecked { + ++i; + } } PERMIT2.transferFrom(batchDetails); } diff --git a/contracts/modules/uniswap/TernaryLib.sol b/contracts/modules/uniswap/TernaryLib.sol new file mode 100644 index 00000000..1fb7eb80 --- /dev/null +++ b/contracts/modules/uniswap/TernaryLib.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity >=0.5.0; + +/// @title Library for replacing ternary operator with efficient bitwise operations +library TernaryLib { + /// @notice Equivalent to the ternary operator: `condition ? a : b` + function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256 res) { + assembly { + res := xor(b, mul(xor(a, b), condition)) + } + } + + /// @notice Equivalent to the ternary operator: `condition ? a : b` + function ternary(bool condition, int256 a, int256 b) internal pure returns (int256 res) { + assembly { + res := xor(b, mul(xor(a, b), condition)) + } + } + + /// @notice Equivalent to the ternary operator: `condition ? a : b` + function ternary(bool condition, address a, address b) internal pure returns (address res) { + assembly { + res := xor(b, mul(xor(a, b), condition)) + } + } + + /// @notice Sorts two tokens to return token0 and token1 + /// @param tokenA The first token to sort + /// @param tokenB The other token to sort + /// @return token0 The smaller token by address value + /// @return token1 The larger token by address value + function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { + assembly { + let diff := mul(xor(tokenA, tokenB), lt(tokenB, tokenA)) + token0 := xor(tokenA, diff) + token1 := xor(tokenB, diff) + } + } + + /// @notice Switches two uint256 if `condition` is true + /// @dev Equivalent to: `condition ? (b, a) : (a, b)` + function switchIf(bool condition, uint256 a, uint256 b) internal pure returns (uint256, uint256) { + assembly { + let diff := mul(xor(a, b), condition) + a := xor(a, diff) + b := xor(b, diff) + } + return (a, b); + } +} diff --git a/contracts/modules/uniswap/v2/UniswapV2Library.sol b/contracts/modules/uniswap/v2/UniswapV2Library.sol index 936d7cd1..1247caf3 100644 --- a/contracts/modules/uniswap/v2/UniswapV2Library.sol +++ b/contracts/modules/uniswap/v2/UniswapV2Library.sol @@ -2,6 +2,7 @@ pragma solidity >=0.8.0; import {IUniswapV2Pair} from '@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol'; +import {TernaryLib} from '../TernaryLib.sol'; /// @title Uniswap v2 Helper Library /// @notice Calculates the recipient address for a command @@ -20,7 +21,7 @@ library UniswapV2Library { pure returns (address pair) { - (address token0, address token1) = sortTokens(tokenA, tokenB); + (address token0, address token1) = TernaryLib.sortTokens(tokenA, tokenB); pair = pairForPreSorted(factory, initCodeHash, token0, token1); } @@ -37,7 +38,7 @@ library UniswapV2Library { returns (address pair, address token0) { address token1; - (token0, token1) = sortTokens(tokenA, tokenB); + (token0, token1) = TernaryLib.sortTokens(tokenA, tokenB); pair = pairForPreSorted(factory, initCodeHash, token0, token1); } @@ -52,15 +53,25 @@ library UniswapV2Library { pure returns (address pair) { - pair = address( - uint160( - uint256( - keccak256( - abi.encodePacked(hex'ff', factory, keccak256(abi.encodePacked(token0, token1)), initCodeHash) - ) - ) - ) - ); + // accomplishes the following: + // address(keccak256(abi.encodePacked(hex'ff', factory, keccak256(abi.encodePacked(token0, token1)), initCodeHash))) + assembly ("memory-safe") { + // Cache the free memory pointer. + let fmp := mload(0x40) + // pairHash = keccak256(abi.encodePacked(token0, token1)) + mstore(0x14, token1) + mstore(0, token0) + let pairHash := keccak256(0x0c, 0x28) + // abi.encodePacked(hex'ff', factory, pairHash, initCodeHash) + // Prefix the factory address with 0xff. + mstore(0, or(factory, 0xff0000000000000000000000000000000000000000)) + mstore(0x20, pairHash) + mstore(0x40, initCodeHash) + // Compute the CREATE2 pair address and clean the upper bits. + pair := and(keccak256(0x0b, 0x55), 0xffffffffffffffffffffffffffffffffffffffff) + // Restore the free memory pointer. + mstore(0x40, fmp) + } } /// @notice Calculates the v2 address for a pair and fetches the reserves for each token @@ -79,7 +90,7 @@ library UniswapV2Library { address token0; (pair, token0) = pairAndToken0For(factory, initCodeHash, tokenA, tokenB); (uint256 reserve0, uint256 reserve1,) = IUniswapV2Pair(pair).getReserves(); - (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0); + (reserveA, reserveB) = TernaryLib.switchIf(tokenA == token0, reserve1, reserve0); } /// @notice Given an input asset amount returns the maximum output amount of the other asset @@ -129,21 +140,14 @@ library UniswapV2Library { { if (path.length < 2) revert InvalidPath(); amount = amountOut; - for (uint256 i = path.length - 1; i > 0; i--) { - uint256 reserveIn; - uint256 reserveOut; + unchecked { + for (uint256 i = path.length - 1; i > 0; --i) { + uint256 reserveIn; + uint256 reserveOut; - (pair, reserveIn, reserveOut) = pairAndReservesFor(factory, initCodeHash, path[i - 1], path[i]); - amount = getAmountIn(amount, reserveIn, reserveOut); + (pair, reserveIn, reserveOut) = pairAndReservesFor(factory, initCodeHash, path[i - 1], path[i]); + amount = getAmountIn(amount, reserveIn, reserveOut); + } } } - - /// @notice Sorts two tokens to return token0 and token1 - /// @param tokenA The first token to sort - /// @param tokenB The other token to sort - /// @return token0 The smaller token by address value - /// @return token1 The larger token by address value - function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { - (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); - } } diff --git a/contracts/modules/uniswap/v2/V2SwapRouter.sol b/contracts/modules/uniswap/v2/V2SwapRouter.sol index 1ac55c7e..e36f489d 100644 --- a/contracts/modules/uniswap/v2/V2SwapRouter.sol +++ b/contracts/modules/uniswap/v2/V2SwapRouter.sol @@ -8,6 +8,7 @@ import {Payments} from '../../Payments.sol'; import {Permit2Payments} from '../../Permit2Payments.sol'; import {Constants} from '../../../libraries/Constants.sol'; import {ERC20} from 'solmate/src/tokens/ERC20.sol'; +import {TernaryLib} from '../TernaryLib.sol'; /// @title Router for Uniswap v2 Trades abstract contract V2SwapRouter is RouterImmutables, Permit2Payments { @@ -20,22 +21,25 @@ abstract contract V2SwapRouter is RouterImmutables, Permit2Payments { if (path.length < 2) revert V2InvalidPath(); // cached to save on duplicate operations - (address token0,) = UniswapV2Library.sortTokens(path[0], path[1]); + (address token0,) = TernaryLib.sortTokens(path[0], path[1]); uint256 finalPairIndex = path.length - 1; uint256 penultimatePairIndex = finalPairIndex - 1; - for (uint256 i; i < finalPairIndex; i++) { - (address input, address output) = (path[i], path[i + 1]); - (uint256 reserve0, uint256 reserve1,) = IUniswapV2Pair(pair).getReserves(); - (uint256 reserveInput, uint256 reserveOutput) = - input == token0 ? (reserve0, reserve1) : (reserve1, reserve0); - uint256 amountInput = ERC20(input).balanceOf(pair) - reserveInput; - uint256 amountOutput = UniswapV2Library.getAmountOut(amountInput, reserveInput, reserveOutput); - (uint256 amount0Out, uint256 amount1Out) = - input == token0 ? (uint256(0), amountOutput) : (amountOutput, uint256(0)); + for (uint256 i; i < finalPairIndex; ++i) { + address input = path[i]; + uint256 amount0Out; + uint256 amount1Out; + { + (uint256 reserve0, uint256 reserve1,) = IUniswapV2Pair(pair).getReserves(); + (uint256 reserveInput, uint256 reserveOutput) = + TernaryLib.switchIf(input == token0, reserve1, reserve0); + uint256 amountInput = ERC20(input).balanceOf(pair) - reserveInput; + uint256 amountOutput = UniswapV2Library.getAmountOut(amountInput, reserveInput, reserveOutput); + (amount0Out, amount1Out) = TernaryLib.switchIf(input == token0, amountOutput, 0); + } address nextPair; (nextPair, token0) = i < penultimatePairIndex ? UniswapV2Library.pairAndToken0For( - UNISWAP_V2_FACTORY, UNISWAP_V2_PAIR_INIT_CODE_HASH, output, path[i + 2] + UNISWAP_V2_FACTORY, UNISWAP_V2_PAIR_INIT_CODE_HASH, path[i + 1], path[i + 2] ) : (recipient, address(0)); IUniswapV2Pair(pair).swap(amount0Out, amount1Out, nextPair, new bytes(0)); diff --git a/contracts/modules/uniswap/v3/BytesLib.sol b/contracts/modules/uniswap/v3/BytesLib.sol index 06520ff6..cb5a5a16 100644 --- a/contracts/modules/uniswap/v3/BytesLib.sol +++ b/contracts/modules/uniswap/v3/BytesLib.sol @@ -1,10 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later - -/// @title Library for Bytes Manipulation pragma solidity ^0.8.0; import {Constants} from '../../../libraries/Constants.sol'; +/// @title Library for Bytes Manipulation library BytesLib { error SliceOutOfBounds(); diff --git a/contracts/modules/uniswap/v3/V3SwapRouter.sol b/contracts/modules/uniswap/v3/V3SwapRouter.sol index 44966bdf..7bec53dd 100644 --- a/contracts/modules/uniswap/v3/V3SwapRouter.sol +++ b/contracts/modules/uniswap/v3/V3SwapRouter.sol @@ -11,12 +11,14 @@ import {RouterImmutables} from '../../../base/RouterImmutables.sol'; import {Permit2Payments} from '../../Permit2Payments.sol'; import {Constants} from '../../../libraries/Constants.sol'; import {ERC20} from 'solmate/src/tokens/ERC20.sol'; +import {TernaryLib} from '../TernaryLib.sol'; /// @title Router for Uniswap v3 Trades abstract contract V3SwapRouter is RouterImmutables, Permit2Payments, IUniswapV3SwapCallback { using V3Path for bytes; using BytesLib for bytes; using SafeCast for uint256; + using TernaryLib for bool; error V3InvalidSwap(); error V3TooLittleReceived(); @@ -93,13 +95,16 @@ abstract contract V3SwapRouter is RouterImmutables, Permit2Payments, IUniswapV3S // the outputs of prior swaps become the inputs to subsequent ones (int256 amount0Delta, int256 amount1Delta, bool zeroForOne) = _swap( amountIn.toInt256(), - hasMultiplePools ? address(this) : recipient, // for intermediate swaps, this contract custodies + hasMultiplePools.ternary(address(this), recipient), // for intermediate swaps, this contract custodies path.getFirstPool(), // only the first pool is needed payer, // for intermediate swaps, this contract custodies true ); - amountIn = uint256(-(zeroForOne ? amount1Delta : amount0Delta)); + unchecked { + // no need to check for overflow here as it will be caught in `toInt256()` + amountIn = uint256(-zeroForOne.ternary(amount1Delta, amount0Delta)); + } // decide whether to continue or terminate if (hasMultiplePools) { @@ -131,9 +136,11 @@ abstract contract V3SwapRouter is RouterImmutables, Permit2Payments, IUniswapV3S (int256 amount0Delta, int256 amount1Delta, bool zeroForOne) = _swap(-amountOut.toInt256(), recipient, path, payer, false); - uint256 amountOutReceived = zeroForOne ? uint256(-amount1Delta) : uint256(-amount0Delta); - - if (amountOutReceived != amountOut) revert V3InvalidAmountOut(); + unchecked { + // no need to check for overflow + uint256 amountOutReceived = uint256(-zeroForOne.ternary(amount1Delta, amount0Delta)); + if (amountOutReceived != amountOut) revert V3InvalidAmountOut(); + } maxAmountInCached = DEFAULT_MAX_AMOUNT_IN; } @@ -144,34 +151,51 @@ abstract contract V3SwapRouter is RouterImmutables, Permit2Payments, IUniswapV3S private returns (int256 amount0Delta, int256 amount1Delta, bool zeroForOne) { - (address tokenIn, uint24 fee, address tokenOut) = path.decodeFirstPool(); - - zeroForOne = isExactIn ? tokenIn < tokenOut : tokenOut < tokenIn; + address pool; + { + (address tokenIn, uint24 fee, address tokenOut) = path.decodeFirstPool(); + pool = computePoolAddress(tokenIn, tokenOut, fee); + // When isExactIn == 1, zeroForOne = tokenIn < tokenOut = !(tokenOut < tokenIn) = 1 ^ (tokenOut < tokenIn) + // When isExactIn == 0, zeroForOne = tokenOut < tokenIn = 0 ^ (tokenOut < tokenIn) + assembly { + zeroForOne := xor(isExactIn, lt(tokenOut, tokenIn)) + } + } - (amount0Delta, amount1Delta) = IUniswapV3Pool(computePoolAddress(tokenIn, tokenOut, fee)).swap( + (amount0Delta, amount1Delta) = IUniswapV3Pool(pool).swap( recipient, zeroForOne, amount, - (zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1), + uint160(zeroForOne.ternary(MIN_SQRT_RATIO + 1, MAX_SQRT_RATIO - 1)), abi.encode(path, payer) ); } function computePoolAddress(address tokenA, address tokenB, uint24 fee) private view returns (address pool) { - if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA); - pool = address( - uint160( - uint256( - keccak256( - abi.encodePacked( - hex'ff', - UNISWAP_V3_FACTORY, - keccak256(abi.encode(tokenA, tokenB, fee)), - UNISWAP_V3_POOL_INIT_CODE_HASH - ) - ) - ) - ) - ); + address factory = UNISWAP_V3_FACTORY; + bytes32 initCodeHash = UNISWAP_V3_POOL_INIT_CODE_HASH; + // accomplishes the following: + // address(keccak256(abi.encodePacked(hex'ff', factory, keccak256(abi.encode(tokenA, tokenB, fee)), initCodeHash))) + assembly ("memory-safe") { + // Cache the free memory pointer. + let fmp := mload(0x40) + // Hash the pool key. + // Equivalent to `if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA)` + let diff := mul(xor(tokenA, tokenB), lt(tokenB, tokenA)) + // poolHash = keccak256(abi.encode(tokenA, tokenB, fee)) + mstore(0, xor(tokenA, diff)) + mstore(0x20, xor(tokenB, diff)) + mstore(0x40, fee) + let poolHash := keccak256(0, 0x60) + // abi.encodePacked(hex'ff', factory, poolHash, initCodeHash) + // Prefix the factory address with 0xff. + mstore(0, or(factory, 0xff0000000000000000000000000000000000000000)) + mstore(0x20, poolHash) + mstore(0x40, initCodeHash) + // Compute the CREATE2 pool address and clean the upper bits. + pool := and(keccak256(0x0b, 0x55), 0xffffffffffffffffffffffffffffffffffffffff) + // Restore the free memory pointer. + mstore(0x40, fmp) + } } } diff --git a/test/foundry-tests/UniswapV2.t.sol b/test/foundry-tests/UniswapV2.t.sol index c925ea85..97935e56 100644 --- a/test/foundry-tests/UniswapV2.t.sol +++ b/test/foundry-tests/UniswapV2.t.sol @@ -12,9 +12,6 @@ import {Constants} from '../../contracts/libraries/Constants.sol'; import {Commands} from '../../contracts/libraries/Commands.sol'; import {RouterParameters} from '../../contracts/base/RouterImmutables.sol'; -import '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol'; -import '@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol'; - abstract contract UniswapV2Test is Test { address constant RECIPIENT = address(10); uint256 constant AMOUNT = 1 ether; diff --git a/test/foundry-tests/UniswapV3.t.sol b/test/foundry-tests/UniswapV3.t.sol new file mode 100644 index 00000000..e6cc87ce --- /dev/null +++ b/test/foundry-tests/UniswapV3.t.sol @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.15; + +import 'forge-std/Test.sol'; +import {Permit2} from 'permit2/src/Permit2.sol'; +import {ERC20, SafeTransferLib} from 'solmate/src/utils/SafeTransferLib.sol'; +import {IUniswapV3Factory} from '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol'; +import {IUniswapV3Pool} from '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol'; +import {IUniswapV3MintCallback} from '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol'; +import {UniversalRouter} from '../../contracts/UniversalRouter.sol'; +import {Payments} from '../../contracts/modules/Payments.sol'; +import {Constants} from '../../contracts/libraries/Constants.sol'; +import {Commands} from '../../contracts/libraries/Commands.sol'; +import {RouterParameters} from '../../contracts/base/RouterImmutables.sol'; + +abstract contract UniswapV3Test is Test, IUniswapV3MintCallback { + using SafeTransferLib for ERC20; + + /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128 + int24 internal constant MIN_TICK = -887272; + /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128 + int24 internal constant MAX_TICK = -MIN_TICK; + uint24 internal constant fee = 3000; + + address constant RECIPIENT = address(10); + uint256 constant AMOUNT = 1 ether; + uint256 constant BALANCE = 100000 ether; + IUniswapV3Factory constant FACTORY = IUniswapV3Factory(0x1F98431c8aD98523631AE4a59f267346ea31F984); + ERC20 constant WETH9 = ERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); + Permit2 constant PERMIT2 = Permit2(0x000000000022D473030F116dDEE9F6B43aC78BA3); + address constant FROM = address(1234); + + UniversalRouter router; + address pool; + + function setUp() public virtual { + vm.createSelectFork(vm.envString('FORK_URL'), 16000000); + setUpTokens(); + + RouterParameters memory params = RouterParameters({ + permit2: address(PERMIT2), + weth9: address(WETH9), + seaportV1_5: address(0), + seaportV1_4: address(0), + openseaConduit: address(0), + nftxZap: address(0), + x2y2: address(0), + foundation: address(0), + sudoswap: address(0), + elementMarket: address(0), + nft20Zap: address(0), + cryptopunks: address(0), + looksRareV2: address(0), + routerRewardsDistributor: address(0), + looksRareRewardsDistributor: address(0), + looksRareToken: address(0), + v2Factory: address(0), + v3Factory: address(FACTORY), + pairInitCodeHash: bytes32(0), + poolInitCodeHash: bytes32(0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54) + }); + router = new UniversalRouter(params); + + // pool doesn't exist, make a mock one + if (FACTORY.getPool(token0(), token1(), fee) == address(0)) { + pool = FACTORY.createPool(token0(), token1(), fee); + IUniswapV3Pool(pool).initialize(1 << 96); + int24 tickSpacing = IUniswapV3Pool(pool).tickSpacing(); + mint( + address(this), + MIN_TICK / tickSpacing * tickSpacing, + MAX_TICK / tickSpacing * tickSpacing, + uint128(AMOUNT * 10) + ); + } + vm.label(pool, 'pool'); + vm.label(token0(), 'token0'); + vm.label(token1(), 'token1'); + + vm.startPrank(FROM); + deal(FROM, BALANCE); + deal(token0(), FROM, BALANCE); + deal(token1(), FROM, BALANCE); + ERC20(token0()).approve(address(PERMIT2), type(uint256).max); + ERC20(token1()).approve(address(PERMIT2), type(uint256).max); + PERMIT2.approve(token0(), address(router), type(uint160).max, type(uint48).max); + PERMIT2.approve(token1(), address(router), type(uint160).max, type(uint48).max); + } + + /// @dev Pay pool to finish minting + function uniswapV3MintCallback(uint256 amount0Owed, uint256 amount1Owed, bytes calldata) external { + if (amount0Owed > 0) deal(token0(), msg.sender, amount0Owed); + if (amount1Owed > 0) deal(token1(), msg.sender, amount1Owed); + } + + /// @dev Make a direct pool mint + function mint(address recipient, int24 tickLower, int24 tickUpper, uint128 liquidity) internal { + IUniswapV3Pool(pool).mint(recipient, tickLower, tickUpper, liquidity, new bytes(0)); + } + + function testExactInput0For1() public { + bytes memory commands = abi.encodePacked(bytes1(uint8(Commands.V3_SWAP_EXACT_IN))); + bytes memory path = abi.encodePacked(token0(), fee, token1()); + bytes[] memory inputs = new bytes[](1); + inputs[0] = abi.encode(Constants.MSG_SENDER, AMOUNT, 0, path, true); + + router.execute(commands, inputs); + assertEq(ERC20(token0()).balanceOf(FROM), BALANCE - AMOUNT); + assertGt(ERC20(token1()).balanceOf(FROM), BALANCE); + } + + function testExactInput1For0() public { + bytes memory commands = abi.encodePacked(bytes1(uint8(Commands.V3_SWAP_EXACT_IN))); + bytes memory path = abi.encodePacked(token1(), fee, token0()); + bytes[] memory inputs = new bytes[](1); + inputs[0] = abi.encode(Constants.MSG_SENDER, AMOUNT, 0, path, true); + + router.execute(commands, inputs); + assertEq(ERC20(token1()).balanceOf(FROM), BALANCE - AMOUNT); + assertGt(ERC20(token0()).balanceOf(FROM), BALANCE); + } + + function testExactOutput0For1() public { + bytes memory commands = abi.encodePacked(bytes1(uint8(Commands.V3_SWAP_EXACT_OUT))); + bytes memory path = abi.encodePacked(token1(), fee, token0()); + bytes[] memory inputs = new bytes[](1); + inputs[0] = abi.encode(Constants.MSG_SENDER, AMOUNT, type(uint256).max, path, true); + + router.execute(commands, inputs); + assertLt(ERC20(token0()).balanceOf(FROM), BALANCE); + assertGe(ERC20(token1()).balanceOf(FROM), BALANCE + AMOUNT); + } + + function testExactOutput1For0() public { + bytes memory commands = abi.encodePacked(bytes1(uint8(Commands.V3_SWAP_EXACT_OUT))); + bytes memory path = abi.encodePacked(token0(), fee, token1()); + bytes[] memory inputs = new bytes[](1); + inputs[0] = abi.encode(Constants.MSG_SENDER, AMOUNT, type(uint256).max, path, true); + + router.execute(commands, inputs); + assertLt(ERC20(token1()).balanceOf(FROM), BALANCE); + assertGe(ERC20(token0()).balanceOf(FROM), BALANCE + AMOUNT); + } + + function token0() internal virtual returns (address); + function token1() internal virtual returns (address); + + function setUpTokens() internal virtual; +} diff --git a/test/foundry-tests/uniswapTokens/v3MockMock.t.sol b/test/foundry-tests/uniswapTokens/v3MockMock.t.sol new file mode 100644 index 00000000..2616ceac --- /dev/null +++ b/test/foundry-tests/uniswapTokens/v3MockMock.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.15; + +import 'forge-std/Test.sol'; +import {MockERC20} from '../mock/MockERC20.sol'; +import {UniswapV3Test} from '../UniswapV3.t.sol'; + +contract V3MockMock is UniswapV3Test { + MockERC20 mockA; + MockERC20 mockB; + + function setUpTokens() internal override { + mockA = new MockERC20(); + mockB = new MockERC20(); + } + + function token0() internal view override returns (address) { + return address(mockA); + } + + function token1() internal view override returns (address) { + return address(mockB); + } +} 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 6e029571..6f8e8da6 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,34 +3,34 @@ exports[`Check Ownership Gas gas: balance check ERC20 1`] = ` Object { "calldataByteLength": 356, - "gasUsed": 39837, + "gasUsed": 39813, } `; exports[`Check Ownership Gas gas: checks ownership after a seaport trade, one NFT 1`] = ` Object { "calldataByteLength": 2180, - "gasUsed": 185340, + "gasUsed": 185298, } `; exports[`Check Ownership Gas gas: checks ownership after a seaport trade, two NFTs 1`] = ` Object { "calldataByteLength": 5028, - "gasUsed": 294767, + "gasUsed": 294713, } `; exports[`Check Ownership Gas gas: does not check ownership after a seaport trade, one NFT 1`] = ` Object { "calldataByteLength": 2020, - "gasUsed": 182447, + "gasUsed": 182423, } `; exports[`Check Ownership Gas gas: just ownership check 1`] = ` Object { "calldataByteLength": 356, - "gasUsed": 32519, + "gasUsed": 32501, } `; diff --git a/test/integration-tests/gas-tests/__snapshots__/CryptoPunk.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/CryptoPunk.gas.test.ts.snap index bd5c70ec..38dcfd92 100644 --- a/test/integration-tests/gas-tests/__snapshots__/CryptoPunk.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/CryptoPunk.gas.test.ts.snap @@ -3,6 +3,6 @@ exports[`Cryptopunks purchases 1 cryptopunk gas 1`] = ` Object { "calldataByteLength": 356, - "gasUsed": 109587, + "gasUsed": 109562, } `; diff --git a/test/integration-tests/gas-tests/__snapshots__/Element.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/Element.gas.test.ts.snap index e7e41b73..dd6e375b 100644 --- a/test/integration-tests/gas-tests/__snapshots__/Element.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/Element.gas.test.ts.snap @@ -3,6 +3,6 @@ exports[`Element Market gas tests gas: purchases open order 1`] = ` Object { "calldataByteLength": 964, - "gasUsed": 123947, + "gasUsed": 123929, } `; diff --git a/test/integration-tests/gas-tests/__snapshots__/Foundation.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/Foundation.gas.test.ts.snap index 43748aee..3092237f 100644 --- a/test/integration-tests/gas-tests/__snapshots__/Foundation.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/Foundation.gas.test.ts.snap @@ -3,6 +3,6 @@ exports[`Foundation Gas Tests Buy a mental worlds NFT from Foundation gas: token id 32 of mental worlds 1`] = ` Object { "calldataByteLength": 612, - "gasUsed": 182987, + "gasUsed": 182972, } `; diff --git a/test/integration-tests/gas-tests/__snapshots__/LooksRareV2.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/LooksRareV2.gas.test.ts.snap index f000a1f9..2d0fb131 100644 --- a/test/integration-tests/gas-tests/__snapshots__/LooksRareV2.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/LooksRareV2.gas.test.ts.snap @@ -3,13 +3,13 @@ exports[`LooksRareV2 Gas Test Bulk Buy Buys 2 721s 1`] = ` Object { "calldataByteLength": 2884, - "gasUsed": 335502, + "gasUsed": 335484, } `; exports[`LooksRareV2 Gas Test Single Buy Buy a 721 1`] = ` Object { "calldataByteLength": 1508, - "gasUsed": 189890, + "gasUsed": 189872, } `; diff --git a/test/integration-tests/gas-tests/__snapshots__/NFT20.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/NFT20.gas.test.ts.snap index 7854cf4a..a442474b 100644 --- a/test/integration-tests/gas-tests/__snapshots__/NFT20.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/NFT20.gas.test.ts.snap @@ -3,6 +3,6 @@ exports[`NFT20 Buy 3 alphabetties from NFT20 gas: purchases token ids 129, 193, 278 of Alphabetties 1`] = ` Object { "calldataByteLength": 836, - "gasUsed": 392225, + "gasUsed": 392207, } `; diff --git a/test/integration-tests/gas-tests/__snapshots__/NFTX.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/NFTX.gas.test.ts.snap index 61efee2a..12905902 100644 --- a/test/integration-tests/gas-tests/__snapshots__/NFTX.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/NFTX.gas.test.ts.snap @@ -3,6 +3,6 @@ exports[`NFTX Gas Tests gas: buyAndRedeem w/ specific selection 1`] = ` Object { "calldataByteLength": 964, - "gasUsed": 574870, + "gasUsed": 574855, } `; 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 611d0a42..4cbb3552 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,55 +3,55 @@ exports[`Payments Gas Tests Individual Command Tests gas: APPROVE_ERC20 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 53851, + "gasUsed": 53827, } `; exports[`Payments Gas Tests Individual Command Tests gas: SWEEP with ERC20 1`] = ` Object { "calldataByteLength": 356, - "gasUsed": 39235, + "gasUsed": 39223, } `; exports[`Payments Gas Tests Individual Command Tests gas: SWEEP_WITH_FEE 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 67925, + "gasUsed": 67901, } `; exports[`Payments Gas Tests Individual Command Tests gas: TRANSFER with ERC20 1`] = ` Object { "calldataByteLength": 356, - "gasUsed": 38248, + "gasUsed": 38236, } `; exports[`Payments Gas Tests Individual Command Tests gas: TRANSFER with ETH 1`] = ` Object { "calldataByteLength": 356, - "gasUsed": 33821, + "gasUsed": 33806, } `; exports[`Payments Gas Tests Individual Command Tests gas: UNWRAP_WETH 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 46765, + "gasUsed": 46744, } `; exports[`Payments Gas Tests Individual Command Tests gas: UNWRAP_WETH_WITH_FEE 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 53127, + "gasUsed": 53082, } `; exports[`Payments Gas Tests Individual Command Tests gas: WRAP_ETH 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 57425, + "gasUsed": 57406, } `; diff --git a/test/integration-tests/gas-tests/__snapshots__/SeaportV1_4.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/SeaportV1_4.gas.test.ts.snap index ab59cc35..fdf6e45e 100644 --- a/test/integration-tests/gas-tests/__snapshots__/SeaportV1_4.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/SeaportV1_4.gas.test.ts.snap @@ -3,13 +3,13 @@ exports[`Seaport v1.4 Gas Tests ERC20 -> NFT gas: fulfillAdvancedOrder 1`] = ` Object { "calldataByteLength": 2532, - "gasUsed": 237135, + "gasUsed": 237051, } `; exports[`Seaport v1.4 Gas Tests ETH -> NFT gas: fulfillAdvancedOrder 1`] = ` Object { "calldataByteLength": 2020, - "gasUsed": 182447, + "gasUsed": 182423, } `; diff --git a/test/integration-tests/gas-tests/__snapshots__/SeaportV1_5.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/SeaportV1_5.gas.test.ts.snap index 0cb15f1c..285a5112 100644 --- a/test/integration-tests/gas-tests/__snapshots__/SeaportV1_5.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/SeaportV1_5.gas.test.ts.snap @@ -3,13 +3,13 @@ exports[`Seaport v1.5 Gas Tests ETH -> NFT gas: fulfillAdvancedOrder 1`] = ` Object { "calldataByteLength": 2020, - "gasUsed": 152097, + "gasUsed": 152082, } `; exports[`Seaport v1.5 Gas Tests ETH -> NFT gas: fulfillAvailableAdvancedOrders 2 orders 1`] = ` Object { "calldataByteLength": 4644, - "gasUsed": 288379, + "gasUsed": 288361, } `; diff --git a/test/integration-tests/gas-tests/__snapshots__/Sudoswap.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/Sudoswap.gas.test.ts.snap index a244721d..b02fe878 100644 --- a/test/integration-tests/gas-tests/__snapshots__/Sudoswap.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/Sudoswap.gas.test.ts.snap @@ -3,20 +3,20 @@ exports[`Sudoswap Gas Tests ERC20 -> NFT gas: purchases NFTs with FRAX ERC20 token already approved 1`] = ` Object { "calldataByteLength": 1380, - "gasUsed": 289920, + "gasUsed": 289866, } `; exports[`Sudoswap Gas Tests ERC20 -> NFT gas: purchases tokens 2402, 2509 of Based Ghoul with FRAX ERC20 token 1`] = ` Object { "calldataByteLength": 1508, - "gasUsed": 311549, + "gasUsed": 311471, } `; exports[`Sudoswap Gas Tests ETH -> NFT gas: purchases token ids 173, 239, 240 of Sudolets 1`] = ` Object { "calldataByteLength": 836, - "gasUsed": 201657, + "gasUsed": 201639, } `; 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 ea83a9a4..cac8b9c0 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": 273152, + "gasUsed": 271117, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Batch reverts gas: 2 sub-plans, neither fails 1`] = ` Object { "calldataByteLength": 1764, - "gasUsed": 248874, + "gasUsed": 246829, } `; 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": 248874, + "gasUsed": 246829, } `; 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": 273152, + "gasUsed": 271117, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Interleaving routes gas: V2, then V3 1`] = ` Object { "calldataByteLength": 836, - "gasUsed": 196828, + "gasUsed": 195538, } `; exports[`Uniswap Gas Tests Mixing V2 and V3 with Universal Router. Interleaving routes gas: V3, then V2 1`] = ` Object { "calldataByteLength": 836, - "gasUsed": 189624, + "gasUsed": 188334, } `; 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": 305306, + "gasUsed": 303445, } `; 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": 313366, + "gasUsed": 311527, } `; 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": 315444, + "gasUsed": 313560, } `; 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": 309818, + "gasUsed": 308003, } `; 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": 179794, + "gasUsed": 178492, } `; 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": 179569, + "gasUsed": 178267, } `; 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": 198235, + "gasUsed": 196826, } `; 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": 187631, + "gasUsed": 186320, } `; 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": 200312, + "gasUsed": 198896, } `; @@ -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": 128824, + "gasUsed": 128262, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, one hop 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 109042, + "gasUsed": 108504, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, three hops 1`] = ` Object { "calldataByteLength": 580, - "gasUsed": 246952, + "gasUsed": 245676, } `; 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": 246694, + "gasUsed": 245418, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, two hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 179686, + "gasUsed": 178794, } `; 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": 179686, + "gasUsed": 178794, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, one hop 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 109016, + "gasUsed": 108443, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, three hops 1`] = ` Object { "calldataByteLength": 580, - "gasUsed": 252135, + "gasUsed": 250038, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, two hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 182300, + "gasUsed": 180944, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ETH gas: exactIn, one trade, one hop 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 125258, + "gasUsed": 124699, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ETH gas: exactOut, one trade, one hop 1`] = ` Object { "calldataByteLength": 804, - "gasUsed": 130417, + "gasUsed": 129855, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ERC20 --> ETH gas: exactOut, with ETH fee 1`] = ` Object { "calldataByteLength": 964, - "gasUsed": 138406, + "gasUsed": 137832, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ETH --> ERC20 gas: exactIn, one trade, one hop 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 108953, + "gasUsed": 108359, } `; exports[`Uniswap Gas Tests Trade on UniswapV2 with Universal Router. ETH --> ERC20 gas: exactOut, one trade, one hop 1`] = ` Object { "calldataByteLength": 772, - "gasUsed": 127616, + "gasUsed": 126998, } `; @@ -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": 117144, + "gasUsed": 116392, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, three hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 276366, + "gasUsed": 274118, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactIn, one trade, two hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 192426, + "gasUsed": 190898, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, one hop 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 118771, + "gasUsed": 117913, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, three hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 421314, + "gasUsed": 419295, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ERC20 gas: exactOut, one trade, two hops 1`] = ` Object { "calldataByteLength": 548, - "gasUsed": 315013, + "gasUsed": 313566, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ETH gas: exactIn swap 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 133408, + "gasUsed": 132635, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ERC20 --> ETH gas: exactOut swap 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 135107, + "gasUsed": 134228, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ETH --> ERC20 gas: exactIn swap 1`] = ` Object { "calldataByteLength": 644, - "gasUsed": 242391, + "gasUsed": 241557, } `; exports[`Uniswap Gas Tests Trade on UniswapV3 with Universal Router. ETH --> ERC20 gas: exactOut swap 1`] = ` Object { "calldataByteLength": 772, - "gasUsed": 129590, + "gasUsed": 128705, } `; 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 eaf4b768..40d37155 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,24 +1,24 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`UniversalRouter Gas Tests gas: bytecode size 1`] = `18307`; +exports[`UniversalRouter Gas Tests gas: bytecode size 1`] = `17851`; exports[`UniversalRouter Gas Tests trading for NFTs gas: ERC20 --> ETH --> Seaport NFT 1`] = ` Object { "calldataByteLength": 2468, - "gasUsed": 252703, + "gasUsed": 252136, } `; exports[`UniversalRouter Gas Tests trading for NFTs gas: ETH --> Seaport NFT 1`] = ` Object { "calldataByteLength": 2020, - "gasUsed": 152097, + "gasUsed": 152082, } `; exports[`UniversalRouter Gas Tests trading for NFTs gas: WETH --> ETH --> Seaport NFT 1`] = ` Object { "calldataByteLength": 2308, - "gasUsed": 186861, + "gasUsed": 186814, } `; 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 5c3725a0..d639c0dc 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`] = `1162636`; +exports[`Uniswap UX Tests gas: Comparisons Casual Swapper - 3 swaps Permit2 Max Approval Swap 1`] = `1153820`; -exports[`Uniswap UX Tests gas: Comparisons Casual Swapper - 3 swaps Permit2 Sign Per Swap 1`] = `1197018`; +exports[`Uniswap UX Tests gas: Comparisons Casual Swapper - 3 swaps Permit2 Sign Per Swap 1`] = `1188154`; exports[`Uniswap UX Tests gas: Comparisons Casual Swapper - 3 swaps SwapRouter02 1`] = `1172945`; -exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper - 10 swaps Permit2 Max Approval Swap 1`] = `3240424`; +exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper - 10 swaps Permit2 Max Approval Swap 1`] = `3214600`; -exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper - 10 swaps Permit2 Sign Per Swap 1`] = `3393845`; +exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper - 10 swaps Permit2 Sign Per Swap 1`] = `3367805`; exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper - 10 swaps SwapRouter02 1`] = `3320620`; -exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper across 3 swap router versions - 15 swaps across 3 versions Permit2 Max Approval Swap 1`] = `4330328`; +exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper across 3 swap router versions - 15 swaps across 3 versions Permit2 Max Approval Swap 1`] = `4296816`; -exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper across 3 swap router versions - 15 swaps across 3 versions Permit2 Sign Per Swap 1`] = `4534102`; +exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper across 3 swap router versions - 15 swaps across 3 versions Permit2 Sign Per Swap 1`] = `4500302`; exports[`Uniswap UX Tests gas: Comparisons Frequent Swapper across 3 swap router versions - 15 swaps across 3 versions SwapRouter02 1`] = `4470036`; -exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Complex Swap Permit2 Max Approval Swap 1`] = `533020`; +exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Complex Swap Permit2 Max Approval Swap 1`] = `529364`; -exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Complex Swap Permit2 Sign Per Swap 1`] = `533338`; +exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Complex Swap Permit2 Sign Per Swap 1`] = `529682`; exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Complex Swap SwapRouter02 1`] = `520492`; -exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Simple Swap Permit2 Max Approval Swap 1`] = `310739`; +exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Simple Swap Permit2 Max Approval Swap 1`] = `309187`; -exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Simple Swap Permit2 Sign Per Swap 1`] = `310675`; +exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Simple Swap Permit2 Sign Per Swap 1`] = `309123`; exports[`Uniswap UX Tests gas: Comparisons One Time Swapper - Simple Swap SwapRouter02 1`] = `278117`; diff --git a/test/integration-tests/gas-tests/__snapshots__/X2Y2.gas.test.ts.snap b/test/integration-tests/gas-tests/__snapshots__/X2Y2.gas.test.ts.snap index 3ad231a8..4f364da0 100644 --- a/test/integration-tests/gas-tests/__snapshots__/X2Y2.gas.test.ts.snap +++ b/test/integration-tests/gas-tests/__snapshots__/X2Y2.gas.test.ts.snap @@ -3,13 +3,13 @@ exports[`X2Y2 ERC-721 purchase gas: purchases 1 ERC-721 on X2Y2 1`] = ` Object { "calldataByteLength": 2212, - "gasUsed": 210135, + "gasUsed": 210123, } `; exports[`X2Y2 ERC-1155 purchase gas: purchases 1 ERC-1155 on X2Y2 1`] = ` Object { "calldataByteLength": 2276, - "gasUsed": 211192, + "gasUsed": 211180, } `;