From d526f7593c9e7e18dbe0bb7f20b610775c49db01 Mon Sep 17 00:00:00 2001 From: Mark Toda Date: Thu, 16 Nov 2023 16:07:02 -0500 Subject: [PATCH 01/12] feat: update v4-core This commit updates v4 core to latest and fixes integration issues --- .env | 9 ++++ contracts/BaseHook.sol | 10 ++-- contracts/hooks/examples/FullRange.sol | 28 +++++------ contracts/hooks/examples/GeomeanOracle.sol | 10 ++-- contracts/hooks/examples/LimitOrder.sol | 42 +++++++++-------- contracts/hooks/examples/TWAMM.sol | 24 +++++----- contracts/hooks/examples/VolatilityOracle.sol | 16 +++---- contracts/interfaces/ITWAMM.sol | 10 ++-- contracts/libraries/LiquidityAmounts.sol | 4 +- contracts/libraries/PoolGetters.sol | 8 ++-- contracts/libraries/TWAMM/TwammMath.sol | 6 +-- contracts/libraries/TransferHelper.sol | 2 +- lib/v4-core | 2 +- test/FullRange.t.sol | 46 +++++++------------ test/GeomeanOracle.t.sol | 30 +++++------- test/LimitOrder.t.sol | 34 +++++--------- test/TWAMM.t.sol | 40 ++++++---------- .../FullRangeImplementation.sol | 4 +- .../GeomeanOracleImplementation.sol | 4 +- .../LimitOrderImplementation.sol | 4 +- .../implementation/TWAMMImplementation.sol | 4 +- 21 files changed, 152 insertions(+), 185 deletions(-) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 00000000..721bb082 --- /dev/null +++ b/.env @@ -0,0 +1,9 @@ +FOUNDRY_FUZZ_SEED=0x4444 + +if [[ "$OSTYPE" == "linux-gnu"* ]]; then + export FOUNDRY_SOLC="./lib/v4-core/bin/solc-static-linux" +elif [[ "$OSTYPE" == "darwin"* ]]; then + export FOUNDRY_SOLC="./lib/v4-core/bin/solc-mac" +fi + +# FOUNDRY_SOLC="./bin/solc-static-linux" diff --git a/contracts/BaseHook.sol b/contracts/BaseHook.sol index 8d463807..a16ab91d 100644 --- a/contracts/BaseHook.sol +++ b/contracts/BaseHook.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; -import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; -import {IHooks} from "@uniswap/v4-core/contracts/interfaces/IHooks.sol"; -import {BalanceDelta} from "@uniswap/v4-core/contracts/types/BalanceDelta.sol"; -import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol"; +import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; abstract contract BaseHook is IHooks { error NotPoolManager(); diff --git a/contracts/hooks/examples/FullRange.sol b/contracts/hooks/examples/FullRange.sol index 6c5b08ec..eaa7539b 100644 --- a/contracts/hooks/examples/FullRange.sol +++ b/contracts/hooks/examples/FullRange.sol @@ -1,22 +1,22 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; -import {PoolManager} from "@uniswap/v4-core/contracts/PoolManager.sol"; -import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {PoolManager} from "@uniswap/v4-core/src/PoolManager.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; import {BaseHook} from "../../BaseHook.sol"; -import {SafeCast} from "@uniswap/v4-core/contracts/libraries/SafeCast.sol"; -import {IHooks} from "@uniswap/v4-core/contracts/interfaces/IHooks.sol"; -import {CurrencyLibrary, Currency} from "@uniswap/v4-core/contracts/types/Currency.sol"; -import {TickMath} from "@uniswap/v4-core/contracts/libraries/TickMath.sol"; -import {BalanceDelta} from "@uniswap/v4-core/contracts/types/BalanceDelta.sol"; -import {IERC20Minimal} from "@uniswap/v4-core/contracts/interfaces/external/IERC20Minimal.sol"; -import {ILockCallback} from "@uniswap/v4-core/contracts/interfaces/callback/ILockCallback.sol"; -import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/contracts/types/PoolId.sol"; -import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol"; -import {FullMath} from "@uniswap/v4-core/contracts/libraries/FullMath.sol"; +import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol"; +import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol"; +import {CurrencyLibrary, Currency} from "@uniswap/v4-core/src/types/Currency.sol"; +import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol"; +import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; +import {IERC20Minimal} from "@uniswap/v4-core/src/interfaces/external/IERC20Minimal.sol"; +import {ILockCallback} from "@uniswap/v4-core/src/interfaces/callback/ILockCallback.sol"; +import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; +import {FullMath} from "@uniswap/v4-core/src/libraries/FullMath.sol"; import {UniswapV4ERC20} from "../../libraries/UniswapV4ERC20.sol"; -import {FixedPoint96} from "@uniswap/v4-core/contracts/libraries/FixedPoint96.sol"; +import {FixedPoint96} from "@uniswap/v4-core/src/libraries/FixedPoint96.sol"; import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol"; import {IERC20Metadata} from "@openzeppelin/contracts/interfaces/IERC20Metadata.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; diff --git a/contracts/hooks/examples/GeomeanOracle.sol b/contracts/hooks/examples/GeomeanOracle.sol index 5c78e785..8ae1c640 100644 --- a/contracts/hooks/examples/GeomeanOracle.sol +++ b/contracts/hooks/examples/GeomeanOracle.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; -import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/contracts/types/PoolId.sol"; -import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; -import {TickMath} from "@uniswap/v4-core/contracts/libraries/TickMath.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; +import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol"; import {Oracle} from "../../libraries/Oracle.sol"; import {BaseHook} from "../../BaseHook.sol"; -import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; /// @notice A hook for a pool that allows a Uniswap pool to act as an oracle. Pools that use this hook must have full range /// tick spacing and liquidity is always permanently locked in these pools. This is the suggested configuration diff --git a/contracts/hooks/examples/LimitOrder.sol b/contracts/hooks/examples/LimitOrder.sol index 8eff6c68..d2654f49 100644 --- a/contracts/hooks/examples/LimitOrder.sol +++ b/contracts/hooks/examples/LimitOrder.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; -import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/contracts/types/PoolId.sol"; -import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; -import {FullMath} from "@uniswap/v4-core/contracts/libraries/FullMath.sol"; -import {SafeCast} from "@uniswap/v4-core/contracts/libraries/SafeCast.sol"; -import {IERC20Minimal} from "@uniswap/v4-core/contracts/interfaces/external/IERC20Minimal.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; +import {FullMath} from "@uniswap/v4-core/src/libraries/FullMath.sol"; +import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol"; +import {IERC20Minimal} from "@uniswap/v4-core/src/interfaces/external/IERC20Minimal.sol"; import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; import {BaseHook} from "../../BaseHook.sol"; -import {Currency, CurrencyLibrary} from "@uniswap/v4-core/contracts/types/Currency.sol"; -import {BalanceDelta} from "@uniswap/v4-core/contracts/types/BalanceDelta.sol"; -import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol"; +import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol"; +import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; type Epoch is uint232; @@ -204,8 +204,12 @@ contract LimitOrder is BaseHook { ZERO_BYTES ); - if (delta.amount0() < 0) poolManager.mint(key.currency0, address(this), amount0 = uint128(-delta.amount0())); - if (delta.amount1() < 0) poolManager.mint(key.currency1, address(this), amount1 = uint128(-delta.amount1())); + if (delta.amount0() < 0) { + poolManager.mint(key.currency0, address(this), amount0 = uint128(-delta.amount0())); + } + if (delta.amount1() < 0) { + poolManager.mint(key.currency1, address(this), amount1 = uint128(-delta.amount1())); + } } function place(PoolKey calldata key, int24 tickLower, bool zeroForOne, uint128 liquidity) @@ -352,8 +356,12 @@ contract LimitOrder is BaseHook { ZERO_BYTES ); - if (delta.amount0() < 0) poolManager.take(key.currency0, to, amount0 = uint128(-delta.amount0())); - if (delta.amount1() < 0) poolManager.take(key.currency1, to, amount1 = uint128(-delta.amount1())); + if (delta.amount0() < 0) { + poolManager.take(key.currency0, to, amount0 = uint128(-delta.amount0())); + } + if (delta.amount1() < 0) { + poolManager.take(key.currency1, to, amount1 = uint128(-delta.amount1())); + } } function withdraw(Epoch epoch, address to) external returns (uint256 amount0, uint256 amount1) { @@ -391,15 +399,11 @@ contract LimitOrder is BaseHook { address to ) external selfOnly { if (token0Amount > 0) { - poolManager.safeTransferFrom( - address(this), address(poolManager), uint256(uint160(Currency.unwrap(currency0))), token0Amount, "" - ); + poolManager.burn(currency0, token0Amount); poolManager.take(currency0, to, token0Amount); } if (token1Amount > 0) { - poolManager.safeTransferFrom( - address(this), address(poolManager), uint256(uint160(Currency.unwrap(currency1))), token1Amount, "" - ); + poolManager.burn(currency1, token1Amount); poolManager.take(currency1, to, token1Amount); } } diff --git a/contracts/hooks/examples/TWAMM.sol b/contracts/hooks/examples/TWAMM.sol index 55d44888..a6635e94 100644 --- a/contracts/hooks/examples/TWAMM.sol +++ b/contracts/hooks/examples/TWAMM.sol @@ -1,24 +1,24 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.15; -import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; -import {TickBitmap} from "@uniswap/v4-core/contracts/libraries/TickBitmap.sol"; -import {SqrtPriceMath} from "@uniswap/v4-core/contracts/libraries/SqrtPriceMath.sol"; -import {FixedPoint96} from "@uniswap/v4-core/contracts/libraries/FixedPoint96.sol"; -import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/contracts/types/PoolId.sol"; -import {SafeCast} from "@uniswap/v4-core/contracts/libraries/SafeCast.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; +import {TickBitmap} from "@uniswap/v4-core/src/libraries/TickBitmap.sol"; +import {SqrtPriceMath} from "@uniswap/v4-core/src/libraries/SqrtPriceMath.sol"; +import {FixedPoint96} from "@uniswap/v4-core/src/libraries/FixedPoint96.sol"; +import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol"; +import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol"; import {BaseHook} from "../../BaseHook.sol"; -import {IERC20Minimal} from "@uniswap/v4-core/contracts/interfaces/external/IERC20Minimal.sol"; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; +import {IERC20Minimal} from "@uniswap/v4-core/src/interfaces/external/IERC20Minimal.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {ITWAMM} from "../../interfaces/ITWAMM.sol"; -import {TickMath} from "@uniswap/v4-core/contracts/libraries/TickMath.sol"; +import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol"; import {TransferHelper} from "../../libraries/TransferHelper.sol"; import {TwammMath} from "../../libraries/TWAMM/TwammMath.sol"; import {OrderPool} from "../../libraries/TWAMM/OrderPool.sol"; -import {Currency, CurrencyLibrary} from "@uniswap/v4-core/contracts/types/Currency.sol"; -import {BalanceDelta} from "@uniswap/v4-core/contracts/types/BalanceDelta.sol"; +import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol"; +import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; import {PoolGetters} from "../../libraries/PoolGetters.sol"; -import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; contract TWAMM is BaseHook, ITWAMM { using TransferHelper for IERC20Minimal; diff --git a/contracts/hooks/examples/VolatilityOracle.sol b/contracts/hooks/examples/VolatilityOracle.sol index 0a7e696d..65485e11 100644 --- a/contracts/hooks/examples/VolatilityOracle.sol +++ b/contracts/hooks/examples/VolatilityOracle.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; -import {IDynamicFeeManager} from "@uniswap/v4-core/contracts/interfaces/IDynamicFeeManager.sol"; -import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; -import {FeeLibrary} from "@uniswap/v4-core/contracts/libraries/FeeLibrary.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {IDynamicFeeManager} from "@uniswap/v4-core/src/interfaces/IDynamicFeeManager.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; +import {FeeLibrary} from "@uniswap/v4-core/src/libraries/FeeLibrary.sol"; import {BaseHook} from "../../BaseHook.sol"; -import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; contract VolatilityOracle is BaseHook, IDynamicFeeManager { using FeeLibrary for uint24; @@ -15,11 +15,7 @@ contract VolatilityOracle is BaseHook, IDynamicFeeManager { uint32 deployTimestamp; - function getFee(address, PoolKey calldata, IPoolManager.SwapParams calldata, bytes calldata) - external - view - returns (uint24) - { + function getFee(address, PoolKey calldata) external view returns (uint24) { uint24 startingFee = 3000; uint32 lapsed = _blockTimestamp() - deployTimestamp; return startingFee + (uint24(lapsed) * 100) / 60; // 100 bps a minute diff --git a/contracts/interfaces/ITWAMM.sol b/contracts/interfaces/ITWAMM.sol index 570617b6..3b932d3c 100644 --- a/contracts/interfaces/ITWAMM.sol +++ b/contracts/interfaces/ITWAMM.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.15; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; -import {IERC20Minimal} from "@uniswap/v4-core/contracts/interfaces/external/IERC20Minimal.sol"; -import {Currency, CurrencyLibrary} from "@uniswap/v4-core/contracts/types/Currency.sol"; -import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/contracts/types/PoolId.sol"; -import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {IERC20Minimal} from "@uniswap/v4-core/src/interfaces/external/IERC20Minimal.sol"; +import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol"; +import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; interface ITWAMM { /// @notice Thrown when account other than owner attempts to interact with an order diff --git a/contracts/libraries/LiquidityAmounts.sol b/contracts/libraries/LiquidityAmounts.sol index b2c8b54c..845cc6e0 100644 --- a/contracts/libraries/LiquidityAmounts.sol +++ b/contracts/libraries/LiquidityAmounts.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; -import "@uniswap/v4-core/contracts/libraries/FullMath.sol"; -import "@uniswap/v4-core/contracts/libraries/FixedPoint96.sol"; +import "@uniswap/v4-core/src/libraries/FullMath.sol"; +import "@uniswap/v4-core/src/libraries/FixedPoint96.sol"; /// @title Liquidity amount functions /// @notice Provides functions for computing liquidity amounts from token amounts and prices diff --git a/contracts/libraries/PoolGetters.sol b/contracts/libraries/PoolGetters.sol index d2c7fbf2..78f34c87 100644 --- a/contracts/libraries/PoolGetters.sol +++ b/contracts/libraries/PoolGetters.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; -import {Pool} from "@uniswap/v4-core/contracts/libraries/Pool.sol"; -import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/contracts/types/PoolId.sol"; -import {BitMath} from "@uniswap/v4-core/contracts/libraries/BitMath.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {Pool} from "@uniswap/v4-core/src/libraries/Pool.sol"; +import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol"; +import {BitMath} from "@uniswap/v4-core/src/libraries/BitMath.sol"; /// @title Helper functions to access pool information library PoolGetters { diff --git a/contracts/libraries/TWAMM/TwammMath.sol b/contracts/libraries/TWAMM/TwammMath.sol index 133a68c7..a5994b51 100644 --- a/contracts/libraries/TWAMM/TwammMath.sol +++ b/contracts/libraries/TWAMM/TwammMath.sol @@ -2,9 +2,9 @@ pragma solidity ^0.8.15; import {ABDKMathQuad} from "./ABDKMathQuad.sol"; -import {FixedPoint96} from "@uniswap/v4-core/contracts/libraries/FixedPoint96.sol"; -import {SafeCast} from "@uniswap/v4-core/contracts/libraries/SafeCast.sol"; -import {TickMath} from "@uniswap/v4-core/contracts/libraries/TickMath.sol"; +import {FixedPoint96} from "@uniswap/v4-core/src/libraries/FixedPoint96.sol"; +import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol"; +import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol"; /// @title TWAMM Math - Pure functions for TWAMM math calculations library TwammMath { diff --git a/contracts/libraries/TransferHelper.sol b/contracts/libraries/TransferHelper.sol index 5b1833a7..9ab40d9e 100644 --- a/contracts/libraries/TransferHelper.sol +++ b/contracts/libraries/TransferHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.15; -import {IERC20Minimal} from "@uniswap/v4-core/contracts/interfaces/external/IERC20Minimal.sol"; +import {IERC20Minimal} from "@uniswap/v4-core/src/interfaces/external/IERC20Minimal.sol"; /// @title TransferHelper /// @notice Contains helper methods for interacting with ERC20 tokens that do not consistently return true/false diff --git a/lib/v4-core b/lib/v4-core index 0095e084..7998e6c3 160000 --- a/lib/v4-core +++ b/lib/v4-core @@ -1 +1 @@ -Subproject commit 0095e0848098c3e32e016eac6d2537b67aa47358 +Subproject commit 7998e6c391b77d2a8455f902097b0180b579db1b diff --git a/test/FullRange.t.sol b/test/FullRange.t.sol index fa9d13ed..0658d683 100644 --- a/test/FullRange.t.sol +++ b/test/FullRange.t.sol @@ -3,22 +3,22 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol"; -import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; import {FullRange} from "../contracts/hooks/examples/FullRange.sol"; import {FullRangeImplementation} from "./shared/implementation/FullRangeImplementation.sol"; -import {PoolManager} from "@uniswap/v4-core/contracts/PoolManager.sol"; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; -import {Deployers} from "@uniswap/v4-core/test/foundry-tests/utils/Deployers.sol"; -import {MockERC20} from "@uniswap/v4-core/test/foundry-tests/utils/MockERC20.sol"; -import {Currency, CurrencyLibrary} from "@uniswap/v4-core/contracts/types/Currency.sol"; -import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/contracts/types/PoolId.sol"; -import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol"; -import {PoolModifyPositionTest} from "@uniswap/v4-core/contracts/test/PoolModifyPositionTest.sol"; -import {PoolSwapTest} from "@uniswap/v4-core/contracts/test/PoolSwapTest.sol"; -import {IHooks} from "@uniswap/v4-core/contracts/interfaces/IHooks.sol"; +import {PoolManager} from "@uniswap/v4-core/src/PoolManager.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {Deployers} from "@uniswap/v4-core/test/utils/Deployers.sol"; +import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol"; +import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol"; +import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; +import {PoolModifyPositionTest} from "@uniswap/v4-core/src/test/PoolModifyPositionTest.sol"; +import {PoolSwapTest} from "@uniswap/v4-core/src/test/PoolSwapTest.sol"; +import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol"; import {UniswapV4ERC20} from "../contracts/libraries/UniswapV4ERC20.sol"; -import {FullMath} from "@uniswap/v4-core/contracts/libraries/FullMath.sol"; -import {SafeCast} from "@uniswap/v4-core/contracts/libraries/SafeCast.sol"; +import {FullMath} from "@uniswap/v4-core/src/libraries/FullMath.sol"; +import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol"; contract TestFullRange is Test, Deployers, GasSnapshot { using PoolIdLibrary for PoolKey; @@ -62,15 +62,10 @@ contract TestFullRange is Test, Deployers, GasSnapshot { MockERC20 token1; MockERC20 token2; - Currency currency0; - Currency currency1; - - PoolManager manager; FullRangeImplementation fullRange = FullRangeImplementation( address(uint160(Hooks.BEFORE_INITIALIZE_FLAG | Hooks.BEFORE_MODIFY_POSITION_FLAG | Hooks.BEFORE_SWAP_FLAG)) ); - PoolKey key; PoolId id; PoolKey key2; @@ -80,20 +75,14 @@ contract TestFullRange is Test, Deployers, GasSnapshot { PoolKey keyWithLiq; PoolId idWithLiq; - PoolModifyPositionTest modifyPositionRouter; - PoolSwapTest swapRouter; - function setUp() public { - token0 = new MockERC20("TestA", "A", 18, 2 ** 128); - token1 = new MockERC20("TestB", "B", 18, 2 ** 128); - token2 = new MockERC20("TestC", "C", 18, 2 ** 128); - - manager = new PoolManager(500000); + token0 = new MockERC20("TestA", "A", 18); + token1 = new MockERC20("TestB", "B", 18); + token2 = new MockERC20("TestC", "C", 18); FullRangeImplementation impl = new FullRangeImplementation(manager, fullRange); vm.etch(address(fullRange), address(impl).code); - key = createPoolKey(token0, token1); id = key.toId(); key2 = createPoolKey(token1, token2); @@ -102,9 +91,6 @@ contract TestFullRange is Test, Deployers, GasSnapshot { keyWithLiq = createPoolKey(token0, token2); idWithLiq = keyWithLiq.toId(); - modifyPositionRouter = new PoolModifyPositionTest(manager); - swapRouter = new PoolSwapTest(manager); - token0.approve(address(fullRange), type(uint256).max); token1.approve(address(fullRange), type(uint256).max); token2.approve(address(fullRange), type(uint256).max); diff --git a/test/GeomeanOracle.t.sol b/test/GeomeanOracle.t.sol index bd0e0c05..96bc7100 100644 --- a/test/GeomeanOracle.t.sol +++ b/test/GeomeanOracle.t.sol @@ -3,22 +3,21 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; import {GetSender} from "./shared/GetSender.sol"; -import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; import {GeomeanOracle} from "../contracts/hooks/examples/GeomeanOracle.sol"; import {GeomeanOracleImplementation} from "./shared/implementation/GeomeanOracleImplementation.sol"; -import {PoolManager} from "@uniswap/v4-core/contracts/PoolManager.sol"; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; -import {Deployers} from "@uniswap/v4-core/test/foundry-tests/utils/Deployers.sol"; -import {TokenFixture} from "@uniswap/v4-core/test/foundry-tests/utils/TokenFixture.sol"; -import {TestERC20} from "@uniswap/v4-core/contracts/test/TestERC20.sol"; -import {CurrencyLibrary, Currency} from "@uniswap/v4-core/contracts/types/Currency.sol"; -import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/contracts/types/PoolId.sol"; -import {PoolModifyPositionTest} from "@uniswap/v4-core/contracts/test/PoolModifyPositionTest.sol"; -import {TickMath} from "@uniswap/v4-core/contracts/libraries/TickMath.sol"; +import {PoolManager} from "@uniswap/v4-core/src/PoolManager.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {Deployers} from "@uniswap/v4-core/test/utils/Deployers.sol"; +import {TestERC20} from "@uniswap/v4-core/src/test/TestERC20.sol"; +import {CurrencyLibrary, Currency} from "@uniswap/v4-core/src/types/Currency.sol"; +import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol"; +import {PoolModifyPositionTest} from "@uniswap/v4-core/src/test/PoolModifyPositionTest.sol"; +import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol"; import {Oracle} from "../contracts/libraries/Oracle.sol"; -import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; -contract TestGeomeanOracle is Test, Deployers, TokenFixture { +contract TestGeomeanOracle is Test, Deployers { using PoolIdLibrary for PoolKey; int24 constant MAX_TICK_SPACING = 32767; @@ -26,7 +25,6 @@ contract TestGeomeanOracle is Test, Deployers, TokenFixture { TestERC20 token0; TestERC20 token1; - PoolManager manager; GeomeanOracleImplementation geomeanOracle = GeomeanOracleImplementation( address( uint160( @@ -35,18 +33,12 @@ contract TestGeomeanOracle is Test, Deployers, TokenFixture { ) ) ); - PoolKey key; PoolId id; - PoolModifyPositionTest modifyPositionRouter; - function setUp() public { - initializeTokens(); token0 = TestERC20(Currency.unwrap(currency0)); token1 = TestERC20(Currency.unwrap(currency1)); - manager = new PoolManager(500000); - vm.record(); GeomeanOracleImplementation impl = new GeomeanOracleImplementation(manager, geomeanOracle); (, bytes32[] memory writes) = vm.accesses(address(impl)); diff --git a/test/LimitOrder.t.sol b/test/LimitOrder.t.sol index 27613654..02eef332 100644 --- a/test/LimitOrder.t.sol +++ b/test/LimitOrder.t.sol @@ -3,41 +3,33 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; import {GetSender} from "./shared/GetSender.sol"; -import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; import {LimitOrder, Epoch, EpochLibrary} from "../contracts/hooks/examples/LimitOrder.sol"; import {LimitOrderImplementation} from "./shared/implementation/LimitOrderImplementation.sol"; -import {PoolManager} from "@uniswap/v4-core/contracts/PoolManager.sol"; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; -import {Deployers} from "@uniswap/v4-core/test/foundry-tests/utils/Deployers.sol"; -import {TokenFixture} from "@uniswap/v4-core/test/foundry-tests/utils/TokenFixture.sol"; -import {TestERC20} from "@uniswap/v4-core/contracts/test/TestERC20.sol"; -import {CurrencyLibrary, Currency} from "@uniswap/v4-core/contracts/types/Currency.sol"; -import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/contracts/types/PoolId.sol"; -import {PoolSwapTest} from "@uniswap/v4-core/contracts/test/PoolSwapTest.sol"; -import {TickMath} from "@uniswap/v4-core/contracts/libraries/TickMath.sol"; -import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol"; - -contract TestLimitOrder is Test, Deployers, TokenFixture { +import {PoolManager} from "@uniswap/v4-core/src/PoolManager.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {Deployers} from "@uniswap/v4-core/test/utils/Deployers.sol"; +import {TestERC20} from "@uniswap/v4-core/src/test/TestERC20.sol"; +import {CurrencyLibrary, Currency} from "@uniswap/v4-core/src/types/Currency.sol"; +import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol"; +import {PoolSwapTest} from "@uniswap/v4-core/src/test/PoolSwapTest.sol"; +import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; + +contract TestLimitOrder is Test, Deployers { using PoolIdLibrary for PoolKey; uint160 constant SQRT_RATIO_10_1 = 250541448375047931186413801569; TestERC20 token0; TestERC20 token1; - PoolManager manager; LimitOrder limitOrder = LimitOrder(address(uint160(Hooks.AFTER_INITIALIZE_FLAG | Hooks.AFTER_SWAP_FLAG))); - PoolKey key; PoolId id; - PoolSwapTest swapRouter; - function setUp() public { - initializeTokens(); token0 = TestERC20(Currency.unwrap(currency0)); token1 = TestERC20(Currency.unwrap(currency1)); - manager = new PoolManager(500000); - vm.record(); LimitOrderImplementation impl = new LimitOrderImplementation(manager, limitOrder); (, bytes32[] memory writes) = vm.accesses(address(impl)); @@ -54,8 +46,6 @@ contract TestLimitOrder is Test, Deployers, TokenFixture { id = key.toId(); manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); - swapRouter = new PoolSwapTest(manager); - token0.approve(address(limitOrder), type(uint256).max); token1.approve(address(limitOrder), type(uint256).max); token0.approve(address(swapRouter), type(uint256).max); diff --git a/test/TWAMM.t.sol b/test/TWAMM.t.sol index 84ed9716..f313f9d7 100644 --- a/test/TWAMM.t.sol +++ b/test/TWAMM.t.sol @@ -3,26 +3,25 @@ pragma solidity ^0.8.15; import {Test} from "forge-std/Test.sol"; import {Vm} from "forge-std/Vm.sol"; import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol"; -import {MockERC20} from "@uniswap/v4-core/test/foundry-tests/utils/MockERC20.sol"; -import {IERC20Minimal} from "@uniswap/v4-core/contracts/interfaces/external/IERC20Minimal.sol"; +import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol"; +import {IERC20Minimal} from "@uniswap/v4-core/src/interfaces/external/IERC20Minimal.sol"; import {TWAMMImplementation} from "./shared/implementation/TWAMMImplementation.sol"; -import {IHooks} from "@uniswap/v4-core/contracts/interfaces/IHooks.sol"; -import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; -import {TickMath} from "@uniswap/v4-core/contracts/libraries/TickMath.sol"; -import {PoolManager} from "@uniswap/v4-core/contracts/PoolManager.sol"; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; -import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/contracts/types/PoolId.sol"; -import {PoolModifyPositionTest} from "@uniswap/v4-core/contracts/test/PoolModifyPositionTest.sol"; -import {PoolSwapTest} from "@uniswap/v4-core/contracts/test/PoolSwapTest.sol"; -import {PoolDonateTest} from "@uniswap/v4-core/contracts/test/PoolDonateTest.sol"; -import {Deployers} from "@uniswap/v4-core/test/foundry-tests/utils/Deployers.sol"; -import {TokenFixture} from "@uniswap/v4-core/test/foundry-tests/utils/TokenFixture.sol"; -import {CurrencyLibrary, Currency} from "@uniswap/v4-core/contracts/types/Currency.sol"; +import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; +import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol"; +import {PoolManager} from "@uniswap/v4-core/src/PoolManager.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol"; +import {PoolModifyPositionTest} from "@uniswap/v4-core/src/test/PoolModifyPositionTest.sol"; +import {PoolSwapTest} from "@uniswap/v4-core/src/test/PoolSwapTest.sol"; +import {PoolDonateTest} from "@uniswap/v4-core/src/test/PoolDonateTest.sol"; +import {Deployers} from "@uniswap/v4-core/test/utils/Deployers.sol"; +import {CurrencyLibrary, Currency} from "@uniswap/v4-core/src/types/Currency.sol"; import {TWAMM} from "../contracts/hooks/examples/TWAMM.sol"; import {ITWAMM} from "../contracts/interfaces/ITWAMM.sol"; -import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; -contract TWAMMTest is Test, Deployers, TokenFixture, GasSnapshot { +contract TWAMMTest is Test, Deployers, GasSnapshot { using PoolIdLibrary for PoolKey; using CurrencyLibrary for Currency; @@ -49,10 +48,6 @@ contract TWAMMTest is Test, Deployers, TokenFixture, GasSnapshot { address(uint160(Hooks.BEFORE_INITIALIZE_FLAG | Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_MODIFY_POSITION_FLAG)) ); // TWAMM twamm; - PoolManager manager; - PoolModifyPositionTest modifyPositionRouter; - PoolSwapTest swapRouter; - PoolDonateTest donateRouter; address hookAddress; MockERC20 token0; MockERC20 token1; @@ -60,10 +55,8 @@ contract TWAMMTest is Test, Deployers, TokenFixture, GasSnapshot { PoolId poolId; function setUp() public { - initializeTokens(); token0 = MockERC20(Currency.unwrap(currency0)); token1 = MockERC20(Currency.unwrap(currency1)); - manager = new PoolManager(500000); TWAMMImplementation impl = new TWAMMImplementation(manager, 10_000, twamm); (, bytes32[] memory writes) = vm.accesses(address(impl)); @@ -76,9 +69,6 @@ contract TWAMMTest is Test, Deployers, TokenFixture, GasSnapshot { } } - modifyPositionRouter = new PoolModifyPositionTest(IPoolManager(address(manager))); - swapRouter = new PoolSwapTest(IPoolManager(address(manager))); - poolKey = PoolKey(Currency.wrap(address(token0)), Currency.wrap(address(token1)), 3000, 60, twamm); poolId = poolKey.toId(); manager.initialize(poolKey, SQRT_RATIO_1_1, ZERO_BYTES); diff --git a/test/shared/implementation/FullRangeImplementation.sol b/test/shared/implementation/FullRangeImplementation.sol index fcd8ae3f..8ee0589f 100644 --- a/test/shared/implementation/FullRangeImplementation.sol +++ b/test/shared/implementation/FullRangeImplementation.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.19; import {BaseHook} from "../../../contracts/BaseHook.sol"; import {FullRange} from "../../../contracts/hooks/examples/FullRange.sol"; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; -import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; contract FullRangeImplementation is FullRange { constructor(IPoolManager _poolManager, FullRange addressToEtch) FullRange(_poolManager) { diff --git a/test/shared/implementation/GeomeanOracleImplementation.sol b/test/shared/implementation/GeomeanOracleImplementation.sol index 06a95fa2..68b669f1 100644 --- a/test/shared/implementation/GeomeanOracleImplementation.sol +++ b/test/shared/implementation/GeomeanOracleImplementation.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.19; import {BaseHook} from "../../../contracts/BaseHook.sol"; import {GeomeanOracle} from "../../../contracts/hooks/examples/GeomeanOracle.sol"; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; -import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; contract GeomeanOracleImplementation is GeomeanOracle { uint32 public time; diff --git a/test/shared/implementation/LimitOrderImplementation.sol b/test/shared/implementation/LimitOrderImplementation.sol index 340cfc42..b70f2553 100644 --- a/test/shared/implementation/LimitOrderImplementation.sol +++ b/test/shared/implementation/LimitOrderImplementation.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.19; import {BaseHook} from "../../../contracts/BaseHook.sol"; import {LimitOrder} from "../../../contracts/hooks/examples/LimitOrder.sol"; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; -import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; contract LimitOrderImplementation is LimitOrder { constructor(IPoolManager _poolManager, LimitOrder addressToEtch) LimitOrder(_poolManager) { diff --git a/test/shared/implementation/TWAMMImplementation.sol b/test/shared/implementation/TWAMMImplementation.sol index 012ca541..883eeb62 100644 --- a/test/shared/implementation/TWAMMImplementation.sol +++ b/test/shared/implementation/TWAMMImplementation.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.19; import {BaseHook} from "../../../contracts/BaseHook.sol"; import {TWAMM} from "../../../contracts/hooks/examples/TWAMM.sol"; -import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"; -import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; contract TWAMMImplementation is TWAMM { constructor(IPoolManager poolManager, uint256 interval, TWAMM addressToEtch) TWAMM(poolManager, interval) { From 3e3ab5dfbf478b21adb64ab81a332229fb4c753b Mon Sep 17 00:00:00 2001 From: Mark Toda Date: Thu, 16 Nov 2023 16:13:26 -0500 Subject: [PATCH 02/12] fix: tests --- .forge-snapshots/TWAMMSubmitOrder.snap | 2 +- foundry.toml | 1 + test/FullRange.t.sol | 3 +++ test/GeomeanOracle.t.sol | 3 +++ test/LimitOrder.t.sol | 3 +++ test/TWAMM.t.sol | 3 +++ 6 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.forge-snapshots/TWAMMSubmitOrder.snap b/.forge-snapshots/TWAMMSubmitOrder.snap index 9adc49a6..d01ad33f 100644 --- a/.forge-snapshots/TWAMMSubmitOrder.snap +++ b/.forge-snapshots/TWAMMSubmitOrder.snap @@ -1 +1 @@ -123576 \ No newline at end of file +123619 \ No newline at end of file diff --git a/foundry.toml b/foundry.toml index b3132187..7c32d4b3 100644 --- a/foundry.toml +++ b/foundry.toml @@ -5,6 +5,7 @@ solc_version = '0.8.20' optimizer_runs = 800 ffi = true fs_permissions = [{ access = "read-write", path = ".forge-snapshots/"}] +cancun = true [profile.ci] fuzz_runs = 100000 diff --git a/test/FullRange.t.sol b/test/FullRange.t.sol index 0658d683..49a7b98d 100644 --- a/test/FullRange.t.sol +++ b/test/FullRange.t.sol @@ -76,6 +76,9 @@ contract TestFullRange is Test, Deployers, GasSnapshot { PoolId idWithLiq; function setUp() public { + deployFreshManagerAndRouters(); + (currency0, currency1) = deployMintAndApprove2Currencies(); + token0 = new MockERC20("TestA", "A", 18); token1 = new MockERC20("TestB", "B", 18); token2 = new MockERC20("TestC", "C", 18); diff --git a/test/GeomeanOracle.t.sol b/test/GeomeanOracle.t.sol index 96bc7100..ce34adbd 100644 --- a/test/GeomeanOracle.t.sol +++ b/test/GeomeanOracle.t.sol @@ -36,6 +36,9 @@ contract TestGeomeanOracle is Test, Deployers { PoolId id; function setUp() public { + deployFreshManagerAndRouters(); + (currency0, currency1) = deployMintAndApprove2Currencies(); + token0 = TestERC20(Currency.unwrap(currency0)); token1 = TestERC20(Currency.unwrap(currency1)); diff --git a/test/LimitOrder.t.sol b/test/LimitOrder.t.sol index 02eef332..222e94c8 100644 --- a/test/LimitOrder.t.sol +++ b/test/LimitOrder.t.sol @@ -27,6 +27,9 @@ contract TestLimitOrder is Test, Deployers { PoolId id; function setUp() public { + deployFreshManagerAndRouters(); + (currency0, currency1) = deployMintAndApprove2Currencies(); + token0 = TestERC20(Currency.unwrap(currency0)); token1 = TestERC20(Currency.unwrap(currency1)); diff --git a/test/TWAMM.t.sol b/test/TWAMM.t.sol index f313f9d7..575d3e6f 100644 --- a/test/TWAMM.t.sol +++ b/test/TWAMM.t.sol @@ -55,6 +55,9 @@ contract TWAMMTest is Test, Deployers, GasSnapshot { PoolId poolId; function setUp() public { + deployFreshManagerAndRouters(); + (currency0, currency1) = deployMintAndApprove2Currencies(); + token0 = MockERC20(Currency.unwrap(currency0)); token1 = MockERC20(Currency.unwrap(currency1)); From 4fe142ca1c1ea6405b21d970b51eda7d9ada8cbd Mon Sep 17 00:00:00 2001 From: Mark Toda Date: Fri, 17 Nov 2023 16:51:56 -0500 Subject: [PATCH 03/12] fix: update tests --- .../FullRangeAddInitialLiquidity.snap | 2 +- .forge-snapshots/FullRangeAddLiquidity.snap | 2 +- .forge-snapshots/FullRangeFirstSwap.snap | 2 +- .forge-snapshots/FullRangeInitialize.snap | 2 +- .../FullRangeRemoveLiquidity.snap | 2 +- .../FullRangeRemoveLiquidityAndRebalance.snap | 2 +- .forge-snapshots/FullRangeSecondSwap.snap | 2 +- .forge-snapshots/FullRangeSwap.snap | 2 +- test/FullRange.t.sol | 65 +++++++++++-------- test/LimitOrder.t.sol | 29 +++++---- test/TWAMM.t.sol | 9 +-- test/utils/HookEnabledSwapRouter.sol | 65 +++++++++++++++++++ 12 files changed, 131 insertions(+), 53 deletions(-) create mode 100644 test/utils/HookEnabledSwapRouter.sol diff --git a/.forge-snapshots/FullRangeAddInitialLiquidity.snap b/.forge-snapshots/FullRangeAddInitialLiquidity.snap index 2d5250a5..7e3a2f44 100644 --- a/.forge-snapshots/FullRangeAddInitialLiquidity.snap +++ b/.forge-snapshots/FullRangeAddInitialLiquidity.snap @@ -1 +1 @@ -412696 \ No newline at end of file +390028 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeAddLiquidity.snap b/.forge-snapshots/FullRangeAddLiquidity.snap index 032a6a3b..fcc9c101 100644 --- a/.forge-snapshots/FullRangeAddLiquidity.snap +++ b/.forge-snapshots/FullRangeAddLiquidity.snap @@ -1 +1 @@ -206962 \ No newline at end of file +184294 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeFirstSwap.snap b/.forge-snapshots/FullRangeFirstSwap.snap index 9d59ac16..df930ad0 100644 --- a/.forge-snapshots/FullRangeFirstSwap.snap +++ b/.forge-snapshots/FullRangeFirstSwap.snap @@ -1 +1 @@ -154763 \ No newline at end of file +133445 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeInitialize.snap b/.forge-snapshots/FullRangeInitialize.snap index e0b3ab13..b07717ab 100644 --- a/.forge-snapshots/FullRangeInitialize.snap +++ b/.forge-snapshots/FullRangeInitialize.snap @@ -1 +1 @@ -879542 \ No newline at end of file +896690 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeRemoveLiquidity.snap b/.forge-snapshots/FullRangeRemoveLiquidity.snap index 920384a4..594d74bc 100644 --- a/.forge-snapshots/FullRangeRemoveLiquidity.snap +++ b/.forge-snapshots/FullRangeRemoveLiquidity.snap @@ -1 +1 @@ -200095 \ No newline at end of file +177393 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeRemoveLiquidityAndRebalance.snap b/.forge-snapshots/FullRangeRemoveLiquidityAndRebalance.snap index 5ee38978..e2e0f2f7 100644 --- a/.forge-snapshots/FullRangeRemoveLiquidityAndRebalance.snap +++ b/.forge-snapshots/FullRangeRemoveLiquidityAndRebalance.snap @@ -1 +1 @@ -379287 \ No newline at end of file +362063 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeSecondSwap.snap b/.forge-snapshots/FullRangeSecondSwap.snap index 436848b5..10867d68 100644 --- a/.forge-snapshots/FullRangeSecondSwap.snap +++ b/.forge-snapshots/FullRangeSecondSwap.snap @@ -1 +1 @@ -112303 \ No newline at end of file +93791 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeSwap.snap b/.forge-snapshots/FullRangeSwap.snap index d48620c7..791a7d96 100644 --- a/.forge-snapshots/FullRangeSwap.snap +++ b/.forge-snapshots/FullRangeSwap.snap @@ -1 +1 @@ -153038 \ No newline at end of file +131720 \ No newline at end of file diff --git a/test/FullRange.t.sol b/test/FullRange.t.sol index 49a7b98d..04d5ce27 100644 --- a/test/FullRange.t.sol +++ b/test/FullRange.t.sol @@ -19,6 +19,7 @@ import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol"; import {UniswapV4ERC20} from "../contracts/libraries/UniswapV4ERC20.sol"; import {FullMath} from "@uniswap/v4-core/src/libraries/FullMath.sol"; import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol"; +import {HookEnabledSwapRouter} from "./utils/HookEnabledSwapRouter.sol"; contract TestFullRange is Test, Deployers, GasSnapshot { using PoolIdLibrary for PoolKey; @@ -47,6 +48,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { uint24 fee ); + HookEnabledSwapRouter router; /// @dev Min tick for full range with tick spacing of 60 int24 internal constant MIN_TICK = -887220; /// @dev Max tick for full range with tick spacing of 60 @@ -77,15 +79,20 @@ contract TestFullRange is Test, Deployers, GasSnapshot { function setUp() public { deployFreshManagerAndRouters(); + router = new HookEnabledSwapRouter(manager); (currency0, currency1) = deployMintAndApprove2Currencies(); token0 = new MockERC20("TestA", "A", 18); + token0.mint(address(this), 2 ** 128); token1 = new MockERC20("TestB", "B", 18); + token1.mint(address(this), 2 ** 128); token2 = new MockERC20("TestC", "C", 18); + token2.mint(address(this), 2 ** 128); FullRangeImplementation impl = new FullRangeImplementation(manager, fullRange); vm.etch(address(fullRange), address(impl).code); + key = createPoolKey(token0, token1); id = key.toId(); key2 = createPoolKey(token1, token2); @@ -97,11 +104,13 @@ contract TestFullRange is Test, Deployers, GasSnapshot { token0.approve(address(fullRange), type(uint256).max); token1.approve(address(fullRange), type(uint256).max); token2.approve(address(fullRange), type(uint256).max); - token0.approve(address(swapRouter), type(uint256).max); - token1.approve(address(swapRouter), type(uint256).max); - token2.approve(address(swapRouter), type(uint256).max); + token0.approve(address(router), type(uint256).max); + token1.approve(address(router), type(uint256).max); + token2.approve(address(router), type(uint256).max); - manager.initialize(keyWithLiq, SQRT_RATIO_1_1, ZERO_BYTES); + initPool( + keyWithLiq.currency0, keyWithLiq.currency1, fullRange, 3000, SQRT_RATIO_1_1, ZERO_BYTES + ); fullRange.addLiquidity( FullRange.AddLiquidityParams( keyWithLiq.currency0, @@ -262,16 +271,16 @@ contract TestFullRange is Test, Deployers, GasSnapshot { vm.expectEmit(true, true, true, true); emit Swap( - id, address(swapRouter), 1 ether, -906610893880149131, 72045250990510446115798809072, 10 ether, -1901, 3000 + id, address(router), 1 ether, -906610893880149131, 72045250990510446115798809072, 10 ether, -1901, 3000 ); IPoolManager.SwapParams memory params = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 1 ether, sqrtPriceLimitX96: SQRT_RATIO_1_2}); - PoolSwapTest.TestSettings memory settings = - PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); + HookEnabledSwapRouter.TestSettings memory settings = + HookEnabledSwapRouter.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); snapStart("FullRangeSwap"); - swapRouter.swap(key, params, settings, ZERO_BYTES); + router.swap(key, params, settings, ZERO_BYTES); snapEnd(); (bool hasAccruedFees,) = fullRange.poolInfo(id); @@ -305,10 +314,10 @@ contract TestFullRange is Test, Deployers, GasSnapshot { IPoolManager.SwapParams memory params = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 1000 ether, sqrtPriceLimitX96: SQRT_RATIO_1_2}); - PoolSwapTest.TestSettings memory settings = - PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); + HookEnabledSwapRouter.TestSettings memory settings = + HookEnabledSwapRouter.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); - swapRouter.swap(key, params, settings, ZERO_BYTES); + router.swap(key, params, settings, ZERO_BYTES); vm.expectRevert(FullRange.TooMuchSlippage.selector); fullRange.addLiquidity( @@ -330,18 +339,18 @@ contract TestFullRange is Test, Deployers, GasSnapshot { IPoolManager.SwapParams memory params = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 1 ether, sqrtPriceLimitX96: SQRT_RATIO_1_2}); - PoolSwapTest.TestSettings memory settings = - PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); + HookEnabledSwapRouter.TestSettings memory settings = + HookEnabledSwapRouter.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); snapStart("FullRangeFirstSwap"); - swapRouter.swap(testKey, params, settings, ZERO_BYTES); + router.swap(testKey, params, settings, ZERO_BYTES); snapEnd(); (bool hasAccruedFees,) = fullRange.poolInfo(id); assertEq(hasAccruedFees, true); snapStart("FullRangeSecondSwap"); - swapRouter.swap(testKey, params, settings, ZERO_BYTES); + router.swap(testKey, params, settings, ZERO_BYTES); snapEnd(); (hasAccruedFees,) = fullRange.poolInfo(id); @@ -366,11 +375,11 @@ contract TestFullRange is Test, Deployers, GasSnapshot { IPoolManager.SwapParams memory params = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 10000000, sqrtPriceLimitX96: SQRT_RATIO_1_2}); - PoolSwapTest.TestSettings memory testSettings = - PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); + HookEnabledSwapRouter.TestSettings memory testSettings = + HookEnabledSwapRouter.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); - swapRouter.swap(key, params, testSettings, ZERO_BYTES); - swapRouter.swap(key2, params, testSettings, ZERO_BYTES); + router.swap(key, params, testSettings, ZERO_BYTES); + router.swap(key2, params, testSettings, ZERO_BYTES); (bool hasAccruedFees,) = fullRange.poolInfo(id); assertEq(hasAccruedFees, true); @@ -549,10 +558,10 @@ contract TestFullRange is Test, Deployers, GasSnapshot { IPoolManager.SwapParams memory params = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 1 ether, sqrtPriceLimitX96: SQRT_RATIO_1_2}); - PoolSwapTest.TestSettings memory testSettings = - PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); + HookEnabledSwapRouter.TestSettings memory testSettings = + HookEnabledSwapRouter.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); - swapRouter.swap(keyWithLiq, params, testSettings, ZERO_BYTES); + router.swap(keyWithLiq, params, testSettings, ZERO_BYTES); UniswapV4ERC20(liquidityToken).approve(address(fullRange), type(uint256).max); @@ -676,10 +685,10 @@ contract TestFullRange is Test, Deployers, GasSnapshot { IPoolManager.SwapParams memory params = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100 ether, sqrtPriceLimitX96: SQRT_RATIO_1_4}); - PoolSwapTest.TestSettings memory testSettings = - PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); + HookEnabledSwapRouter.TestSettings memory testSettings = + HookEnabledSwapRouter.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); - swapRouter.swap(key, params, testSettings, ZERO_BYTES); + router.swap(key, params, testSettings, ZERO_BYTES); (bool hasAccruedFees,) = fullRange.poolInfo(id); assertEq(hasAccruedFees, true); @@ -731,10 +740,10 @@ contract TestFullRange is Test, Deployers, GasSnapshot { sqrtPriceLimitX96: SQRT_RATIO_1_4 }); - PoolSwapTest.TestSettings memory testSettings = - PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); + HookEnabledSwapRouter.TestSettings memory testSettings = + HookEnabledSwapRouter.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); - swapRouter.swap(key, params, testSettings, ZERO_BYTES); + router.swap(key, params, testSettings, ZERO_BYTES); // Test contract removes liquidity, succeeds UniswapV4ERC20(liquidityToken).approve(address(fullRange), type(uint256).max); diff --git a/test/LimitOrder.t.sol b/test/LimitOrder.t.sol index 222e94c8..007d84b7 100644 --- a/test/LimitOrder.t.sol +++ b/test/LimitOrder.t.sol @@ -12,15 +12,16 @@ import {Deployers} from "@uniswap/v4-core/test/utils/Deployers.sol"; import {TestERC20} from "@uniswap/v4-core/src/test/TestERC20.sol"; import {CurrencyLibrary, Currency} from "@uniswap/v4-core/src/types/Currency.sol"; import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol"; -import {PoolSwapTest} from "@uniswap/v4-core/src/test/PoolSwapTest.sol"; import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; +import {HookEnabledSwapRouter} from "./utils/HookEnabledSwapRouter.sol"; contract TestLimitOrder is Test, Deployers { using PoolIdLibrary for PoolKey; uint160 constant SQRT_RATIO_10_1 = 250541448375047931186413801569; + HookEnabledSwapRouter router; TestERC20 token0; TestERC20 token1; LimitOrder limitOrder = LimitOrder(address(uint160(Hooks.AFTER_INITIALIZE_FLAG | Hooks.AFTER_SWAP_FLAG))); @@ -30,6 +31,7 @@ contract TestLimitOrder is Test, Deployers { deployFreshManagerAndRouters(); (currency0, currency1) = deployMintAndApprove2Currencies(); + router = new HookEnabledSwapRouter(manager); token0 = TestERC20(Currency.unwrap(currency0)); token1 = TestERC20(Currency.unwrap(currency1)); @@ -45,14 +47,15 @@ contract TestLimitOrder is Test, Deployers { } } - key = PoolKey(currency0, currency1, 3000, 60, limitOrder); - id = key.toId(); - manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); + // key = PoolKey(currency0, currency1, 3000, 60, limitOrder); + (key, id) = initPoolAndAddLiquidity( + currency0, currency1, limitOrder, 3000, SQRT_RATIO_1_1, ZERO_BYTES + ); token0.approve(address(limitOrder), type(uint256).max); token1.approve(address(limitOrder), type(uint256).max); - token0.approve(address(swapRouter), type(uint256).max); - token1.approve(address(swapRouter), type(uint256).max); + token0.approve(address(router), type(uint256).max); + token1.approve(address(router), type(uint256).max); } function testGetTickLowerLast() public { @@ -100,10 +103,10 @@ contract TestLimitOrder is Test, Deployers { function testZeroForOneInRangeRevert() public { // swapping is free, there's no liquidity in the pool, so we only need to specify 1 wei - swapRouter.swap( + router.swap( key, - IPoolManager.SwapParams(false, 1, SQRT_RATIO_1_1 + 1), - PoolSwapTest.TestSettings(true, true), + IPoolManager.SwapParams(false, 1 ether, SQRT_RATIO_1_1 + 1), + HookEnabledSwapRouter.TestSettings(true, true), ZERO_BYTES ); vm.expectRevert(LimitOrder.InRange.selector); @@ -126,8 +129,8 @@ contract TestLimitOrder is Test, Deployers { function testNotZeroForOneInRangeRevert() public { // swapping is free, there's no liquidity in the pool, so we only need to specify 1 wei - swapRouter.swap( - key, IPoolManager.SwapParams(true, 1, SQRT_RATIO_1_1 - 1), PoolSwapTest.TestSettings(true, true), ZERO_BYTES + router.swap( + key, IPoolManager.SwapParams(true, 1, SQRT_RATIO_1_1 - 1), HookEnabledSwapRouter.TestSettings(true, true), ZERO_BYTES ); vm.expectRevert(LimitOrder.InRange.selector); limitOrder.place(key, -60, false, 1000000); @@ -185,10 +188,10 @@ contract TestLimitOrder is Test, Deployers { uint128 liquidity = 1000000; limitOrder.place(key, tickLower, zeroForOne, liquidity); - swapRouter.swap( + router.swap( key, IPoolManager.SwapParams(false, 1e18, TickMath.getSqrtRatioAtTick(60)), - PoolSwapTest.TestSettings(true, true), + HookEnabledSwapRouter.TestSettings(true, true), ZERO_BYTES ); diff --git a/test/TWAMM.t.sol b/test/TWAMM.t.sol index 575d3e6f..1575d95d 100644 --- a/test/TWAMM.t.sol +++ b/test/TWAMM.t.sol @@ -93,6 +93,7 @@ contract TWAMMTest is Test, Deployers, GasSnapshot { (PoolKey memory initKey, PoolId initId) = newPoolKeyWithTWAMM(twamm); assertEq(twamm.lastVirtualOrderTimestamp(initId), 0); vm.warp(10000); + manager.initialize(initKey, SQRT_RATIO_1_1, ZERO_BYTES); assertEq(twamm.lastVirtualOrderTimestamp(initId), 10000); } @@ -185,8 +186,8 @@ contract TWAMMTest is Test, Deployers, GasSnapshot { assertEq(sellRate0For1, 2e18 / (expiration2 - submitTimestamp2)); assertEq(sellRate1For0, 3e18 / (expiration2 - submitTimestamp1)); - assertEq(earningsFactor0For1, 1712020976636017581269515821040000); - assertEq(earningsFactor1For0, 1470157410324350030712806974476955); + assertEq(earningsFactor0For1, 1636776489931663248324424309240000); + assertEq(earningsFactor1For0, 1534530274609724617872321172427618); } function testTWAMM_submitOrder_EmitsEvent() public { @@ -409,8 +410,8 @@ contract TWAMMTest is Test, Deployers, GasSnapshot { } function newPoolKeyWithTWAMM(IHooks hooks) public returns (PoolKey memory, PoolId) { - MockERC20[] memory tokens = deployTokens(2, 2 ** 255); - PoolKey memory key = PoolKey(Currency.wrap(address(tokens[0])), Currency.wrap(address(tokens[1])), 0, 60, hooks); + (Currency _token0, Currency _token1) = deployMintAndApprove2Currencies(); + PoolKey memory key = PoolKey(_token0, _token1, 0, 60, hooks); return (key, key.toId()); } diff --git a/test/utils/HookEnabledSwapRouter.sol b/test/utils/HookEnabledSwapRouter.sol new file mode 100644 index 00000000..8c5bec5b --- /dev/null +++ b/test/utils/HookEnabledSwapRouter.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import {CurrencyLibrary, Currency} from "@uniswap/v4-core/src/types/Currency.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; +import {PoolTestBase} from "@uniswap/v4-core/src/test/PoolTestBase.sol"; +import {Test} from "forge-std/Test.sol"; + +contract HookEnabledSwapRouter is Test, PoolTestBase { + using CurrencyLibrary for Currency; + + constructor(IPoolManager _manager) PoolTestBase(_manager) {} + + error NoSwapOccurred(); + + struct CallbackData { + address sender; + TestSettings testSettings; + PoolKey key; + IPoolManager.SwapParams params; + bytes hookData; + } + + struct TestSettings { + bool withdrawTokens; + bool settleUsingTransfer; + } + + function swap( + PoolKey memory key, + IPoolManager.SwapParams memory params, + TestSettings memory testSettings, + bytes memory hookData + ) external payable returns (BalanceDelta delta) { + delta = abi.decode( + manager.lock(abi.encode(CallbackData(msg.sender, testSettings, key, params, hookData))), (BalanceDelta) + ); + + uint256 ethBalance = address(this).balance; + if (ethBalance > 0) CurrencyLibrary.NATIVE.transfer(msg.sender, ethBalance); + } + + function lockAcquired(bytes calldata rawData) external returns (bytes memory) { + require(msg.sender == address(manager)); + + CallbackData memory data = abi.decode(rawData, (CallbackData)); + + BalanceDelta delta = manager.swap(data.key, data.params, data.hookData); + + // Make sure youve added liquidity to the test pool! + if (BalanceDelta.unwrap(delta) == 0) revert NoSwapOccurred(); + + if (data.params.zeroForOne) { + _settle(data.key.currency0, data.sender, delta.amount0(), data.testSettings.settleUsingTransfer); + _take(data.key.currency1, data.sender, delta.amount1(), data.testSettings.withdrawTokens); + } else { + _settle(data.key.currency1, data.sender, delta.amount1(), data.testSettings.settleUsingTransfer); + _take(data.key.currency0, data.sender, delta.amount0(), data.testSettings.withdrawTokens); + } + + return abi.encode(delta); + } +} From 15a9c8a680ad728aa3d9c61d68b4660abb5d2d83 Mon Sep 17 00:00:00 2001 From: Mark Toda Date: Fri, 17 Nov 2023 17:06:03 -0500 Subject: [PATCH 04/12] fix: test router was borked --- .forge-snapshots/FullRangeFirstSwap.snap | 2 +- .forge-snapshots/FullRangeSecondSwap.snap | 2 +- .forge-snapshots/FullRangeSwap.snap | 2 +- foundry.toml | 1 + test/FullRange.t.sol | 4 +--- test/LimitOrder.t.sol | 9 +++++---- test/TWAMM.t.sol | 10 +++++++--- test/utils/HookEnabledSwapRouter.sol | 15 ++++++++++----- 8 files changed, 27 insertions(+), 18 deletions(-) diff --git a/.forge-snapshots/FullRangeFirstSwap.snap b/.forge-snapshots/FullRangeFirstSwap.snap index df930ad0..08d86dfe 100644 --- a/.forge-snapshots/FullRangeFirstSwap.snap +++ b/.forge-snapshots/FullRangeFirstSwap.snap @@ -1 +1 @@ -133445 \ No newline at end of file +133339 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeSecondSwap.snap b/.forge-snapshots/FullRangeSecondSwap.snap index 10867d68..e21f3119 100644 --- a/.forge-snapshots/FullRangeSecondSwap.snap +++ b/.forge-snapshots/FullRangeSecondSwap.snap @@ -1 +1 @@ -93791 \ No newline at end of file +93685 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeSwap.snap b/.forge-snapshots/FullRangeSwap.snap index 791a7d96..77bbcb9a 100644 --- a/.forge-snapshots/FullRangeSwap.snap +++ b/.forge-snapshots/FullRangeSwap.snap @@ -1 +1 @@ -131720 \ No newline at end of file +131614 \ No newline at end of file diff --git a/foundry.toml b/foundry.toml index 7c32d4b3..302fc02b 100644 --- a/foundry.toml +++ b/foundry.toml @@ -9,5 +9,6 @@ cancun = true [profile.ci] fuzz_runs = 100000 +solc = "./lib/v4-core/bin/solc-static-linux" # See more config options https://github.com/foundry-rs/foundry/tree/master/config diff --git a/test/FullRange.t.sol b/test/FullRange.t.sol index 04d5ce27..4c131856 100644 --- a/test/FullRange.t.sol +++ b/test/FullRange.t.sol @@ -108,9 +108,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { token1.approve(address(router), type(uint256).max); token2.approve(address(router), type(uint256).max); - initPool( - keyWithLiq.currency0, keyWithLiq.currency1, fullRange, 3000, SQRT_RATIO_1_1, ZERO_BYTES - ); + initPool(keyWithLiq.currency0, keyWithLiq.currency1, fullRange, 3000, SQRT_RATIO_1_1, ZERO_BYTES); fullRange.addLiquidity( FullRange.AddLiquidityParams( keyWithLiq.currency0, diff --git a/test/LimitOrder.t.sol b/test/LimitOrder.t.sol index 007d84b7..415e30be 100644 --- a/test/LimitOrder.t.sol +++ b/test/LimitOrder.t.sol @@ -48,9 +48,7 @@ contract TestLimitOrder is Test, Deployers { } // key = PoolKey(currency0, currency1, 3000, 60, limitOrder); - (key, id) = initPoolAndAddLiquidity( - currency0, currency1, limitOrder, 3000, SQRT_RATIO_1_1, ZERO_BYTES - ); + (key, id) = initPoolAndAddLiquidity(currency0, currency1, limitOrder, 3000, SQRT_RATIO_1_1, ZERO_BYTES); token0.approve(address(limitOrder), type(uint256).max); token1.approve(address(limitOrder), type(uint256).max); @@ -130,7 +128,10 @@ contract TestLimitOrder is Test, Deployers { function testNotZeroForOneInRangeRevert() public { // swapping is free, there's no liquidity in the pool, so we only need to specify 1 wei router.swap( - key, IPoolManager.SwapParams(true, 1, SQRT_RATIO_1_1 - 1), HookEnabledSwapRouter.TestSettings(true, true), ZERO_BYTES + key, + IPoolManager.SwapParams(true, 1 ether, SQRT_RATIO_1_1 - 1), + HookEnabledSwapRouter.TestSettings(true, true), + ZERO_BYTES ); vm.expectRevert(LimitOrder.InRange.selector); limitOrder.place(key, -60, false, 1000000); diff --git a/test/TWAMM.t.sol b/test/TWAMM.t.sol index 1575d95d..266424db 100644 --- a/test/TWAMM.t.sol +++ b/test/TWAMM.t.sol @@ -61,7 +61,11 @@ contract TWAMMTest is Test, Deployers, GasSnapshot { token0 = MockERC20(Currency.unwrap(currency0)); token1 = MockERC20(Currency.unwrap(currency1)); - TWAMMImplementation impl = new TWAMMImplementation(manager, 10_000, twamm); + TWAMMImplementation impl = new TWAMMImplementation( + manager, + 10_000, + twamm + ); (, bytes32[] memory writes) = vm.accesses(address(impl)); vm.etch(address(twamm), address(impl).code); // for each storage key that was written during the hook implementation, copy the value over @@ -236,7 +240,7 @@ contract TWAMMTest is Test, Deployers, GasSnapshot { uint256 token1Owed = twamm.tokensOwed(poolKey.currency1, orderKey1.owner); // takes 10% off the remaining half (so 80% of original sellrate) - assertEq(updatedSellRate, originalSellRate * 80 / 100); + assertEq(updatedSellRate, (originalSellRate * 80) / 100); assertEq(token0Owed, uint256(-amountDelta)); assertEq(token1Owed, orderAmount / 2); } @@ -261,7 +265,7 @@ contract TWAMMTest is Test, Deployers, GasSnapshot { uint256 token1Owed = twamm.tokensOwed(poolKey.currency1, orderKey1.owner); // takes 10% off the remaining half (so 80% of original sellrate) - assertEq(updatedSellRate, originalSellRate * 80 / 100); + assertEq(updatedSellRate, (originalSellRate * 80) / 100); assertEq(token0Owed, orderAmount / 2); assertEq(token1Owed, uint256(-amountDelta)); } diff --git a/test/utils/HookEnabledSwapRouter.sol b/test/utils/HookEnabledSwapRouter.sol index 8c5bec5b..b924ed61 100644 --- a/test/utils/HookEnabledSwapRouter.sol +++ b/test/utils/HookEnabledSwapRouter.sol @@ -2,19 +2,20 @@ pragma solidity ^0.8.20; import {CurrencyLibrary, Currency} from "@uniswap/v4-core/src/types/Currency.sol"; +import {IERC20Minimal} from "@uniswap/v4-core/src/interfaces/external/IERC20Minimal.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {PoolTestBase} from "@uniswap/v4-core/src/test/PoolTestBase.sol"; import {Test} from "forge-std/Test.sol"; -contract HookEnabledSwapRouter is Test, PoolTestBase { +contract HookEnabledSwapRouter is PoolTestBase { using CurrencyLibrary for Currency; - constructor(IPoolManager _manager) PoolTestBase(_manager) {} - error NoSwapOccurred(); + constructor(IPoolManager _manager) PoolTestBase(_manager) {} + struct CallbackData { address sender; TestSettings testSettings; @@ -54,10 +55,14 @@ contract HookEnabledSwapRouter is Test, PoolTestBase { if (data.params.zeroForOne) { _settle(data.key.currency0, data.sender, delta.amount0(), data.testSettings.settleUsingTransfer); - _take(data.key.currency1, data.sender, delta.amount1(), data.testSettings.withdrawTokens); + if (delta.amount1() < 0) { + _take(data.key.currency1, data.sender, delta.amount1(), data.testSettings.withdrawTokens); + } } else { _settle(data.key.currency1, data.sender, delta.amount1(), data.testSettings.settleUsingTransfer); - _take(data.key.currency0, data.sender, delta.amount0(), data.testSettings.withdrawTokens); + if (delta.amount0() < 0) { + _take(data.key.currency0, data.sender, delta.amount0(), data.testSettings.withdrawTokens); + } } return abi.encode(delta); From 0dc0c0b868d5ae8cd86c1f7def7b3d2714a29141 Mon Sep 17 00:00:00 2001 From: Mark Toda Date: Mon, 20 Nov 2023 14:45:50 -0500 Subject: [PATCH 05/12] fix: alice comments --- .env | 2 -- test/FullRange.t.sol | 12 ++++-------- test/TWAMM.t.sol | 4 +--- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/.env b/.env index 721bb082..7859e840 100644 --- a/.env +++ b/.env @@ -5,5 +5,3 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then elif [[ "$OSTYPE" == "darwin"* ]]; then export FOUNDRY_SOLC="./lib/v4-core/bin/solc-mac" fi - -# FOUNDRY_SOLC="./bin/solc-static-linux" diff --git a/test/FullRange.t.sol b/test/FullRange.t.sol index 4c131856..e6c75f97 100644 --- a/test/FullRange.t.sol +++ b/test/FullRange.t.sol @@ -80,14 +80,10 @@ contract TestFullRange is Test, Deployers, GasSnapshot { function setUp() public { deployFreshManagerAndRouters(); router = new HookEnabledSwapRouter(manager); - (currency0, currency1) = deployMintAndApprove2Currencies(); - - token0 = new MockERC20("TestA", "A", 18); - token0.mint(address(this), 2 ** 128); - token1 = new MockERC20("TestB", "B", 18); - token1.mint(address(this), 2 ** 128); - token2 = new MockERC20("TestC", "C", 18); - token2.mint(address(this), 2 ** 128); + MockERC20[] memory tokens = deployTokens(3, 2 ** 128); + token0 = tokens[0]; + token1 = tokens[1]; + token2 = tokens[2]; FullRangeImplementation impl = new FullRangeImplementation(manager, fullRange); vm.etch(address(fullRange), address(impl).code); diff --git a/test/TWAMM.t.sol b/test/TWAMM.t.sol index 266424db..14125657 100644 --- a/test/TWAMM.t.sol +++ b/test/TWAMM.t.sol @@ -76,9 +76,7 @@ contract TWAMMTest is Test, Deployers, GasSnapshot { } } - poolKey = PoolKey(Currency.wrap(address(token0)), Currency.wrap(address(token1)), 3000, 60, twamm); - poolId = poolKey.toId(); - manager.initialize(poolKey, SQRT_RATIO_1_1, ZERO_BYTES); + (poolKey, poolId) = initPool(currency0, currency1, twamm, 3000, SQRT_RATIO_1_1, ZERO_BYTES); token0.approve(address(modifyPositionRouter), 100 ether); token1.approve(address(modifyPositionRouter), 100 ether); From 311ff6f870f0e6306cdcf9de58612ebba29ae71f Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Mon, 11 Dec 2023 13:58:50 -0500 Subject: [PATCH 06/12] update to latest core --- .../FullOracleObserve0After5Seconds.snap | 2 +- .../FullOracleObserve200By13.snap | 2 +- .../FullOracleObserve200By13Plus5.snap | 2 +- .../FullOracleObserve5After5Seconds.snap | 2 +- .forge-snapshots/FullOracleObserveOldest.snap | 2 +- .../FullOracleObserveOldestAfter5Seconds.snap | 2 +- .forge-snapshots/FullOracleObserveZero.snap | 2 +- .../FullRangeAddInitialLiquidity.snap | 2 +- .forge-snapshots/FullRangeAddLiquidity.snap | 2 +- .forge-snapshots/FullRangeFirstSwap.snap | 2 +- .forge-snapshots/FullRangeInitialize.snap | 2 +- .../FullRangeRemoveLiquidity.snap | 2 +- .../FullRangeRemoveLiquidityAndRebalance.snap | 2 +- .forge-snapshots/FullRangeSecondSwap.snap | 2 +- .forge-snapshots/FullRangeSwap.snap | 2 +- .forge-snapshots/OracleGrow10Slots.snap | 2 +- .../OracleGrow10SlotsCardinalityGreater.snap | 2 +- .forge-snapshots/OracleGrow1Slot.snap | 2 +- .../OracleGrow1SlotCardinalityGreater.snap | 2 +- .forge-snapshots/OracleInitialize.snap | 2 +- ...eObserveBetweenOldestAndOldestPlusOne.snap | 2 +- .../OracleObserveCurrentTime.snap | 2 +- ...racleObserveCurrentTimeCounterfactual.snap | 2 +- .../OracleObserveLast20Seconds.snap | 2 +- .../OracleObserveLatestEqual.snap | 2 +- .../OracleObserveLatestTransform.snap | 2 +- .forge-snapshots/OracleObserveMiddle.snap | 2 +- .forge-snapshots/OracleObserveOldest.snap | 2 +- .../OracleObserveSinceMostRecent.snap | 2 +- .forge-snapshots/TWAMMSubmitOrder.snap | 2 +- .gitignore | 3 +- contracts/BaseHook.sol | 11 ++++-- contracts/hooks/examples/FullRange.sol | 20 ++++++----- contracts/hooks/examples/GeomeanOracle.sol | 12 ++++--- contracts/hooks/examples/LimitOrder.sol | 14 +++++--- contracts/hooks/examples/TWAMM.sol | 21 ++++++++---- contracts/hooks/examples/VolatilityOracle.sol | 8 +++-- lib/v4-core | 2 +- test/FullRange.t.sol | 34 +++++++++---------- test/GeomeanOracle.t.sol | 18 +++++----- test/LimitOrder.t.sol | 4 +-- test/TWAMM.t.sol | 2 +- .../FullRangeImplementation.sol | 2 +- .../GeomeanOracleImplementation.sol | 2 +- .../LimitOrderImplementation.sol | 2 +- .../implementation/TWAMMImplementation.sol | 2 +- test/utils/HookEnabledSwapRouter.sol | 5 +-- 47 files changed, 126 insertions(+), 96 deletions(-) diff --git a/.forge-snapshots/FullOracleObserve0After5Seconds.snap b/.forge-snapshots/FullOracleObserve0After5Seconds.snap index 9463411b..bc61a749 100644 --- a/.forge-snapshots/FullOracleObserve0After5Seconds.snap +++ b/.forge-snapshots/FullOracleObserve0After5Seconds.snap @@ -1 +1 @@ -2000 \ No newline at end of file +2771 \ No newline at end of file diff --git a/.forge-snapshots/FullOracleObserve200By13.snap b/.forge-snapshots/FullOracleObserve200By13.snap index 638f8744..7706f4dd 100644 --- a/.forge-snapshots/FullOracleObserve200By13.snap +++ b/.forge-snapshots/FullOracleObserve200By13.snap @@ -1 +1 @@ -21068 \ No newline at end of file +23377 \ No newline at end of file diff --git a/.forge-snapshots/FullOracleObserve200By13Plus5.snap b/.forge-snapshots/FullOracleObserve200By13Plus5.snap index 1bc3059d..8afa5484 100644 --- a/.forge-snapshots/FullOracleObserve200By13Plus5.snap +++ b/.forge-snapshots/FullOracleObserve200By13Plus5.snap @@ -1 +1 @@ -21318 \ No newline at end of file +23624 \ No newline at end of file diff --git a/.forge-snapshots/FullOracleObserve5After5Seconds.snap b/.forge-snapshots/FullOracleObserve5After5Seconds.snap index a5bb2393..f66ebbd5 100644 --- a/.forge-snapshots/FullOracleObserve5After5Seconds.snap +++ b/.forge-snapshots/FullOracleObserve5After5Seconds.snap @@ -1 +1 @@ -2076 \ No newline at end of file +2798 \ No newline at end of file diff --git a/.forge-snapshots/FullOracleObserveOldest.snap b/.forge-snapshots/FullOracleObserveOldest.snap index db768f3a..9db3df4e 100644 --- a/.forge-snapshots/FullOracleObserveOldest.snap +++ b/.forge-snapshots/FullOracleObserveOldest.snap @@ -1 +1 @@ -20164 \ No newline at end of file +22396 \ No newline at end of file diff --git a/.forge-snapshots/FullOracleObserveOldestAfter5Seconds.snap b/.forge-snapshots/FullOracleObserveOldestAfter5Seconds.snap index c04b75bb..b2f26cf1 100644 --- a/.forge-snapshots/FullOracleObserveOldestAfter5Seconds.snap +++ b/.forge-snapshots/FullOracleObserveOldestAfter5Seconds.snap @@ -1 +1 @@ -20458 \ No newline at end of file +22695 \ No newline at end of file diff --git a/.forge-snapshots/FullOracleObserveZero.snap b/.forge-snapshots/FullOracleObserveZero.snap index 7f966954..f91847e9 100644 --- a/.forge-snapshots/FullOracleObserveZero.snap +++ b/.forge-snapshots/FullOracleObserveZero.snap @@ -1 +1 @@ -1525 \ No newline at end of file +2130 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeAddInitialLiquidity.snap b/.forge-snapshots/FullRangeAddInitialLiquidity.snap index 7e3a2f44..7d8545fe 100644 --- a/.forge-snapshots/FullRangeAddInitialLiquidity.snap +++ b/.forge-snapshots/FullRangeAddInitialLiquidity.snap @@ -1 +1 @@ -390028 \ No newline at end of file +410731 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeAddLiquidity.snap b/.forge-snapshots/FullRangeAddLiquidity.snap index fcc9c101..e7c101bd 100644 --- a/.forge-snapshots/FullRangeAddLiquidity.snap +++ b/.forge-snapshots/FullRangeAddLiquidity.snap @@ -1 +1 @@ -184294 \ No newline at end of file +204653 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeFirstSwap.snap b/.forge-snapshots/FullRangeFirstSwap.snap index 08d86dfe..2b5ad7d2 100644 --- a/.forge-snapshots/FullRangeFirstSwap.snap +++ b/.forge-snapshots/FullRangeFirstSwap.snap @@ -1 +1 @@ -133339 \ No newline at end of file +156432 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeInitialize.snap b/.forge-snapshots/FullRangeInitialize.snap index b07717ab..c2b5d0ef 100644 --- a/.forge-snapshots/FullRangeInitialize.snap +++ b/.forge-snapshots/FullRangeInitialize.snap @@ -1 +1 @@ -896690 \ No newline at end of file +897565 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeRemoveLiquidity.snap b/.forge-snapshots/FullRangeRemoveLiquidity.snap index 594d74bc..f8ded9d9 100644 --- a/.forge-snapshots/FullRangeRemoveLiquidity.snap +++ b/.forge-snapshots/FullRangeRemoveLiquidity.snap @@ -1 +1 @@ -177393 \ No newline at end of file +200027 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeRemoveLiquidityAndRebalance.snap b/.forge-snapshots/FullRangeRemoveLiquidityAndRebalance.snap index e2e0f2f7..504a326a 100644 --- a/.forge-snapshots/FullRangeRemoveLiquidityAndRebalance.snap +++ b/.forge-snapshots/FullRangeRemoveLiquidityAndRebalance.snap @@ -1 +1 @@ -362063 \ No newline at end of file +386065 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeSecondSwap.snap b/.forge-snapshots/FullRangeSecondSwap.snap index e21f3119..9e12e78d 100644 --- a/.forge-snapshots/FullRangeSecondSwap.snap +++ b/.forge-snapshots/FullRangeSecondSwap.snap @@ -1 +1 @@ -93685 \ No newline at end of file +114700 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeSwap.snap b/.forge-snapshots/FullRangeSwap.snap index 77bbcb9a..d9365d02 100644 --- a/.forge-snapshots/FullRangeSwap.snap +++ b/.forge-snapshots/FullRangeSwap.snap @@ -1 +1 @@ -131614 \ No newline at end of file +154641 \ No newline at end of file diff --git a/.forge-snapshots/OracleGrow10Slots.snap b/.forge-snapshots/OracleGrow10Slots.snap index 61763356..3aa3cfac 100644 --- a/.forge-snapshots/OracleGrow10Slots.snap +++ b/.forge-snapshots/OracleGrow10Slots.snap @@ -1 +1 @@ -233028 \ No newline at end of file +254711 \ No newline at end of file diff --git a/.forge-snapshots/OracleGrow10SlotsCardinalityGreater.snap b/.forge-snapshots/OracleGrow10SlotsCardinalityGreater.snap index 4f1264df..50fc054a 100644 --- a/.forge-snapshots/OracleGrow10SlotsCardinalityGreater.snap +++ b/.forge-snapshots/OracleGrow10SlotsCardinalityGreater.snap @@ -1 +1 @@ -223717 \ No newline at end of file +245393 \ No newline at end of file diff --git a/.forge-snapshots/OracleGrow1Slot.snap b/.forge-snapshots/OracleGrow1Slot.snap index 3d85d6d7..15a052b9 100644 --- a/.forge-snapshots/OracleGrow1Slot.snap +++ b/.forge-snapshots/OracleGrow1Slot.snap @@ -1 +1 @@ -32886 \ No newline at end of file +54893 \ No newline at end of file diff --git a/.forge-snapshots/OracleGrow1SlotCardinalityGreater.snap b/.forge-snapshots/OracleGrow1SlotCardinalityGreater.snap index bc6dc069..d6664238 100644 --- a/.forge-snapshots/OracleGrow1SlotCardinalityGreater.snap +++ b/.forge-snapshots/OracleGrow1SlotCardinalityGreater.snap @@ -1 +1 @@ -23586 \ No newline at end of file +45575 \ No newline at end of file diff --git a/.forge-snapshots/OracleInitialize.snap b/.forge-snapshots/OracleInitialize.snap index da81ec04..3039612c 100644 --- a/.forge-snapshots/OracleInitialize.snap +++ b/.forge-snapshots/OracleInitialize.snap @@ -1 +1 @@ -51411 \ No newline at end of file +72361 \ No newline at end of file diff --git a/.forge-snapshots/OracleObserveBetweenOldestAndOldestPlusOne.snap b/.forge-snapshots/OracleObserveBetweenOldestAndOldestPlusOne.snap index f61a3565..ae13ac3f 100644 --- a/.forge-snapshots/OracleObserveBetweenOldestAndOldestPlusOne.snap +++ b/.forge-snapshots/OracleObserveBetweenOldestAndOldestPlusOne.snap @@ -1 +1 @@ -5571 \ No newline at end of file +6618 \ No newline at end of file diff --git a/.forge-snapshots/OracleObserveCurrentTime.snap b/.forge-snapshots/OracleObserveCurrentTime.snap index 7f966954..f91847e9 100644 --- a/.forge-snapshots/OracleObserveCurrentTime.snap +++ b/.forge-snapshots/OracleObserveCurrentTime.snap @@ -1 +1 @@ -1525 \ No newline at end of file +2130 \ No newline at end of file diff --git a/.forge-snapshots/OracleObserveCurrentTimeCounterfactual.snap b/.forge-snapshots/OracleObserveCurrentTimeCounterfactual.snap index 7f966954..f91847e9 100644 --- a/.forge-snapshots/OracleObserveCurrentTimeCounterfactual.snap +++ b/.forge-snapshots/OracleObserveCurrentTimeCounterfactual.snap @@ -1 +1 @@ -1525 \ No newline at end of file +2130 \ No newline at end of file diff --git a/.forge-snapshots/OracleObserveLast20Seconds.snap b/.forge-snapshots/OracleObserveLast20Seconds.snap index 41599c5d..b63da1de 100644 --- a/.forge-snapshots/OracleObserveLast20Seconds.snap +++ b/.forge-snapshots/OracleObserveLast20Seconds.snap @@ -1 +1 @@ -75965 \ No newline at end of file +88543 \ No newline at end of file diff --git a/.forge-snapshots/OracleObserveLatestEqual.snap b/.forge-snapshots/OracleObserveLatestEqual.snap index 7f966954..f91847e9 100644 --- a/.forge-snapshots/OracleObserveLatestEqual.snap +++ b/.forge-snapshots/OracleObserveLatestEqual.snap @@ -1 +1 @@ -1525 \ No newline at end of file +2130 \ No newline at end of file diff --git a/.forge-snapshots/OracleObserveLatestTransform.snap b/.forge-snapshots/OracleObserveLatestTransform.snap index 9463411b..bc61a749 100644 --- a/.forge-snapshots/OracleObserveLatestTransform.snap +++ b/.forge-snapshots/OracleObserveLatestTransform.snap @@ -1 +1 @@ -2000 \ No newline at end of file +2771 \ No newline at end of file diff --git a/.forge-snapshots/OracleObserveMiddle.snap b/.forge-snapshots/OracleObserveMiddle.snap index 0b1caa8d..ba7fb703 100644 --- a/.forge-snapshots/OracleObserveMiddle.snap +++ b/.forge-snapshots/OracleObserveMiddle.snap @@ -1 +1 @@ -5746 \ No newline at end of file +6807 \ No newline at end of file diff --git a/.forge-snapshots/OracleObserveOldest.snap b/.forge-snapshots/OracleObserveOldest.snap index bee097af..3ee11622 100644 --- a/.forge-snapshots/OracleObserveOldest.snap +++ b/.forge-snapshots/OracleObserveOldest.snap @@ -1 +1 @@ -5277 \ No newline at end of file +6319 \ No newline at end of file diff --git a/.forge-snapshots/OracleObserveSinceMostRecent.snap b/.forge-snapshots/OracleObserveSinceMostRecent.snap index a51f76e9..204ec243 100644 --- a/.forge-snapshots/OracleObserveSinceMostRecent.snap +++ b/.forge-snapshots/OracleObserveSinceMostRecent.snap @@ -1 +1 @@ -2615 \ No newline at end of file +3466 \ No newline at end of file diff --git a/.forge-snapshots/TWAMMSubmitOrder.snap b/.forge-snapshots/TWAMMSubmitOrder.snap index d01ad33f..21c2b598 100644 --- a/.forge-snapshots/TWAMMSubmitOrder.snap +++ b/.forge-snapshots/TWAMMSubmitOrder.snap @@ -1 +1 @@ -123619 \ No newline at end of file +146128 \ No newline at end of file diff --git a/.gitignore b/.gitignore index de5c2c73..785fb393 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ cache/ -foundry-out/ \ No newline at end of file +foundry-out/ +.vscode/ \ No newline at end of file diff --git a/contracts/BaseHook.sol b/contracts/BaseHook.sol index a16ab91d..941de34c 100644 --- a/contracts/BaseHook.sol +++ b/contracts/BaseHook.sol @@ -40,16 +40,21 @@ abstract contract BaseHook is IHooks { _; } - function getHooksCalls() public pure virtual returns (Hooks.Calls memory); + function getHooksCalls() public pure virtual returns (Hooks.Permissions memory); // this function is virtual so that we can override it during testing, // which allows us to deploy an implementation to any address // and then etch the bytecode into the correct address function validateHookAddress(BaseHook _this) internal pure virtual { - Hooks.validateHookAddress(_this, getHooksCalls()); + Hooks.validateHookPermissions(_this, getHooksCalls()); } - function lockAcquired(bytes calldata data) external virtual poolManagerOnly returns (bytes memory) { + function lockAcquired(address, /*sender*/ bytes calldata data) + external + virtual + poolManagerOnly + returns (bytes memory) + { (bool success, bytes memory returnData) = address(this).call(data); if (success) return returnData; if (returnData.length == 0) revert LockFailure(); diff --git a/contracts/hooks/examples/FullRange.sol b/contracts/hooks/examples/FullRange.sol index eaa7539b..ecd4a26b 100644 --- a/contracts/hooks/examples/FullRange.sol +++ b/contracts/hooks/examples/FullRange.sol @@ -87,8 +87,8 @@ contract FullRange is BaseHook, ILockCallback { _; } - function getHooksCalls() public pure override returns (Hooks.Calls memory) { - return Hooks.Calls({ + function getHooksCalls() public pure override returns (Hooks.Permissions memory) { + return Hooks.Permissions({ beforeInitialize: true, afterInitialize: false, beforeModifyPosition: true, @@ -96,7 +96,9 @@ contract FullRange is BaseHook, ILockCallback { beforeSwap: true, afterSwap: false, beforeDonate: false, - afterDonate: false + afterDonate: false, + noOp: false, + accessLock: false }); } @@ -115,7 +117,7 @@ contract FullRange is BaseHook, ILockCallback { PoolId poolId = key.toId(); - (uint160 sqrtPriceX96,,,) = poolManager.getSlot0(poolId); + (uint160 sqrtPriceX96,,) = poolManager.getSlot0(poolId); if (sqrtPriceX96 == 0) revert PoolNotInitialized(); @@ -172,7 +174,7 @@ contract FullRange is BaseHook, ILockCallback { PoolId poolId = key.toId(); - (uint160 sqrtPriceX96,,,) = poolManager.getSlot0(poolId); + (uint160 sqrtPriceX96,,) = poolManager.getSlot0(poolId); if (sqrtPriceX96 == 0) revert PoolNotInitialized(); @@ -247,7 +249,9 @@ contract FullRange is BaseHook, ILockCallback { internal returns (BalanceDelta delta) { - delta = abi.decode(poolManager.lock(abi.encode(CallbackData(msg.sender, key, params))), (BalanceDelta)); + delta = abi.decode( + poolManager.lock(address(this), abi.encode(CallbackData(msg.sender, key, params))), (BalanceDelta) + ); } function _settleDeltas(address sender, PoolKey memory key, BalanceDelta delta) internal { @@ -295,7 +299,7 @@ contract FullRange is BaseHook, ILockCallback { pool.hasAccruedFees = false; } - function lockAcquired(bytes calldata rawData) + function lockAcquired(address, /*sender*/ bytes calldata rawData) external override(ILockCallback, BaseHook) poolManagerOnly @@ -332,7 +336,7 @@ contract FullRange is BaseHook, ILockCallback { ) * FixedPointMathLib.sqrt(FixedPoint96.Q96) ).toUint160(); - (uint160 sqrtPriceX96,,,) = poolManager.getSlot0(poolId); + (uint160 sqrtPriceX96,,) = poolManager.getSlot0(poolId); poolManager.swap( key, diff --git a/contracts/hooks/examples/GeomeanOracle.sol b/contracts/hooks/examples/GeomeanOracle.sol index 8ae1c640..35389d0f 100644 --- a/contracts/hooks/examples/GeomeanOracle.sol +++ b/contracts/hooks/examples/GeomeanOracle.sol @@ -60,8 +60,8 @@ contract GeomeanOracle is BaseHook { constructor(IPoolManager _poolManager) BaseHook(_poolManager) {} - function getHooksCalls() public pure override returns (Hooks.Calls memory) { - return Hooks.Calls({ + function getHooksCalls() public pure override returns (Hooks.Permissions memory) { + return Hooks.Permissions({ beforeInitialize: true, afterInitialize: true, beforeModifyPosition: true, @@ -69,7 +69,9 @@ contract GeomeanOracle is BaseHook { beforeSwap: true, afterSwap: false, beforeDonate: false, - afterDonate: false + afterDonate: false, + noOp: false, + accessLock: false }); } @@ -101,7 +103,7 @@ contract GeomeanOracle is BaseHook { /// @dev Called before any action that potentially modifies pool price or liquidity, such as swap or modify position function _updatePool(PoolKey calldata key) private { PoolId id = key.toId(); - (, int24 tick,,) = poolManager.getSlot0(id); + (, int24 tick,) = poolManager.getSlot0(id); uint128 liquidity = poolManager.getLiquidity(id); @@ -146,7 +148,7 @@ contract GeomeanOracle is BaseHook { ObservationState memory state = states[id]; - (, int24 tick,,) = poolManager.getSlot0(id); + (, int24 tick,) = poolManager.getSlot0(id); uint128 liquidity = poolManager.getLiquidity(id); diff --git a/contracts/hooks/examples/LimitOrder.sol b/contracts/hooks/examples/LimitOrder.sol index d2654f49..2a5287bf 100644 --- a/contracts/hooks/examples/LimitOrder.sol +++ b/contracts/hooks/examples/LimitOrder.sol @@ -73,8 +73,8 @@ contract LimitOrder is BaseHook { constructor(IPoolManager _poolManager) BaseHook(_poolManager) {} - function getHooksCalls() public pure override returns (Hooks.Calls memory) { - return Hooks.Calls({ + function getHooksCalls() public pure override returns (Hooks.Permissions memory) { + return Hooks.Permissions({ beforeInitialize: false, afterInitialize: true, beforeModifyPosition: false, @@ -82,7 +82,9 @@ contract LimitOrder is BaseHook { beforeSwap: false, afterSwap: true, beforeDonate: false, - afterDonate: false + afterDonate: false, + noOp: false, + accessLock: false }); } @@ -107,7 +109,7 @@ contract LimitOrder is BaseHook { } function getTick(PoolId poolId) private view returns (int24 tick) { - (, tick,,) = poolManager.getSlot0(poolId); + (, tick,) = poolManager.getSlot0(poolId); } function getTickLower(int24 tick, int24 tickSpacing) private pure returns (int24) { @@ -156,6 +158,7 @@ contract LimitOrder is BaseHook { (uint256 amount0, uint256 amount1) = abi.decode( poolManager.lock( + address(this), abi.encodeCall(this.lockAcquiredFill, (key, lower, -int256(uint256(epochInfo.liquidityTotal)))) ), (uint256, uint256) @@ -219,6 +222,7 @@ contract LimitOrder is BaseHook { if (liquidity == 0) revert ZeroLiquidity(); poolManager.lock( + address(this), abi.encodeCall(this.lockAcquiredPlace, (key, tickLower, zeroForOne, int256(uint256(liquidity)), msg.sender)) ); @@ -302,6 +306,7 @@ contract LimitOrder is BaseHook { uint256 amount1Fee; (amount0, amount1, amount0Fee, amount1Fee) = abi.decode( poolManager.lock( + address(this), abi.encodeCall( this.lockAcquiredKill, (key, tickLower, -int256(uint256(liquidity)), to, liquidity == liquidityTotal) @@ -385,6 +390,7 @@ contract LimitOrder is BaseHook { epochInfo.liquidityTotal = liquidityTotal - liquidity; poolManager.lock( + address(this), abi.encodeCall(this.lockAcquiredWithdraw, (epochInfo.currency0, epochInfo.currency1, amount0, amount1, to)) ); diff --git a/contracts/hooks/examples/TWAMM.sol b/contracts/hooks/examples/TWAMM.sol index a6635e94..bb0592ad 100644 --- a/contracts/hooks/examples/TWAMM.sol +++ b/contracts/hooks/examples/TWAMM.sol @@ -60,8 +60,8 @@ contract TWAMM is BaseHook, ITWAMM { expirationInterval = _expirationInterval; } - function getHooksCalls() public pure override returns (Hooks.Calls memory) { - return Hooks.Calls({ + function getHooksCalls() public pure override returns (Hooks.Permissions memory) { + return Hooks.Permissions({ beforeInitialize: true, afterInitialize: false, beforeModifyPosition: true, @@ -69,7 +69,9 @@ contract TWAMM is BaseHook, ITWAMM { beforeSwap: true, afterSwap: false, beforeDonate: false, - afterDonate: false + afterDonate: false, + noOp: false, + accessLock: false }); } @@ -138,7 +140,7 @@ contract TWAMM is BaseHook, ITWAMM { /// @inheritdoc ITWAMM function executeTWAMMOrders(PoolKey memory key) public { PoolId poolId = key.toId(); - (uint160 sqrtPriceX96,,,) = poolManager.getSlot0(poolId); + (uint160 sqrtPriceX96,,) = poolManager.getSlot0(poolId); State storage twamm = twammStates[poolId]; (bool zeroForOne, uint160 sqrtPriceLimitX96) = _executeTWAMMOrders( @@ -146,7 +148,9 @@ contract TWAMM is BaseHook, ITWAMM { ); if (sqrtPriceLimitX96 != 0 && sqrtPriceLimitX96 != sqrtPriceX96) { - poolManager.lock(abi.encode(key, IPoolManager.SwapParams(zeroForOne, type(int256).max, sqrtPriceLimitX96))); + poolManager.lock( + address(this), abi.encode(key, IPoolManager.SwapParams(zeroForOne, type(int256).max, sqrtPriceLimitX96)) + ); } } @@ -302,7 +306,12 @@ contract TWAMM is BaseHook, ITWAMM { IERC20Minimal(Currency.unwrap(token)).safeTransfer(to, amountTransferred); } - function lockAcquired(bytes calldata rawData) external override poolManagerOnly returns (bytes memory) { + function lockAcquired(address sender, bytes calldata rawData) + external + override + poolManagerOnly + returns (bytes memory) + { (PoolKey memory key, IPoolManager.SwapParams memory swapParams) = abi.decode(rawData, (PoolKey, IPoolManager.SwapParams)); diff --git a/contracts/hooks/examples/VolatilityOracle.sol b/contracts/hooks/examples/VolatilityOracle.sol index 65485e11..657c9fae 100644 --- a/contracts/hooks/examples/VolatilityOracle.sol +++ b/contracts/hooks/examples/VolatilityOracle.sol @@ -30,8 +30,8 @@ contract VolatilityOracle is BaseHook, IDynamicFeeManager { deployTimestamp = _blockTimestamp(); } - function getHooksCalls() public pure override returns (Hooks.Calls memory) { - return Hooks.Calls({ + function getHooksCalls() public pure override returns (Hooks.Permissions memory) { + return Hooks.Permissions({ beforeInitialize: true, afterInitialize: false, beforeModifyPosition: false, @@ -39,7 +39,9 @@ contract VolatilityOracle is BaseHook, IDynamicFeeManager { beforeSwap: false, afterSwap: false, beforeDonate: false, - afterDonate: false + afterDonate: false, + noOp: false, + accessLock: false }); } diff --git a/lib/v4-core b/lib/v4-core index 7998e6c3..cda1f483 160000 --- a/lib/v4-core +++ b/lib/v4-core @@ -1 +1 @@ -Subproject commit 7998e6c391b77d2a8455f902097b0180b579db1b +Subproject commit cda1f483d41b0db7ee28a7de3f3bbe47c7f33cfc diff --git a/test/FullRange.t.sol b/test/FullRange.t.sol index e6c75f97..3d3f6800 100644 --- a/test/FullRange.t.sol +++ b/test/FullRange.t.sol @@ -127,7 +127,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { emit Initialize(id, testKey.currency0, testKey.currency1, testKey.fee, testKey.tickSpacing, testKey.hooks); snapStart("FullRangeInitialize"); - manager.initialize(testKey, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(testKey, SQRT_RATIO_1_1, ZERO_BYTES); snapEnd(); (, address liquidityToken) = fullRange.poolInfo(id); @@ -139,11 +139,11 @@ contract TestFullRange is Test, Deployers, GasSnapshot { PoolKey memory wrongKey = PoolKey(key.currency0, key.currency1, 0, TICK_SPACING + 1, fullRange); vm.expectRevert(FullRange.TickSpacingNotDefault.selector); - manager.initialize(wrongKey, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(wrongKey, SQRT_RATIO_1_1, ZERO_BYTES); } function testFullRange_addLiquidity_InitialAddSucceeds() public { - manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); uint256 prevBalance0 = key.currency0.balanceOf(address(this)); uint256 prevBalance1 = key.currency1.balanceOf(address(this)); @@ -169,7 +169,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { } function testFullRange_addLiquidity_InitialAddFuzz(uint256 amount) public { - manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); if (amount < LOCKED_LIQUIDITY) { vm.expectRevert(FullRange.LiquidityDoesntMeetMinimum.selector); fullRange.addLiquidity( @@ -244,7 +244,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { } function testFullRange_addLiquidity_SwapThenAddSucceeds() public { - manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); uint256 prevBalance0 = key.currency0.balanceOf(address(this)); uint256 prevBalance1 = key.currency1.balanceOf(address(this)); @@ -298,7 +298,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { } function testFullRange_addLiquidity_FailsIfTooMuchSlippage() public { - manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); fullRange.addLiquidity( FullRange.AddLiquidityParams( @@ -323,7 +323,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { function testFullRange_swap_TwoSwaps() public { PoolKey memory testKey = key; - manager.initialize(testKey, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(testKey, SQRT_RATIO_1_1, ZERO_BYTES); fullRange.addLiquidity( FullRange.AddLiquidityParams( @@ -352,8 +352,8 @@ contract TestFullRange is Test, Deployers, GasSnapshot { } function testFullRange_swap_TwoPools() public { - manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); - manager.initialize(key2, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(key2, SQRT_RATIO_1_1, ZERO_BYTES); fullRange.addLiquidity( FullRange.AddLiquidityParams( @@ -408,7 +408,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { } function testFullRange_removeLiquidity_InitialRemoveFuzz(uint256 amount) public { - manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); fullRange.addLiquidity( FullRange.AddLiquidityParams( @@ -456,7 +456,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { } function testFullRange_removeLiquidity_FailsIfNoLiquidity() public { - manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); (, address liquidityToken) = fullRange.poolInfo(id); UniswapV4ERC20(liquidityToken).approve(address(fullRange), type(uint256).max); @@ -468,7 +468,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { } function testFullRange_removeLiquidity_SucceedsWithPartial() public { - manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); uint256 prevBalance0 = key.currency0.balanceOfSelf(); uint256 prevBalance1 = key.currency1.balanceOfSelf(); @@ -503,7 +503,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { } function testFullRange_removeLiquidity_DiffRatios() public { - manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); uint256 prevBalance0 = key.currency0.balanceOf(address(this)); uint256 prevBalance1 = key.currency1.balanceOf(address(this)); @@ -571,7 +571,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { } function testFullRange_removeLiquidity_RemoveAllFuzz(uint256 amount) public { - manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); (, address liquidityToken) = fullRange.poolInfo(id); if (amount <= LOCKED_LIQUIDITY) { @@ -626,7 +626,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { vm.prank(address(2)); token1.approve(address(fullRange), type(uint256).max); - manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); (, address liquidityToken) = fullRange.poolInfo(id); // Test contract adds liquidity @@ -704,7 +704,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { } function testFullRange_removeLiquidity_SwapRemoveAllFuzz(uint256 amount) public { - manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); (, address liquidityToken) = fullRange.poolInfo(id); if (amount <= LOCKED_LIQUIDITY) { @@ -753,7 +753,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { } function testFullRange_BeforeModifyPositionFailsWithWrongMsgSender() public { - manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); vm.expectRevert(FullRange.SenderMustBeHook.selector); modifyPositionRouter.modifyPosition( diff --git a/test/GeomeanOracle.t.sol b/test/GeomeanOracle.t.sol index ce34adbd..aa5e5c6d 100644 --- a/test/GeomeanOracle.t.sol +++ b/test/GeomeanOracle.t.sol @@ -66,12 +66,12 @@ contract TestGeomeanOracle is Test, Deployers { } function testBeforeInitializeAllowsPoolCreation() public { - manager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); } function testBeforeInitializeRevertsIfFee() public { vm.expectRevert(GeomeanOracle.OnlyOneOraclePoolAllowed.selector); - manager.initialize( + initializeRouter.initialize( PoolKey(Currency.wrap(address(token0)), Currency.wrap(address(token1)), 1, MAX_TICK_SPACING, geomeanOracle), SQRT_RATIO_1_1, ZERO_BYTES @@ -80,7 +80,7 @@ contract TestGeomeanOracle is Test, Deployers { function testBeforeInitializeRevertsIfNotMaxTickSpacing() public { vm.expectRevert(GeomeanOracle.OnlyOneOraclePoolAllowed.selector); - manager.initialize( + initializeRouter.initialize( PoolKey(Currency.wrap(address(token0)), Currency.wrap(address(token1)), 0, 60, geomeanOracle), SQRT_RATIO_1_1, ZERO_BYTES @@ -88,7 +88,7 @@ contract TestGeomeanOracle is Test, Deployers { } function testAfterInitializeState() public { - manager.initialize(key, SQRT_RATIO_2_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_2_1, ZERO_BYTES); GeomeanOracle.ObservationState memory observationState = geomeanOracle.getState(key); assertEq(observationState.index, 0); assertEq(observationState.cardinality, 1); @@ -96,7 +96,7 @@ contract TestGeomeanOracle is Test, Deployers { } function testAfterInitializeObservation() public { - manager.initialize(key, SQRT_RATIO_2_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_2_1, ZERO_BYTES); Oracle.Observation memory observation = geomeanOracle.getObservation(key, 0); assertTrue(observation.initialized); assertEq(observation.blockTimestamp, 1); @@ -105,7 +105,7 @@ contract TestGeomeanOracle is Test, Deployers { } function testAfterInitializeObserve0() public { - manager.initialize(key, SQRT_RATIO_2_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_2_1, ZERO_BYTES); uint32[] memory secondsAgo = new uint32[](1); secondsAgo[0] = 0; (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s) = @@ -117,7 +117,7 @@ contract TestGeomeanOracle is Test, Deployers { } function testBeforeModifyPositionNoObservations() public { - manager.initialize(key, SQRT_RATIO_2_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_2_1, ZERO_BYTES); modifyPositionRouter.modifyPosition( key, IPoolManager.ModifyPositionParams( @@ -139,7 +139,7 @@ contract TestGeomeanOracle is Test, Deployers { } function testBeforeModifyPositionObservation() public { - manager.initialize(key, SQRT_RATIO_2_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_2_1, ZERO_BYTES); geomeanOracle.setTime(3); // advance 2 seconds modifyPositionRouter.modifyPosition( key, @@ -162,7 +162,7 @@ contract TestGeomeanOracle is Test, Deployers { } function testBeforeModifyPositionObservationAndCardinality() public { - manager.initialize(key, SQRT_RATIO_2_1, ZERO_BYTES); + initializeRouter.initialize(key, SQRT_RATIO_2_1, ZERO_BYTES); geomeanOracle.setTime(3); // advance 2 seconds geomeanOracle.increaseCardinalityNext(key, 2); GeomeanOracle.ObservationState memory observationState = geomeanOracle.getState(key); diff --git a/test/LimitOrder.t.sol b/test/LimitOrder.t.sol index 415e30be..94cca602 100644 --- a/test/LimitOrder.t.sol +++ b/test/LimitOrder.t.sol @@ -63,7 +63,7 @@ contract TestLimitOrder is Test, Deployers { function testGetTickLowerLastWithDifferentPrice() public { PoolKey memory differentKey = PoolKey(Currency.wrap(address(token0)), Currency.wrap(address(token1)), 3000, 61, limitOrder); - manager.initialize(differentKey, SQRT_RATIO_10_1, ZERO_BYTES); + initializeRouter.initialize(differentKey, SQRT_RATIO_10_1, ZERO_BYTES); assertEq(limitOrder.getTickLowerLast(differentKey.toId()), 22997); } @@ -197,7 +197,7 @@ contract TestLimitOrder is Test, Deployers { ); assertEq(limitOrder.getTickLowerLast(id), 60); - (, int24 tick,,) = manager.getSlot0(id); + (, int24 tick,) = manager.getSlot0(id); assertEq(tick, 60); (bool filled,,, uint256 token0Total, uint256 token1Total,) = limitOrder.epochInfos(Epoch.wrap(1)); diff --git a/test/TWAMM.t.sol b/test/TWAMM.t.sol index 14125657..1e3b6a5f 100644 --- a/test/TWAMM.t.sol +++ b/test/TWAMM.t.sol @@ -96,7 +96,7 @@ contract TWAMMTest is Test, Deployers, GasSnapshot { assertEq(twamm.lastVirtualOrderTimestamp(initId), 0); vm.warp(10000); - manager.initialize(initKey, SQRT_RATIO_1_1, ZERO_BYTES); + initializeRouter.initialize(initKey, SQRT_RATIO_1_1, ZERO_BYTES); assertEq(twamm.lastVirtualOrderTimestamp(initId), 10000); } diff --git a/test/shared/implementation/FullRangeImplementation.sol b/test/shared/implementation/FullRangeImplementation.sol index 8ee0589f..63592f5c 100644 --- a/test/shared/implementation/FullRangeImplementation.sol +++ b/test/shared/implementation/FullRangeImplementation.sol @@ -8,7 +8,7 @@ import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; contract FullRangeImplementation is FullRange { constructor(IPoolManager _poolManager, FullRange addressToEtch) FullRange(_poolManager) { - Hooks.validateHookAddress(addressToEtch, getHooksCalls()); + Hooks.validateHookPermissions(addressToEtch, getHooksCalls()); } // make this a no-op in testing diff --git a/test/shared/implementation/GeomeanOracleImplementation.sol b/test/shared/implementation/GeomeanOracleImplementation.sol index 68b669f1..0c964671 100644 --- a/test/shared/implementation/GeomeanOracleImplementation.sol +++ b/test/shared/implementation/GeomeanOracleImplementation.sol @@ -10,7 +10,7 @@ contract GeomeanOracleImplementation is GeomeanOracle { uint32 public time; constructor(IPoolManager _poolManager, GeomeanOracle addressToEtch) GeomeanOracle(_poolManager) { - Hooks.validateHookAddress(addressToEtch, getHooksCalls()); + Hooks.validateHookPermissions(addressToEtch, getHooksCalls()); } // make this a no-op in testing diff --git a/test/shared/implementation/LimitOrderImplementation.sol b/test/shared/implementation/LimitOrderImplementation.sol index b70f2553..c0f5a5f8 100644 --- a/test/shared/implementation/LimitOrderImplementation.sol +++ b/test/shared/implementation/LimitOrderImplementation.sol @@ -8,7 +8,7 @@ import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; contract LimitOrderImplementation is LimitOrder { constructor(IPoolManager _poolManager, LimitOrder addressToEtch) LimitOrder(_poolManager) { - Hooks.validateHookAddress(addressToEtch, getHooksCalls()); + Hooks.validateHookPermissions(addressToEtch, getHooksCalls()); } // make this a no-op in testing diff --git a/test/shared/implementation/TWAMMImplementation.sol b/test/shared/implementation/TWAMMImplementation.sol index 883eeb62..27a9e10c 100644 --- a/test/shared/implementation/TWAMMImplementation.sol +++ b/test/shared/implementation/TWAMMImplementation.sol @@ -8,7 +8,7 @@ import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; contract TWAMMImplementation is TWAMM { constructor(IPoolManager poolManager, uint256 interval, TWAMM addressToEtch) TWAMM(poolManager, interval) { - Hooks.validateHookAddress(addressToEtch, getHooksCalls()); + Hooks.validateHookPermissions(addressToEtch, getHooksCalls()); } // make this a no-op in testing diff --git a/test/utils/HookEnabledSwapRouter.sol b/test/utils/HookEnabledSwapRouter.sol index b924ed61..54832b4a 100644 --- a/test/utils/HookEnabledSwapRouter.sol +++ b/test/utils/HookEnabledSwapRouter.sol @@ -36,14 +36,15 @@ contract HookEnabledSwapRouter is PoolTestBase { bytes memory hookData ) external payable returns (BalanceDelta delta) { delta = abi.decode( - manager.lock(abi.encode(CallbackData(msg.sender, testSettings, key, params, hookData))), (BalanceDelta) + manager.lock(address(this), abi.encode(CallbackData(msg.sender, testSettings, key, params, hookData))), + (BalanceDelta) ); uint256 ethBalance = address(this).balance; if (ethBalance > 0) CurrencyLibrary.NATIVE.transfer(msg.sender, ethBalance); } - function lockAcquired(bytes calldata rawData) external returns (bytes memory) { + function lockAcquired(address, /*sender*/ bytes calldata rawData) external returns (bytes memory) { require(msg.sender == address(manager)); CallbackData memory data = abi.decode(rawData, (CallbackData)); From 5f4b7171edcf24be0cc977898f43da2bc345455c Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Mon, 11 Dec 2023 14:02:41 -0500 Subject: [PATCH 07/12] use prev values --- test/TWAMM.t.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/TWAMM.t.sol b/test/TWAMM.t.sol index 1e3b6a5f..bc4f73ff 100644 --- a/test/TWAMM.t.sol +++ b/test/TWAMM.t.sol @@ -188,8 +188,8 @@ contract TWAMMTest is Test, Deployers, GasSnapshot { assertEq(sellRate0For1, 2e18 / (expiration2 - submitTimestamp2)); assertEq(sellRate1For0, 3e18 / (expiration2 - submitTimestamp1)); - assertEq(earningsFactor0For1, 1636776489931663248324424309240000); - assertEq(earningsFactor1For0, 1534530274609724617872321172427618); + assertEq(earningsFactor0For1, 1712020976636017581269515821040000); + assertEq(earningsFactor1For0, 1470157410324350030712806974476955); } function testTWAMM_submitOrder_EmitsEvent() public { From ffe3b05dfe0e3e390f49cf39b8d731aa158cb5b3 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Mon, 11 Dec 2023 14:27:23 -0500 Subject: [PATCH 08/12] change twamm to use pool getters --- .forge-snapshots/TWAMMSubmitOrder.snap | 2 +- contracts/hooks/examples/TWAMM.sol | 4 ++-- contracts/libraries/PoolGetters.sol | 5 +++-- lib/v4-core | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.forge-snapshots/TWAMMSubmitOrder.snap b/.forge-snapshots/TWAMMSubmitOrder.snap index 21c2b598..0aef60be 100644 --- a/.forge-snapshots/TWAMMSubmitOrder.snap +++ b/.forge-snapshots/TWAMMSubmitOrder.snap @@ -1 +1 @@ -146128 \ No newline at end of file +146158 \ No newline at end of file diff --git a/contracts/hooks/examples/TWAMM.sol b/contracts/hooks/examples/TWAMM.sol index bb0592ad..395469a7 100644 --- a/contracts/hooks/examples/TWAMM.sol +++ b/contracts/hooks/examples/TWAMM.sol @@ -525,7 +525,7 @@ contract TWAMM is BaseHook, ITWAMM { _isCrossingInitializedTick(params.pool, poolManager, poolKey, finalSqrtPriceX96); if (crossingInitializedTick) { - int128 liquidityNetAtTick = poolManager.getNetLiquidityAtTick(poolKey.toId(), tick); + int128 liquidityNetAtTick = poolManager.getPoolTickInfo(poolKey.toId(), tick).liquidityNet; uint160 initializedSqrtPrice = TickMath.getSqrtRatioAtTick(tick); uint256 swapDelta0 = SqrtPriceMath.getAmount0Delta( @@ -609,7 +609,7 @@ contract TWAMM is BaseHook, ITWAMM { unchecked { // update pool - int128 liquidityNet = poolManager.getNetLiquidityAtTick(poolKey.toId(), params.initializedTick); + int128 liquidityNet = poolManager.getPoolTickInfo(poolKey.toId(), params.initializedTick).liquidityNet; if (initializedSqrtPrice < params.pool.sqrtPriceX96) liquidityNet = -liquidityNet; params.pool.liquidity = liquidityNet < 0 ? params.pool.liquidity - uint128(-liquidityNet) diff --git a/contracts/libraries/PoolGetters.sol b/contracts/libraries/PoolGetters.sol index 78f34c87..e3cb318b 100644 --- a/contracts/libraries/PoolGetters.sol +++ b/contracts/libraries/PoolGetters.sol @@ -7,6 +7,7 @@ import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol"; import {BitMath} from "@uniswap/v4-core/src/libraries/BitMath.sol"; /// @title Helper functions to access pool information +/// TODO: Expose other getters on core with extsload. Only use when extsload is available and storage layout is frozen. library PoolGetters { uint256 constant POOL_SLOT = 10; uint256 constant TICKS_OFFSET = 4; @@ -62,7 +63,7 @@ library PoolGetters { // all the 1s at or to the right of the current bitPos uint256 mask = (1 << bitPos) - 1 + (1 << bitPos); // uint256 masked = self[wordPos] & mask; - uint256 masked = getTickBitmapAtWord(poolManager, poolId, wordPos) & mask; + uint256 masked = poolManager.getPoolBitmapInfo(poolId, wordPos) & mask; // if there are no initialized ticks to the right of or at the current tick, return rightmost in the word initialized = masked != 0; @@ -75,7 +76,7 @@ library PoolGetters { (int16 wordPos, uint8 bitPos) = position(compressed + 1); // all the 1s at or to the left of the bitPos uint256 mask = ~((1 << bitPos) - 1); - uint256 masked = getTickBitmapAtWord(poolManager, poolId, wordPos) & mask; + uint256 masked = poolManager.getPoolBitmapInfo(poolId, wordPos) & mask; // if there are no initialized ticks to the left of the current tick, return leftmost in the word initialized = masked != 0; diff --git a/lib/v4-core b/lib/v4-core index cda1f483..83557113 160000 --- a/lib/v4-core +++ b/lib/v4-core @@ -1 +1 @@ -Subproject commit cda1f483d41b0db7ee28a7de3f3bbe47c7f33cfc +Subproject commit 83557113a0425eb3d81570c30e7a5ce550037149 From 6a72276c339aec55e7b8d75d7c5fbb806fb14a15 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Mon, 11 Dec 2023 15:11:36 -0500 Subject: [PATCH 09/12] changes after merging main --- contracts/base/PeripheryPayments.sol | 2 +- contracts/interfaces/IPeripheryPayments.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/base/PeripheryPayments.sol b/contracts/base/PeripheryPayments.sol index f272da34..24466924 100644 --- a/contracts/base/PeripheryPayments.sol +++ b/contracts/base/PeripheryPayments.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.19; import {ERC20} from "solmate/tokens/ERC20.sol"; -import {Currency, CurrencyLibrary} from "@uniswap/v4-core/contracts/types/Currency.sol"; +import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol"; import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol"; import {IPeripheryPayments} from "../interfaces/IPeripheryPayments.sol"; diff --git a/contracts/interfaces/IPeripheryPayments.sol b/contracts/interfaces/IPeripheryPayments.sol index 765b980f..f3c24660 100644 --- a/contracts/interfaces/IPeripheryPayments.sol +++ b/contracts/interfaces/IPeripheryPayments.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; -import {Currency} from "@uniswap/v4-core/contracts/types/Currency.sol"; +import {Currency} from "@uniswap/v4-core/src/types/Currency.sol"; /// @title Periphery Payments /// @notice Functions to ease deposits and withdrawals of ETH From 57183bdd7e540d65b002ccf7b9787ea1ada18898 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Mon, 11 Dec 2023 15:23:20 -0500 Subject: [PATCH 10/12] use --via-ir in cli --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 280df88b..f6d99f2d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,6 +22,6 @@ jobs: version: nightly - name: Run tests - run: forge test -vvv + run: forge test -vvv --via-ir env: FOUNDRY_PROFILE: ci From 18d68e812f056675e7356222a745315c2221ea4c Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Thu, 14 Dec 2023 12:30:46 -0500 Subject: [PATCH 11/12] fix formatting --- test/TWAMM.t.sol | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/TWAMM.t.sol b/test/TWAMM.t.sol index bc4f73ff..17ed64a1 100644 --- a/test/TWAMM.t.sol +++ b/test/TWAMM.t.sol @@ -61,11 +61,7 @@ contract TWAMMTest is Test, Deployers, GasSnapshot { token0 = MockERC20(Currency.unwrap(currency0)); token1 = MockERC20(Currency.unwrap(currency1)); - TWAMMImplementation impl = new TWAMMImplementation( - manager, - 10_000, - twamm - ); + TWAMMImplementation impl = new TWAMMImplementation(manager, 10_000, twamm); (, bytes32[] memory writes) = vm.accesses(address(impl)); vm.etch(address(twamm), address(impl).code); // for each storage key that was written during the hook implementation, copy the value over From fead64a423609083982e195016c814e307319ddc Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Thu, 14 Dec 2023 12:53:17 -0500 Subject: [PATCH 12/12] fix FullRange/TWAMM hook --- .forge-snapshots/FullRangeAddInitialLiquidity.snap | 2 +- .forge-snapshots/FullRangeAddLiquidity.snap | 2 +- .forge-snapshots/FullRangeRemoveLiquidity.snap | 2 +- .../FullRangeRemoveLiquidityAndRebalance.snap | 2 +- contracts/hooks/examples/FullRange.sol | 4 +++- contracts/hooks/examples/TWAMM.sol | 8 +------- 6 files changed, 8 insertions(+), 12 deletions(-) diff --git a/.forge-snapshots/FullRangeAddInitialLiquidity.snap b/.forge-snapshots/FullRangeAddInitialLiquidity.snap index 7d8545fe..ef62f828 100644 --- a/.forge-snapshots/FullRangeAddInitialLiquidity.snap +++ b/.forge-snapshots/FullRangeAddInitialLiquidity.snap @@ -1 +1 @@ -410731 \ No newline at end of file +410761 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeAddLiquidity.snap b/.forge-snapshots/FullRangeAddLiquidity.snap index e7c101bd..b3688dfa 100644 --- a/.forge-snapshots/FullRangeAddLiquidity.snap +++ b/.forge-snapshots/FullRangeAddLiquidity.snap @@ -1 +1 @@ -204653 \ No newline at end of file +204683 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeRemoveLiquidity.snap b/.forge-snapshots/FullRangeRemoveLiquidity.snap index f8ded9d9..bc1c95e2 100644 --- a/.forge-snapshots/FullRangeRemoveLiquidity.snap +++ b/.forge-snapshots/FullRangeRemoveLiquidity.snap @@ -1 +1 @@ -200027 \ No newline at end of file +200057 \ No newline at end of file diff --git a/.forge-snapshots/FullRangeRemoveLiquidityAndRebalance.snap b/.forge-snapshots/FullRangeRemoveLiquidityAndRebalance.snap index 504a326a..b5d7708e 100644 --- a/.forge-snapshots/FullRangeRemoveLiquidityAndRebalance.snap +++ b/.forge-snapshots/FullRangeRemoveLiquidityAndRebalance.snap @@ -1 +1 @@ -386065 \ No newline at end of file +386095 \ No newline at end of file diff --git a/contracts/hooks/examples/FullRange.sol b/contracts/hooks/examples/FullRange.sol index ecd4a26b..1bd0cfe2 100644 --- a/contracts/hooks/examples/FullRange.sol +++ b/contracts/hooks/examples/FullRange.sol @@ -299,12 +299,14 @@ contract FullRange is BaseHook, ILockCallback { pool.hasAccruedFees = false; } - function lockAcquired(address, /*sender*/ bytes calldata rawData) + function lockAcquired(address sender, bytes calldata rawData) external override(ILockCallback, BaseHook) poolManagerOnly returns (bytes memory) { + // Now that manager can be called by EOAs with a lock target, it's necessary for lockAcquired to check the original sender if it wants to trust the data passed through. + if (sender != address(this)) revert SenderMustBeHook(); CallbackData memory data = abi.decode(rawData, (CallbackData)); BalanceDelta delta; diff --git a/contracts/hooks/examples/TWAMM.sol b/contracts/hooks/examples/TWAMM.sol index 395469a7..4fd5dd74 100644 --- a/contracts/hooks/examples/TWAMM.sol +++ b/contracts/hooks/examples/TWAMM.sol @@ -131,12 +131,6 @@ contract TWAMM is BaseHook, ITWAMM { self.lastVirtualOrderTimestamp = block.timestamp; } - struct CallbackData { - address sender; - PoolKey key; - IPoolManager.SwapParams params; - } - /// @inheritdoc ITWAMM function executeTWAMMOrders(PoolKey memory key) public { PoolId poolId = key.toId(); @@ -306,7 +300,7 @@ contract TWAMM is BaseHook, ITWAMM { IERC20Minimal(Currency.unwrap(token)).safeTransfer(to, amountTransferred); } - function lockAcquired(address sender, bytes calldata rawData) + function lockAcquired(address, /*sender*/ bytes calldata rawData) external override poolManagerOnly