From d93b3c9237fe44e00a5c0f3bccffcce674af4119 Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Mon, 11 Dec 2023 13:41:09 -0300
Subject: [PATCH 01/19] Remove access lock

---
 ...swap hook, already cached dynamic fee.snap |   2 +-
 .../cached dynamic fee, no hooks.snap         |   2 +-
 .forge-snapshots/donate gas with 1 token.snap |   2 +-
 .../donate gas with 2 tokens.snap             |   2 +-
 .forge-snapshots/initialize.snap              |   2 +-
 .forge-snapshots/mint with empty hook.snap    |   2 +-
 .forge-snapshots/mint with native token.snap  |   2 +-
 .forge-snapshots/mint.snap                    |   2 +-
 .../mintWithEmptyHookEOAInitiated.snap        |   2 +-
 .../modify position with noop.snap            |   2 +-
 .../poolManager bytecode size.snap            |   2 +-
 .forge-snapshots/simple swap with native.snap |   2 +-
 .forge-snapshots/simple swap.snap             |   2 +-
 .forge-snapshots/simpleSwapEOAInitiated.snap  |   2 +-
 .../simpleSwapNativeEOAInitiated.snap         |   2 +-
 ...p against liquidity with native token.snap |   2 +-
 .forge-snapshots/swap against liquidity.snap  |   2 +-
 .../swap burn claim for input.snap            |   2 +-
 .../swap mint output as claim.snap            |   2 +-
 .forge-snapshots/swap with dynamic fee.snap   |   2 +-
 .forge-snapshots/swap with hooks.snap         |   2 +-
 .forge-snapshots/swap with noop.snap          |   2 +-
 .../update dynamic fee in before swap.snap    |   2 +-
 src/PoolManager.sol                           |   1 -
 src/libraries/Hooks.sol                       |   5 +-
 src/test/AccessLockHook.sol                   | 280 ------
 src/test/EmptyTestHooks.sol                   |   3 +-
 src/test/NoOpTestHooks.sol                    |   3 +-
 src/test/PoolDonateTest.sol                   |  12 +-
 src/test/PoolInitializeTest.sol               |  14 +-
 src/test/PoolModifyPositionTest.sol           |  15 +-
 src/test/PoolSwapTest.sol                     |  48 +-
 test/AccessLock.t.sol                         | 853 ------------------
 test/Hooks.t.sol                              | 101 +--
 34 files changed, 80 insertions(+), 1301 deletions(-)
 delete mode 100644 src/test/AccessLockHook.sol
 delete mode 100644 test/AccessLock.t.sol

diff --git a/.forge-snapshots/before swap hook, already cached dynamic fee.snap b/.forge-snapshots/before swap hook, already cached dynamic fee.snap
index 44d36db5e..c6604068b 100644
--- a/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
+++ b/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
@@ -1 +1 @@
-194519
\ No newline at end of file
+194810
\ No newline at end of file
diff --git a/.forge-snapshots/cached dynamic fee, no hooks.snap b/.forge-snapshots/cached dynamic fee, no hooks.snap
index ecc6dc509..7e5695e17 100644
--- a/.forge-snapshots/cached dynamic fee, no hooks.snap	
+++ b/.forge-snapshots/cached dynamic fee, no hooks.snap	
@@ -1 +1 @@
-146864
\ No newline at end of file
+147155
\ No newline at end of file
diff --git a/.forge-snapshots/donate gas with 1 token.snap b/.forge-snapshots/donate gas with 1 token.snap
index d09eb4748..5124469c5 100644
--- a/.forge-snapshots/donate gas with 1 token.snap	
+++ b/.forge-snapshots/donate gas with 1 token.snap	
@@ -1 +1 @@
-137968
\ No newline at end of file
+137830
\ No newline at end of file
diff --git a/.forge-snapshots/donate gas with 2 tokens.snap b/.forge-snapshots/donate gas with 2 tokens.snap
index ef8943ef6..750c16b17 100644
--- a/.forge-snapshots/donate gas with 2 tokens.snap	
+++ b/.forge-snapshots/donate gas with 2 tokens.snap	
@@ -1 +1 @@
-185390
\ No newline at end of file
+185252
\ No newline at end of file
diff --git a/.forge-snapshots/initialize.snap b/.forge-snapshots/initialize.snap
index 1e8ddbbcd..680d86780 100644
--- a/.forge-snapshots/initialize.snap
+++ b/.forge-snapshots/initialize.snap
@@ -1 +1 @@
-74268
\ No newline at end of file
+74213
\ No newline at end of file
diff --git a/.forge-snapshots/mint with empty hook.snap b/.forge-snapshots/mint with empty hook.snap
index f796eec15..b6a7df0e2 100644
--- a/.forge-snapshots/mint with empty hook.snap	
+++ b/.forge-snapshots/mint with empty hook.snap	
@@ -1 +1 @@
-323262
\ No newline at end of file
+323124
\ No newline at end of file
diff --git a/.forge-snapshots/mint with native token.snap b/.forge-snapshots/mint with native token.snap
index 1817e9ba2..71f46d1e2 100644
--- a/.forge-snapshots/mint with native token.snap	
+++ b/.forge-snapshots/mint with native token.snap	
@@ -1 +1 @@
-200100
\ No newline at end of file
+199962
\ No newline at end of file
diff --git a/.forge-snapshots/mint.snap b/.forge-snapshots/mint.snap
index ef066c96f..80422fda2 100644
--- a/.forge-snapshots/mint.snap
+++ b/.forge-snapshots/mint.snap
@@ -1 +1 @@
-200042
\ No newline at end of file
+199904
\ No newline at end of file
diff --git a/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap b/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
index d22631db9..eb0cff75d 100644
--- a/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
+++ b/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
@@ -1 +1 @@
-255158
\ No newline at end of file
+255020
\ No newline at end of file
diff --git a/.forge-snapshots/modify position with noop.snap b/.forge-snapshots/modify position with noop.snap
index 6ecd69a39..417bccb67 100644
--- a/.forge-snapshots/modify position with noop.snap	
+++ b/.forge-snapshots/modify position with noop.snap	
@@ -1 +1 @@
-58201
\ No newline at end of file
+58063
\ No newline at end of file
diff --git a/.forge-snapshots/poolManager bytecode size.snap b/.forge-snapshots/poolManager bytecode size.snap
index 533a9d3f2..c1302049f 100644
--- a/.forge-snapshots/poolManager bytecode size.snap	
+++ b/.forge-snapshots/poolManager bytecode size.snap	
@@ -1 +1 @@
-23592
\ No newline at end of file
+23544
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap with native.snap b/.forge-snapshots/simple swap with native.snap
index e66e1bc95..d9d1efec5 100644
--- a/.forge-snapshots/simple swap with native.snap	
+++ b/.forge-snapshots/simple swap with native.snap	
@@ -1 +1 @@
-195835
\ No newline at end of file
+195697
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap.snap b/.forge-snapshots/simple swap.snap
index e388485d4..2e51f4d43 100644
--- a/.forge-snapshots/simple swap.snap	
+++ b/.forge-snapshots/simple swap.snap	
@@ -1 +1 @@
-204403
\ No newline at end of file
+204265
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapEOAInitiated.snap b/.forge-snapshots/simpleSwapEOAInitiated.snap
index 90ceff1c6..17442dc1e 100644
--- a/.forge-snapshots/simpleSwapEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapEOAInitiated.snap
@@ -1 +1 @@
-175669
\ No newline at end of file
+175531
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
index a32a609e5..73521e106 100644
--- a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
@@ -1 +1 @@
-172331
\ No newline at end of file
+172193
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity with native token.snap b/.forge-snapshots/swap against liquidity with native token.snap
index 3838ae2e8..419176d5f 100644
--- a/.forge-snapshots/swap against liquidity with native token.snap	
+++ b/.forge-snapshots/swap against liquidity with native token.snap	
@@ -1 +1 @@
-126463
\ No newline at end of file
+126325
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity.snap b/.forge-snapshots/swap against liquidity.snap
index 9ce2e3bf8..42b5a458b 100644
--- a/.forge-snapshots/swap against liquidity.snap	
+++ b/.forge-snapshots/swap against liquidity.snap	
@@ -1 +1 @@
-113954
\ No newline at end of file
+113816
\ No newline at end of file
diff --git a/.forge-snapshots/swap burn claim for input.snap b/.forge-snapshots/swap burn claim for input.snap
index 9390d2181..71512a224 100644
--- a/.forge-snapshots/swap burn claim for input.snap	
+++ b/.forge-snapshots/swap burn claim for input.snap	
@@ -1 +1 @@
-133127
\ No newline at end of file
+132989
\ No newline at end of file
diff --git a/.forge-snapshots/swap mint output as claim.snap b/.forge-snapshots/swap mint output as claim.snap
index 12d1a218c..6b4d61781 100644
--- a/.forge-snapshots/swap mint output as claim.snap	
+++ b/.forge-snapshots/swap mint output as claim.snap	
@@ -1 +1 @@
-216596
\ No newline at end of file
+216458
\ No newline at end of file
diff --git a/.forge-snapshots/swap with dynamic fee.snap b/.forge-snapshots/swap with dynamic fee.snap
index da2a04f8e..a3be9998f 100644
--- a/.forge-snapshots/swap with dynamic fee.snap	
+++ b/.forge-snapshots/swap with dynamic fee.snap	
@@ -1 +1 @@
-193620
\ No newline at end of file
+193911
\ No newline at end of file
diff --git a/.forge-snapshots/swap with hooks.snap b/.forge-snapshots/swap with hooks.snap
index 54570960b..9fffbdfcd 100644
--- a/.forge-snapshots/swap with hooks.snap	
+++ b/.forge-snapshots/swap with hooks.snap	
@@ -1 +1 @@
-113932
\ No newline at end of file
+113794
\ No newline at end of file
diff --git a/.forge-snapshots/swap with noop.snap b/.forge-snapshots/swap with noop.snap
index 876b81885..ae6e82e41 100644
--- a/.forge-snapshots/swap with noop.snap	
+++ b/.forge-snapshots/swap with noop.snap	
@@ -1 +1 @@
-51546
\ No newline at end of file
+51408
\ No newline at end of file
diff --git a/.forge-snapshots/update dynamic fee in before swap.snap b/.forge-snapshots/update dynamic fee in before swap.snap
index 4d31f4eaa..bafcf12e7 100644
--- a/.forge-snapshots/update dynamic fee in before swap.snap	
+++ b/.forge-snapshots/update dynamic fee in before swap.snap	
@@ -1 +1 @@
-200363
\ No newline at end of file
+200654
\ No newline at end of file
diff --git a/src/PoolManager.sol b/src/PoolManager.sol
index e0c30663c..14f57bbbe 100644
--- a/src/PoolManager.sol
+++ b/src/PoolManager.sol
@@ -100,7 +100,6 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, Claims {
 
     function _checkLocker(address caller, address locker, IHooks hook) internal pure {
         if (caller == locker) return;
-        if (caller == address(hook) && hook.hasPermission(Hooks.ACCESS_LOCK_FLAG)) return;
         revert LockedBy(locker, address(hook));
     }
 
diff --git a/src/libraries/Hooks.sol b/src/libraries/Hooks.sol
index 09c68e608..5627b7bda 100644
--- a/src/libraries/Hooks.sol
+++ b/src/libraries/Hooks.sol
@@ -25,7 +25,6 @@ library Hooks {
     uint256 internal constant BEFORE_DONATE_FLAG = 1 << 153;
     uint256 internal constant AFTER_DONATE_FLAG = 1 << 152;
     uint256 internal constant NO_OP_FLAG = 1 << 151;
-    uint256 internal constant ACCESS_LOCK_FLAG = 1 << 150;
 
     bytes4 public constant NO_OP_SELECTOR = bytes4(keccak256(abi.encodePacked("NoOp")));
 
@@ -39,7 +38,6 @@ library Hooks {
         bool beforeDonate;
         bool afterDonate;
         bool noOp;
-        bool accessLock;
     }
 
     /// @notice Thrown if the address will not lead to the specified hook calls being called
@@ -67,7 +65,6 @@ library Hooks {
                 || permissions.beforeDonate != self.hasPermission(BEFORE_DONATE_FLAG)
                 || permissions.afterDonate != self.hasPermission(AFTER_DONATE_FLAG)
                 || permissions.noOp != self.hasPermission(NO_OP_FLAG)
-                || permissions.accessLock != self.hasPermission(ACCESS_LOCK_FLAG)
         ) {
             revert HookAddressNotValid(address(self));
         }
@@ -87,7 +84,7 @@ library Hooks {
         // If a hook contract is set, it must have at least 1 flag set, or have a dynamic fee
         return address(hook) == address(0)
             ? !fee.isDynamicFee()
-            : (uint160(address(hook)) >= ACCESS_LOCK_FLAG || fee.isDynamicFee());
+            : (uint160(address(hook)) >= NO_OP_FLAG || fee.isDynamicFee());
     }
 
     /// @notice performs a hook call using the given calldata on the given hook
diff --git a/src/test/AccessLockHook.sol b/src/test/AccessLockHook.sol
deleted file mode 100644
index 8293af2fb..000000000
--- a/src/test/AccessLockHook.sol
+++ /dev/null
@@ -1,280 +0,0 @@
-// SPDX-License-Identifier: UNLICENSED
-pragma solidity ^0.8.20;
-
-import {BaseTestHooks} from "./BaseTestHooks.sol";
-import {PoolKey} from "../types/PoolKey.sol";
-import {IPoolManager} from "../interfaces/IPoolManager.sol";
-import {IHooks} from "../interfaces/IHooks.sol";
-import {CurrencyLibrary, Currency} from "../types/Currency.sol";
-import {Hooks} from "../libraries/Hooks.sol";
-import {TickMath} from "../libraries/TickMath.sol";
-import {Test} from "forge-std/Test.sol";
-import {ILockCallback} from "../interfaces/callback/ILockCallback.sol";
-import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
-import {Constants} from "../../test/utils/Constants.sol";
-import {PoolIdLibrary} from "../types/PoolId.sol";
-import {BalanceDelta} from "../types/BalanceDelta.sol";
-
-contract AccessLockHook is Test, BaseTestHooks {
-    using PoolIdLibrary for PoolKey;
-    using CurrencyLibrary for Currency;
-
-    IPoolManager manager;
-
-    constructor(IPoolManager _manager) {
-        manager = _manager;
-    }
-
-    error InvalidAction();
-
-    enum LockAction {
-        Mint,
-        Take,
-        Donate,
-        Swap,
-        ModifyPosition,
-        Burn,
-        Settle,
-        Initialize,
-        NoOp
-    }
-
-    function beforeInitialize(
-        address, /* sender **/
-        PoolKey calldata key,
-        uint160, /* sqrtPriceX96 **/
-        bytes calldata hookData
-    ) external override returns (bytes4) {
-        return _executeAction(key, hookData, IHooks.beforeInitialize.selector);
-    }
-
-    function beforeSwap(
-        address, /* sender **/
-        PoolKey calldata key,
-        IPoolManager.SwapParams calldata, /* params **/
-        bytes calldata hookData
-    ) external override returns (bytes4) {
-        return _executeAction(key, hookData, IHooks.beforeSwap.selector);
-    }
-
-    function beforeDonate(
-        address, /* sender **/
-        PoolKey calldata key,
-        uint256, /* amount0 **/
-        uint256, /* amount1 **/
-        bytes calldata hookData
-    ) external override returns (bytes4) {
-        return _executeAction(key, hookData, IHooks.beforeDonate.selector);
-    }
-
-    function beforeModifyPosition(
-        address, /* sender **/
-        PoolKey calldata key,
-        IPoolManager.ModifyPositionParams calldata, /* params **/
-        bytes calldata hookData
-    ) external override returns (bytes4) {
-        return _executeAction(key, hookData, IHooks.beforeModifyPosition.selector);
-    }
-
-    function _executeAction(PoolKey memory key, bytes calldata hookData, bytes4 selector) internal returns (bytes4) {
-        if (hookData.length == 0) {
-            // We have re-entered the hook or we are initializing liquidity in the pool before testing the lock actions.
-            return selector;
-        }
-        (uint256 amount, LockAction action) = abi.decode(hookData, (uint256, LockAction));
-
-        // These actions just use some hardcoded parameters.
-        if (action == LockAction.Mint) {
-            manager.mint(key.currency1, address(this), amount);
-        } else if (action == LockAction.Take) {
-            manager.take(key.currency1, address(this), amount);
-        } else if (action == LockAction.Donate) {
-            manager.donate(key, amount, amount, new bytes(0));
-        } else if (action == LockAction.Swap) {
-            manager.swap(
-                key,
-                IPoolManager.SwapParams({
-                    zeroForOne: true,
-                    amountSpecified: int256(amount),
-                    sqrtPriceLimitX96: TickMath.MIN_SQRT_RATIO + 1
-                }),
-                new bytes(0)
-            );
-        } else if (action == LockAction.ModifyPosition) {
-            manager.modifyPosition(
-                key,
-                IPoolManager.ModifyPositionParams({tickLower: -60, tickUpper: 60, liquidityDelta: int256(amount)}),
-                new bytes(0)
-            );
-        } else if (action == LockAction.NoOp) {
-            assertEq(address(manager.getCurrentHook()), address(this));
-            return Hooks.NO_OP_SELECTOR;
-        } else if (action == LockAction.Burn) {
-            manager.burn(key.currency1, amount);
-        } else if (action == LockAction.Settle) {
-            manager.take(key.currency1, address(this), amount);
-            assertEq(MockERC20(Currency.unwrap(key.currency1)).balanceOf(address(this)), amount);
-            assertEq(manager.getLockNonzeroDeltaCount(), 1);
-            MockERC20(Currency.unwrap(key.currency1)).transfer(address(manager), amount);
-            manager.settle(key.currency1);
-            assertEq(manager.getLockNonzeroDeltaCount(), 0);
-        } else if (action == LockAction.Initialize) {
-            PoolKey memory newKey = PoolKey({
-                currency0: key.currency0,
-                currency1: key.currency1,
-                fee: Constants.FEE_LOW,
-                tickSpacing: 60,
-                hooks: IHooks(address(0))
-            });
-            manager.initialize(newKey, Constants.SQRT_RATIO_1_2, new bytes(0));
-        } else {
-            revert InvalidAction();
-        }
-
-        return selector;
-    }
-}
-
-// Hook that can access the lock.
-// Also has the ability to call out to another hook or pool.
-contract AccessLockHook2 is Test, BaseTestHooks {
-    IPoolManager manager;
-
-    error IncorrectHookSet();
-
-    constructor(IPoolManager _manager) {
-        manager = _manager;
-    }
-
-    function beforeModifyPosition(
-        address sender,
-        PoolKey calldata key,
-        IPoolManager.ModifyPositionParams calldata params,
-        bytes calldata hookData
-    ) external override returns (bytes4) {
-        if (address(manager.getCurrentHook()) != address(this)) {
-            revert IncorrectHookSet();
-        }
-
-        (bool shouldCallHook, PoolKey memory key2) = abi.decode(hookData, (bool, PoolKey));
-
-        if (shouldCallHook) {
-            // Should revert.
-            bytes memory hookData2 = abi.encode(100, AccessLockHook.LockAction.Mint);
-            IHooks(key2.hooks).beforeModifyPosition(sender, key, params, hookData2); // params dont really matter, just want to tell the other hook to do a mint action, but will revert
-        } else {
-            // Should succeed and should NOT set the current hook to key2.hooks.
-            // The permissions should remain to THIS hook during this lock.
-            manager.modifyPosition(key2, params, new bytes(0));
-
-            if (address(manager.getCurrentHook()) != address(this)) {
-                revert IncorrectHookSet();
-            }
-            // Should succeed.
-            manager.mint(key.currency1, address(this), 10);
-        }
-        return IHooks.beforeModifyPosition.selector;
-    }
-}
-
-// Reenters the PoolManager to donate and asserts currentHook is set and unset correctly throughout the popping and pushing of locks.
-contract AccessLockHook3 is Test, ILockCallback, BaseTestHooks {
-    IPoolManager manager;
-    // The pool to donate to in the nested lock.
-    // Ensure this has balance of currency0.abi
-    PoolKey key;
-
-    constructor(IPoolManager _manager) {
-        manager = _manager;
-    }
-
-    // Instead of passing through key all the way to the nested lock, just save it.
-    function setKey(PoolKey memory _key) external {
-        key = _key;
-    }
-
-    function beforeModifyPosition(
-        address, /* sender **/
-        PoolKey calldata, /* key **/
-        IPoolManager.ModifyPositionParams calldata, /* params **/
-        bytes calldata /* hookData **/
-    ) external override returns (bytes4) {
-        assertEq(address(manager.getCurrentHook()), address(this));
-        manager.lock(address(this), abi.encode(true));
-        assertEq(address(manager.getCurrentHook()), address(this));
-        manager.lock(address(this), abi.encode(false));
-        assertEq(address(manager.getCurrentHook()), address(this));
-        return IHooks.beforeModifyPosition.selector;
-    }
-
-    function lockAcquired(address caller, bytes memory data) external returns (bytes memory) {
-        require(caller == address(this));
-        assertEq(manager.getLockLength(), 2);
-        assertEq(address(manager.getCurrentHook()), address(0));
-
-        (bool isFirstLock) = abi.decode(data, (bool));
-        if (isFirstLock) {
-            manager.donate(key, 10, 0, new bytes(0));
-            assertEq(address(manager.getCurrentHook()), address(key.hooks));
-            MockERC20(Currency.unwrap(key.currency0)).transfer(address(manager), 10);
-            manager.settle(key.currency0);
-        }
-        return data;
-    }
-}
-
-contract AccessLockFeeHook is Test, BaseTestHooks {
-    IPoolManager manager;
-
-    uint256 constant WITHDRAWAL_FEE_BIPS = 40; // 40/10000 = 0.4%
-    uint256 constant SWAP_FEE_BIPS = 55; // 55/10000 = 0.55%
-    uint256 constant TOTAL_BIPS = 10000;
-
-    constructor(IPoolManager _manager) {
-        manager = _manager;
-    }
-
-    function afterModifyPosition(
-        address, /* sender **/
-        PoolKey calldata key,
-        IPoolManager.ModifyPositionParams calldata, /* params **/
-        BalanceDelta delta,
-        bytes calldata /* hookData **/
-    ) external override returns (bytes4) {
-        int128 amount0 = delta.amount0();
-        int128 amount1 = delta.amount1();
-
-        // positive delta => user owes money => liquidity addition
-        if (amount0 >= 0 && amount1 >= 0) return IHooks.afterModifyPosition.selector;
-
-        // negative delta => user is owed money => liquidity withdrawal
-        uint256 amount0Fee = uint128(-amount0) * WITHDRAWAL_FEE_BIPS / TOTAL_BIPS;
-        uint256 amount1Fee = uint128(-amount1) * WITHDRAWAL_FEE_BIPS / TOTAL_BIPS;
-
-        manager.take(key.currency0, address(this), amount0Fee);
-        manager.take(key.currency1, address(this), amount1Fee);
-
-        return IHooks.afterModifyPosition.selector;
-    }
-
-    function afterSwap(
-        address, /* sender **/
-        PoolKey calldata key,
-        IPoolManager.SwapParams calldata params,
-        BalanceDelta delta,
-        bytes calldata /* hookData **/
-    ) external override returns (bytes4) {
-        int128 amount0 = delta.amount0();
-        int128 amount1 = delta.amount1();
-
-        // fee on output token - output delta will be negative
-        (Currency feeCurrency, uint256 outputAmount) =
-            (params.zeroForOne) ? (key.currency1, uint128(-amount1)) : (key.currency0, uint128(-amount0));
-
-        uint256 feeAmount = outputAmount * SWAP_FEE_BIPS / TOTAL_BIPS;
-
-        manager.take(feeCurrency, address(this), feeAmount);
-
-        return IHooks.afterSwap.selector;
-    }
-}
diff --git a/src/test/EmptyTestHooks.sol b/src/test/EmptyTestHooks.sol
index 6e8f9fc3f..1bfbe8097 100644
--- a/src/test/EmptyTestHooks.sol
+++ b/src/test/EmptyTestHooks.sol
@@ -21,8 +21,7 @@ contract EmptyTestHooks is IHooks {
                 afterSwap: true,
                 beforeDonate: true,
                 afterDonate: true,
-                noOp: true,
-                accessLock: true
+                noOp: true
             })
         );
     }
diff --git a/src/test/NoOpTestHooks.sol b/src/test/NoOpTestHooks.sol
index 5c5dd8a1d..4aa6dc241 100644
--- a/src/test/NoOpTestHooks.sol
+++ b/src/test/NoOpTestHooks.sol
@@ -20,8 +20,7 @@ contract NoOpTestHooks is BaseTestHooks {
                 afterSwap: false,
                 beforeDonate: true,
                 afterDonate: false,
-                noOp: true,
-                accessLock: false
+                noOp: true
             })
         );
     }
diff --git a/src/test/PoolDonateTest.sol b/src/test/PoolDonateTest.sol
index efbbd6176..a6b2eac42 100644
--- a/src/test/PoolDonateTest.sol
+++ b/src/test/PoolDonateTest.sol
@@ -59,13 +59,11 @@ contract PoolDonateTest is PoolTestBase, Test {
         (,, uint256 reserveAfter0, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender);
         (,, uint256 reserveAfter1, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender);
 
-        if (!data.key.hooks.hasPermission(Hooks.ACCESS_LOCK_FLAG)) {
-            assertEq(reserveBefore0, reserveAfter0);
-            assertEq(reserveBefore1, reserveAfter1);
-            if (!data.key.hooks.hasPermission(Hooks.NO_OP_FLAG)) {
-                assertEq(deltaAfter0, int256(data.amount0));
-                assertEq(deltaAfter1, int256(data.amount1));
-            }
+        assertEq(reserveBefore0, reserveAfter0);
+        assertEq(reserveBefore1, reserveAfter1);
+        if (!data.key.hooks.hasPermission(Hooks.NO_OP_FLAG)) {
+            assertEq(deltaAfter0, int256(data.amount0));
+            assertEq(deltaAfter1, int256(data.amount1));
         }
 
         if (delta == BalanceDeltaLibrary.MAXIMUM_DELTA) {
diff --git a/src/test/PoolInitializeTest.sol b/src/test/PoolInitializeTest.sol
index 772ae5a85..081a1293a 100644
--- a/src/test/PoolInitializeTest.sol
+++ b/src/test/PoolInitializeTest.sol
@@ -44,17 +44,9 @@ contract PoolInitializeTest is Test, PoolTestBase {
         int256 delta1 = manager.currencyDelta(address(this), data.key.currency1);
         uint256 nonZeroDC = manager.getLockNonzeroDeltaCount();
 
-        if (!data.key.hooks.hasPermission(Hooks.ACCESS_LOCK_FLAG)) {
-            assertEq(delta0, 0, "delta0");
-            assertEq(delta1, 0, "delta1");
-            assertEq(nonZeroDC, 0, "NonzeroDeltaCount");
-        } else {
-            // settle deltas
-            if (delta0 > 0) _settle(data.key.currency0, data.sender, int128(delta0), true);
-            if (delta1 > 0) _settle(data.key.currency1, data.sender, int128(delta1), true);
-            if (delta0 < 0) _take(data.key.currency0, data.sender, int128(delta0), true);
-            if (delta1 < 0) _take(data.key.currency1, data.sender, int128(delta1), true);
-        }
+        assertEq(delta0, 0, "delta0");
+        assertEq(delta1, 0, "delta1");
+        assertEq(nonZeroDC, 0, "NonzeroDeltaCount");
 
         return abi.encode(tick);
     }
diff --git a/src/test/PoolModifyPositionTest.sol b/src/test/PoolModifyPositionTest.sol
index 0a5852529..866768298 100644
--- a/src/test/PoolModifyPositionTest.sol
+++ b/src/test/PoolModifyPositionTest.sol
@@ -52,15 +52,12 @@ contract PoolModifyPositionTest is Test, PoolTestBase {
         (,,, int256 delta0) = _fetchBalances(data.key.currency0, data.sender);
         (,,, int256 delta1) = _fetchBalances(data.key.currency1, data.sender);
 
-        // These assertions only apply in non lock-accessing pools.
-        if (!data.key.hooks.hasPermission(Hooks.ACCESS_LOCK_FLAG)) {
-            if (data.params.liquidityDelta > 0) {
-                assert(delta0 > 0 || delta1 > 0 || data.key.hooks.hasPermission(Hooks.NO_OP_FLAG));
-                assert(!(delta0 < 0 || delta1 < 0));
-            } else {
-                assert(delta0 < 0 || delta1 < 0 || data.key.hooks.hasPermission(Hooks.NO_OP_FLAG));
-                assert(!(delta0 > 0 || delta1 > 0));
-            }
+        if (data.params.liquidityDelta > 0) {
+            assert(delta0 > 0 || delta1 > 0 || data.key.hooks.hasPermission(Hooks.NO_OP_FLAG));
+            assert(!(delta0 < 0 || delta1 < 0));
+        } else {
+            assert(delta0 < 0 || delta1 < 0 || data.key.hooks.hasPermission(Hooks.NO_OP_FLAG));
+            assert(!(delta0 > 0 || delta1 > 0));
         }
 
         if (delta0 > 0) _settle(data.key.currency0, data.sender, int128(delta0), true);
diff --git a/src/test/PoolSwapTest.sol b/src/test/PoolSwapTest.sol
index 872720be3..8e568466f 100644
--- a/src/test/PoolSwapTest.sol
+++ b/src/test/PoolSwapTest.sol
@@ -68,33 +68,29 @@ contract PoolSwapTest is Test, PoolTestBase {
         (,, uint256 reserveAfter0, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender);
         (,, uint256 reserveAfter1, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender);
 
-        if (!data.key.hooks.hasPermission(Hooks.ACCESS_LOCK_FLAG)) {
-            // Hanndle assertions when the hook cannot access the lock.
-            // IE if the hook can access the lock, the reserves before and after are not necessarily the same. Hook can "take".
-            assertEq(reserveBefore0, reserveAfter0);
-            assertEq(reserveBefore1, reserveAfter1);
-
-            if (!data.key.hooks.hasPermission(Hooks.NO_OP_FLAG)) {
-                if (data.params.zeroForOne) {
-                    if (data.params.amountSpecified > 0) {
-                        // exact input, 0 for 1
-                        assertEq(deltaAfter0, data.params.amountSpecified);
-                        assert(deltaAfter1 < 0);
-                    } else {
-                        // exact output, 0 for 1
-                        assert(deltaAfter0 > 0);
-                        assertEq(deltaAfter1, data.params.amountSpecified);
-                    }
+        assertEq(reserveBefore0, reserveAfter0);
+        assertEq(reserveBefore1, reserveAfter1);
+
+        if (!data.key.hooks.hasPermission(Hooks.NO_OP_FLAG)) {
+            if (data.params.zeroForOne) {
+                if (data.params.amountSpecified > 0) {
+                    // exact input, 0 for 1
+                    assertEq(deltaAfter0, data.params.amountSpecified);
+                    assert(deltaAfter1 < 0);
                 } else {
-                    if (data.params.amountSpecified > 0) {
-                        // exact input, 1 for 0
-                        assertEq(deltaAfter1, data.params.amountSpecified);
-                        assert(deltaAfter0 < 0);
-                    } else {
-                        // exact output, 1 for 0
-                        assert(deltaAfter1 > 0);
-                        assertEq(deltaAfter0, data.params.amountSpecified);
-                    }
+                    // exact output, 0 for 1
+                    assert(deltaAfter0 > 0);
+                    assertEq(deltaAfter1, data.params.amountSpecified);
+                }
+            } else {
+                if (data.params.amountSpecified > 0) {
+                    // exact input, 1 for 0
+                    assertEq(deltaAfter1, data.params.amountSpecified);
+                    assert(deltaAfter0 < 0);
+                } else {
+                    // exact output, 1 for 0
+                    assert(deltaAfter1 > 0);
+                    assertEq(deltaAfter0, data.params.amountSpecified);
                 }
             }
         }
diff --git a/test/AccessLock.t.sol b/test/AccessLock.t.sol
deleted file mode 100644
index 82ea2270f..000000000
--- a/test/AccessLock.t.sol
+++ /dev/null
@@ -1,853 +0,0 @@
-// SPDX-License-Identifier: UNLICENSED
-pragma solidity ^0.8.20;
-
-import {Test} from "forge-std/Test.sol";
-import {AccessLockHook, AccessLockHook2, AccessLockHook3, AccessLockFeeHook} from "../src/test/AccessLockHook.sol";
-import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
-import {PoolModifyPositionTest} from "../src/test/PoolModifyPositionTest.sol";
-import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
-import {PoolDonateTest} from "../src/test/PoolDonateTest.sol";
-import {Constants} from "./utils/Constants.sol";
-import {PoolKey} from "../src/types/PoolKey.sol";
-import {Deployers} from "./utils/Deployers.sol";
-import {Currency, CurrencyLibrary} from "../src/types/Currency.sol";
-import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
-import {Hooks} from "../src/libraries/Hooks.sol";
-import {IHooks} from "../src/interfaces/IHooks.sol";
-import {BalanceDelta, BalanceDeltaLibrary} from "../src/types/BalanceDelta.sol";
-import {Pool} from "../src/libraries/Pool.sol";
-import {TickMath} from "../src/libraries/TickMath.sol";
-import {PoolIdLibrary} from "../src/types/PoolId.sol";
-
-contract AccessLockTest is Test, Deployers {
-    using Pool for Pool.State;
-    using CurrencyLibrary for Currency;
-    using PoolIdLibrary for PoolKey;
-    using BalanceDeltaLibrary for BalanceDelta;
-
-    AccessLockHook accessLockHook;
-    AccessLockHook noAccessLockHook;
-    AccessLockHook2 accessLockHook2;
-    AccessLockHook3 accessLockHook3;
-    AccessLockHook accessLockNoOpHook;
-    AccessLockFeeHook accessLockFeeHook;
-
-    // global for stack too deep errors
-    BalanceDelta delta;
-
-    uint128 amount = 1e18;
-
-    function setUp() public {
-        // Initialize managers and routers.
-        deployFreshManagerAndRouters();
-        (currency0, currency1) = deployMintAndApprove2Currencies();
-
-        // Create AccessLockHook.
-        address accessLockAddress = address(
-            uint160(
-                Hooks.ACCESS_LOCK_FLAG | Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_MODIFY_POSITION_FLAG
-                    | Hooks.BEFORE_DONATE_FLAG
-            )
-        );
-        deployCodeTo("AccessLockHook.sol:AccessLockHook", abi.encode(manager), accessLockAddress);
-        accessLockHook = AccessLockHook(accessLockAddress);
-
-        (key,) =
-            initPool(currency0, currency1, IHooks(accessLockAddress), Constants.FEE_MEDIUM, SQRT_RATIO_1_1, ZERO_BYTES);
-
-        // Create AccessLockHook2.
-        address accessLockAddress2 = address(uint160(Hooks.ACCESS_LOCK_FLAG | Hooks.BEFORE_MODIFY_POSITION_FLAG));
-        deployCodeTo("AccessLockHook.sol:AccessLockHook2", abi.encode(manager), accessLockAddress2);
-        accessLockHook2 = AccessLockHook2(accessLockAddress2);
-
-        // Create AccessLockHook3.
-        address accessLockAddress3 = address(
-            (uint160(makeAddr("hook3")) << 10) >> 10
-                | (uint160(Hooks.ACCESS_LOCK_FLAG | Hooks.BEFORE_MODIFY_POSITION_FLAG))
-        );
-        deployCodeTo("AccessLockHook.sol:AccessLockHook3", abi.encode(manager), accessLockAddress3);
-        accessLockHook3 = AccessLockHook3(accessLockAddress3);
-
-        // Create NoAccessLockHook.
-        address noAccessLockHookAddress = address(uint160(Hooks.BEFORE_MODIFY_POSITION_FLAG));
-        deployCodeTo("AccessLockHook.sol:AccessLockHook", abi.encode(manager), noAccessLockHookAddress);
-        noAccessLockHook = AccessLockHook(noAccessLockHookAddress);
-
-        // Create AccessLockHook with NoOp.
-        address accessLockNoOpHookAddress = address(
-            uint160(
-                Hooks.NO_OP_FLAG | Hooks.ACCESS_LOCK_FLAG | Hooks.BEFORE_INITIALIZE_FLAG | Hooks.BEFORE_SWAP_FLAG
-                    | Hooks.BEFORE_MODIFY_POSITION_FLAG | Hooks.BEFORE_DONATE_FLAG
-            )
-        );
-        deployCodeTo("AccessLockHook.sol:AccessLockHook", abi.encode(manager), accessLockNoOpHookAddress);
-        accessLockNoOpHook = AccessLockHook(accessLockNoOpHookAddress);
-
-        // Create AccessLockFeeHook
-        address accessLockFeeHookAddress =
-            address(uint160(Hooks.ACCESS_LOCK_FLAG | Hooks.AFTER_SWAP_FLAG | Hooks.AFTER_MODIFY_POSITION_FLAG));
-        deployCodeTo("AccessLockHook.sol:AccessLockFeeHook", abi.encode(manager), accessLockFeeHookAddress);
-        accessLockFeeHook = AccessLockFeeHook(accessLockFeeHookAddress);
-    }
-
-    function test_onlyByLocker_revertsForNoAccessLockPool() public {
-        (PoolKey memory keyWithoutAccessLockFlag,) =
-            initPool(currency0, currency1, IHooks(noAccessLockHook), Constants.FEE_MEDIUM, SQRT_RATIO_1_1, ZERO_BYTES);
-
-        vm.expectRevert(
-            abi.encodeWithSelector(
-                IPoolManager.LockedBy.selector, address(modifyPositionRouter), address(noAccessLockHook)
-            )
-        );
-        modifyPositionRouter.modifyPosition(
-            keyWithoutAccessLockFlag,
-            IPoolManager.ModifyPositionParams({tickLower: 0, tickUpper: 60, liquidityDelta: 0}),
-            abi.encode(10, AccessLockHook.LockAction.Mint) // attempts a mint action that should revert
-        );
-    }
-    /**
-     *
-     *
-     * The following test suite tests that appropriate hooks can call
-     *  every function gated by the `onlyByLocker` modifier.
-     *  We call these "LockActions".
-     *  LockActions:
-     *  - Mint
-     *  - Take
-     *  - Swap
-     *  - ModifyPosition
-     *  - Donate
-     *  - Burn
-     *  - Settle
-     *  - Initialize
-     * Each of these calls is then tested from every callback after the
-     * currentHook gets set (beforeModifyPosition, beforeSwap, and beforeDonate).
-     *
-     */
-
-    /**
-     *
-     * BEFORE MODIFY POSITION TESTS
-     *
-     */
-    function test_beforeModifyPosition_mint_succeedsWithAccessLock() public {
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        delta = modifyPositionRouter.modifyPosition(
-            key, IPoolManager.ModifyPositionParams(0, 60, 1e18), abi.encode(amount, AccessLockHook.LockAction.Mint)
-        );
-
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        assertEq(balanceOfBefore0 - balanceOfAfter0, uint256(uint128(delta.amount0())));
-        // The balance of our contract should be from the modifyPositionRouter (delta) AND the hook (amount).
-        assertEq(balanceOfBefore1 - balanceOfAfter1, uint256(amount + uint256(uint128(delta.amount1()))));
-
-        assertEq(manager.balanceOf(address(accessLockHook), currency1), amount);
-    }
-
-    function test_beforeModifyPosition_take_succeedsWithAccessLock() public {
-        // Add liquidity so there is something to take.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        // Hook only takes currency 1 rn.
-        delta = modifyPositionRouter.modifyPosition(
-            key, IPoolManager.ModifyPositionParams(-60, 60, 1e18), abi.encode(amount, AccessLockHook.LockAction.Take)
-        );
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        assertEq(balanceOfBefore0 - balanceOfAfter0, uint256(uint128(delta.amount0())));
-        // The balance of our contract should be from the modifyPositionRouter (delta) AND the hook (amount).
-        assertEq(balanceOfBefore1 - balanceOfAfter1, uint256(amount + uint256(uint128(delta.amount1()))));
-        assertEq(MockERC20(Currency.unwrap(currency1)).balanceOf(address(accessLockHook)), amount);
-    }
-
-    function test_beforeModifyPosition_swap_succeedsWithAccessLock() public {
-        // Add liquidity so there is something to swap over.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        // Essentially "no-op"s the modifyPosition call and executes a swap before hand, applying the deltas from the swap to the locker.
-        modifyPositionRouter.modifyPosition(
-            key, IPoolManager.ModifyPositionParams(-120, 120, 0), abi.encode(amount, AccessLockHook.LockAction.Swap)
-        );
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        // Balance decreases because we are swapping currency0 for currency1.
-        assertLt(balanceOfAfter0, balanceOfBefore0);
-        // Balance should be greater in currency1.
-        assertGt(balanceOfAfter1, balanceOfBefore1);
-    }
-
-    function test_beforeModifyPosition_modifyPosition_succeedsWithAccessLock() public {
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams(-120, 120, 1e18),
-            abi.encode(amount, AccessLockHook.LockAction.ModifyPosition)
-        );
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        // Should have less balance in both currencies.
-        assertLt(balanceOfAfter0, balanceOfBefore0);
-        assertLt(balanceOfAfter1, balanceOfBefore1);
-    }
-
-    function test_beforeModifyPosition_donate_succeedsWithAccessLock() public {
-        // Add liquidity so there is a position to receive fees.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams(-120, 120, 1e18),
-            abi.encode(amount, AccessLockHook.LockAction.Donate)
-        );
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        // Should have less balance in both currencies.
-        assertLt(balanceOfAfter0, balanceOfBefore0);
-        assertLt(balanceOfAfter1, balanceOfBefore1);
-    }
-
-    function test_beforeModifyPosition_burn_succeedsWithAccessLock() public {
-        // Add liquidity so there is a position to swap over.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        delta = swapRouter.swap(
-            key,
-            IPoolManager.SwapParams(true, 10000, TickMath.MIN_SQRT_RATIO + 1),
-            PoolSwapTest.TestSettings({withdrawTokens: false, settleUsingTransfer: true, currencyAlreadySent: false}),
-            ZERO_BYTES
-        );
-
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 amount1 = uint256(uint128(-delta.amount1()));
-        // We have some balance in the manager.
-        assertEq(manager.balanceOf(address(this), currency1), amount1);
-        manager.transfer(address(key.hooks), currency1, amount1);
-        assertEq(manager.balanceOf(address(key.hooks), currency1), amount1);
-
-        modifyPositionRouter.modifyPosition(
-            key, IPoolManager.ModifyPositionParams(-120, 120, 0), abi.encode(amount1, AccessLockHook.LockAction.Burn)
-        );
-
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        assertEq(balanceOfAfter1, balanceOfBefore1 + amount1);
-    }
-
-    function test_beforeModifyPosition_settle_succeedsWithAccessLock() public {
-        // Add liquidity so there is something to take.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        // Assertions in the hook. Takes and then settles within the hook.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams(-120, 120, 1e18),
-            abi.encode(amount, AccessLockHook.LockAction.Settle)
-        );
-    }
-
-    function test_beforeModifyPosition_initialize_succeedsWithAccessLock() public {
-        // The hook intitializes a new pool with the new key at Constants.SQRT_RATIO_1_2;
-        modifyPositionRouter.modifyPosition(
-            key, IPoolManager.ModifyPositionParams(-120, 120, 1e18), abi.encode(0, AccessLockHook.LockAction.Initialize)
-        );
-
-        PoolKey memory newKey = PoolKey({
-            currency0: key.currency0,
-            currency1: key.currency1,
-            fee: Constants.FEE_LOW,
-            tickSpacing: 60,
-            hooks: IHooks(address(0))
-        });
-        (Pool.Slot0 memory slot0,,,) = manager.pools(newKey.toId());
-
-        assertEq(slot0.sqrtPriceX96, Constants.SQRT_RATIO_1_2);
-    }
-
-    /**
-     *
-     * BEFORE SWAP TESTS
-     *
-     */
-
-    function test_beforeSwap_mint_succeedsWithAccessLock() public {
-        // Add liquidity so there is something to swap against.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        // Small amount to swap (like NoOp). This way we can expect balances to just be from the hook applied delta.
-        delta = swapRouter.swap(
-            key,
-            IPoolManager.SwapParams(true, 1, TickMath.MIN_SQRT_RATIO + 1),
-            PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false}),
-            abi.encode(amount, AccessLockHook.LockAction.Mint)
-        );
-
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        assertEq(balanceOfBefore0 - balanceOfAfter0, uint256(uint128(delta.amount0())));
-        // The balance of our contract should be from the modifyPositionRouter (delta) AND the hook (amount).
-        assertEq(balanceOfBefore1 - balanceOfAfter1, uint256(amount + uint256(uint128(delta.amount1()))));
-
-        assertEq(manager.balanceOf(address(accessLockHook), currency1), amount);
-    }
-
-    function test_beforeSwap_take_succeedsWithAccessLock() public {
-        // Add liquidity so there is something to take.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        // Hook only takes currency 1 rn.
-        // Use small amount to NoOp.
-        delta = swapRouter.swap(
-            key,
-            IPoolManager.SwapParams(true, 1, TickMath.MIN_SQRT_RATIO + 1),
-            PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false}),
-            abi.encode(amount, AccessLockHook.LockAction.Take)
-        );
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        assertEq(balanceOfBefore0 - balanceOfAfter0, uint256(uint128(delta.amount0())));
-        // The balance of our contract should be from the modifyPositionRouter (delta) AND the hook (amount).
-        assertEq(balanceOfBefore1 - balanceOfAfter1, uint256(amount + uint256(uint128(delta.amount1()))));
-        assertEq(MockERC20(Currency.unwrap(currency1)).balanceOf(address(accessLockHook)), amount);
-    }
-
-    function test_beforeSwap_swap_succeedsWithAccessLock() public {
-        // Add liquidity so there is something to swap over.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        swapRouter.swap(
-            key,
-            // Use small amounts so that the zeroForOne swap is larger
-            IPoolManager.SwapParams(false, 1, TickMath.MAX_SQRT_RATIO - 1),
-            PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false}),
-            abi.encode(amount, AccessLockHook.LockAction.Swap)
-        );
-
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        // The larger swap is zeroForOne
-        // Balance decreases because we are swapping currency0 for currency1.
-        assertLt(balanceOfAfter0, balanceOfBefore0);
-        // Balance should be greater in currency1.
-        assertGt(balanceOfAfter1, balanceOfBefore1);
-    }
-
-    function test_beforeSwap_modifyPosition_succeedsWithAccessLock() public {
-        // Add liquidity so there is something to swap over.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        // Make the swap amount small (like a NoOp).
-        swapRouter.swap(
-            key,
-            IPoolManager.SwapParams(true, 1, TickMath.MIN_SQRT_RATIO + 1),
-            PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false}),
-            abi.encode(amount, AccessLockHook.LockAction.ModifyPosition)
-        );
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        // Should have less balance in both currencies.
-        assertLt(balanceOfAfter0, balanceOfBefore0);
-        assertLt(balanceOfAfter1, balanceOfBefore1);
-    }
-
-    function test_beforeSwap_donate_succeedsWithAccessLock() public {
-        // Add liquidity so there is a position to receive fees.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        // Make the swap amount small (like a NoOp).
-        swapRouter.swap(
-            key,
-            IPoolManager.SwapParams(true, 1, TickMath.MIN_SQRT_RATIO + 1),
-            PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false}),
-            abi.encode(amount, AccessLockHook.LockAction.Donate)
-        );
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        // Should have less balance in both currencies.
-        assertLt(balanceOfAfter0, balanceOfBefore0);
-        assertLt(balanceOfAfter1, balanceOfBefore1);
-    }
-
-    /**
-     *
-     * BEFORE DONATE TESTS
-     *
-     */
-
-    function test_beforeDonate_mint_succeedsWithAccessLock() public {
-        // Add liquidity so there is something to donate to.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        delta = donateRouter.donate(key, 1e18, 1e18, abi.encode(amount, AccessLockHook.LockAction.Mint));
-
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        assertEq(balanceOfBefore0 - balanceOfAfter0, uint256(uint128(delta.amount0())));
-        // The balance of our contract should be from the donateRouter (delta) AND the hook (amount).
-        assertEq(balanceOfBefore1 - balanceOfAfter1, uint256(amount + uint256(uint128(delta.amount1()))));
-
-        assertEq(manager.balanceOf(address(accessLockHook), currency1), amount);
-    }
-
-    function test_beforeDonate_take_succeedsWithAccessLock() public {
-        // Add liquidity so there is something to take.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        // Hook only takes currency 1 rn.
-        delta = donateRouter.donate(key, 1e18, 1e18, abi.encode(amount, AccessLockHook.LockAction.Take));
-        // Take applies a positive delta in currency1.
-        // Donate applies a positive delta in currency0 and currency1.
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        assertEq(balanceOfBefore0 - balanceOfAfter0, uint256(uint128(delta.amount0())));
-        // The balance of our contract should be from the modifyPositionRouter (delta) AND the hook (amount).
-        assertEq(balanceOfBefore1 - balanceOfAfter1, uint256(amount + uint256(uint128(delta.amount1()))));
-        assertEq(MockERC20(Currency.unwrap(currency1)).balanceOf(address(accessLockHook)), amount);
-    }
-
-    function test_beforeDonate_swap_succeedsWithAccessLock() public {
-        // Add liquidity so there is something to swap over.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        // Donate small amounts (NoOp) so we know the swap amount dominates.
-        donateRouter.donate(key, 1, 1, abi.encode(amount, AccessLockHook.LockAction.Swap));
-
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        // Balance of currency0 decreases bc we 1) donate and 2) swap zeroForOne.
-        assertLt(balanceOfAfter0, balanceOfBefore0);
-        // Since the donate amount is small, and we swapped zeroForOne, we expect balance of currency1 to increase.
-        assertGt(balanceOfAfter1, balanceOfBefore1);
-    }
-
-    function test_beforeDonate_modifyPosition_succeedsWithAccessLock() public {
-        // Add liquidity so there is something to donate to.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        donateRouter.donate(key, 1e18, 1e18, abi.encode(amount, AccessLockHook.LockAction.ModifyPosition));
-
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        // Should have less balance in both currencies from adding liquidity AND donating.
-        assertLt(balanceOfAfter0, balanceOfBefore0);
-        assertLt(balanceOfAfter1, balanceOfBefore1);
-    }
-
-    function test_beforeDonate_donate_succeedsWithAccessLock() public {
-        // Add liquidity so there is a position to receive fees.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        // Make the swap amount small (like a NoOp).
-        donateRouter.donate(key, 1e18, 1e18, abi.encode(amount, AccessLockHook.LockAction.Donate));
-
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        // Should have less balance in both currencies.
-        assertLt(balanceOfAfter0, balanceOfBefore0);
-        assertLt(balanceOfAfter1, balanceOfBefore1);
-    }
-    /**
-     *
-     * BEFORE INITIALIZE TESTS
-     *
-     */
-
-    function test_beforeInitialize_mint_succeedsWithAccessLock() public {
-        PoolKey memory key1 = PoolKey({
-            currency0: currency0,
-            currency1: currency1,
-            fee: Constants.FEE_MEDIUM,
-            tickSpacing: 60,
-            hooks: IHooks(address(accessLockNoOpHook))
-        });
-
-        initializeRouter.initialize(key1, SQRT_RATIO_1_1, abi.encode(amount, AccessLockHook.LockAction.Mint));
-
-        assertEq(manager.balanceOf(address(accessLockNoOpHook), currency1), amount);
-    }
-
-    function test_beforeInitialize_take_succeedsWithAccessLock() public {
-        PoolKey memory key1 = PoolKey({
-            currency0: currency0,
-            currency1: currency1,
-            fee: Constants.FEE_MEDIUM,
-            tickSpacing: 60,
-            hooks: IHooks(address(accessLockNoOpHook))
-        });
-
-        // Add liquidity to a different pool there is something to take.
-        modifyPositionRouter.modifyPosition(
-            key,
-            IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1000e18}),
-            ZERO_BYTES
-        );
-
-        initializeRouter.initialize(key1, SQRT_RATIO_1_1, abi.encode(amount, AccessLockHook.LockAction.Take));
-
-        assertEq(MockERC20(Currency.unwrap(currency1)).balanceOf(address(accessLockNoOpHook)), amount);
-    }
-
-    function test_beforeInitialize_swap_revertsOnPoolNotInitialized() public {
-        PoolKey memory key1 = PoolKey({
-            currency0: currency0,
-            currency1: currency1,
-            fee: Constants.FEE_MEDIUM,
-            tickSpacing: 60,
-            hooks: IHooks(address(accessLockNoOpHook))
-        });
-
-        vm.expectRevert(IPoolManager.PoolNotInitialized.selector);
-        initializeRouter.initialize(key1, SQRT_RATIO_1_1, abi.encode(amount, AccessLockHook.LockAction.Swap));
-    }
-
-    function test_beforeInitialize_modifyPosition_revertsOnPoolNotInitialized() public {
-        PoolKey memory key1 = PoolKey({
-            currency0: currency0,
-            currency1: currency1,
-            fee: Constants.FEE_MEDIUM,
-            tickSpacing: 60,
-            hooks: IHooks(address(accessLockNoOpHook))
-        });
-
-        vm.expectRevert(IPoolManager.PoolNotInitialized.selector);
-        initializeRouter.initialize(key1, SQRT_RATIO_1_1, abi.encode(amount, AccessLockHook.LockAction.ModifyPosition));
-    }
-
-    function test_beforeInitialize_donate_revertsOnPoolNotInitialized() public {
-        PoolKey memory key1 = PoolKey({
-            currency0: currency0,
-            currency1: currency1,
-            fee: Constants.FEE_MEDIUM,
-            tickSpacing: 60,
-            hooks: IHooks(address(accessLockNoOpHook))
-        });
-
-        vm.expectRevert(IPoolManager.PoolNotInitialized.selector);
-        initializeRouter.initialize(key1, SQRT_RATIO_1_1, abi.encode(amount, AccessLockHook.LockAction.Donate));
-    }
-
-    /**
-     *
-     * HOOK FEE TESTS
-     *
-     */
-
-    function test_hookFees_takesFeeOnWithdrawal() public {
-        (key,) = initPool(
-            currency0, currency1, IHooks(address(accessLockFeeHook)), Constants.FEE_MEDIUM, SQRT_RATIO_1_1, ZERO_BYTES
-        );
-
-        (uint256 userBalanceBefore0, uint256 poolBalanceBefore0, uint256 reservesBefore0) = _fetchBalances(currency0);
-        (uint256 userBalanceBefore1, uint256 poolBalanceBefore1, uint256 reservesBefore1) = _fetchBalances(currency1);
-
-        // add liquidity
-        delta = modifyPositionRouter.modifyPosition(key, LIQ_PARAMS, ZERO_BYTES);
-
-        (uint256 userBalanceAfter0, uint256 poolBalanceAfter0, uint256 reservesAfter0) = _fetchBalances(currency0);
-        (uint256 userBalanceAfter1, uint256 poolBalanceAfter1, uint256 reservesAfter1) = _fetchBalances(currency1);
-
-        assert(delta.amount0() > 0 && delta.amount1() > 0);
-        assertEq(userBalanceBefore0 - uint128(delta.amount0()), userBalanceAfter0, "addLiq user balance currency0");
-        assertEq(userBalanceBefore1 - uint128(delta.amount1()), userBalanceAfter1, "addLiq user balance currency1");
-        assertEq(poolBalanceBefore0 + uint128(delta.amount0()), poolBalanceAfter0, "addLiq pool balance currency0");
-        assertEq(poolBalanceBefore1 + uint128(delta.amount1()), poolBalanceAfter1, "addLiq pool balance currency1");
-        assertEq(reservesBefore0 + uint128(delta.amount0()), reservesAfter0, "addLiq reserves currency0");
-        assertEq(reservesBefore1 + uint128(delta.amount1()), reservesAfter1, "addLiq reserves currency1");
-
-        (userBalanceBefore0, poolBalanceBefore0, reservesBefore0) =
-            (userBalanceAfter0, poolBalanceAfter0, reservesAfter0);
-        (userBalanceBefore1, poolBalanceBefore1, reservesBefore1) =
-            (userBalanceAfter1, poolBalanceAfter1, reservesAfter1);
-
-        // remove liquidity, a 40 bip fee should be taken
-        LIQ_PARAMS.liquidityDelta *= -1;
-        delta = modifyPositionRouter.modifyPosition(key, LIQ_PARAMS, ZERO_BYTES);
-
-        (userBalanceAfter0, poolBalanceAfter0, reservesAfter0) = _fetchBalances(currency0);
-        (userBalanceAfter1, poolBalanceAfter1, reservesAfter1) = _fetchBalances(currency1);
-
-        assert(delta.amount0() < 0 && delta.amount1() < 0);
-
-        uint256 totalWithdraw0 = uint128(-delta.amount0()) - (uint128(-delta.amount0()) * 40 / 10000);
-        uint256 totalWithdraw1 = uint128(-delta.amount1()) - (uint128(-delta.amount1()) * 40 / 10000);
-
-        assertEq(userBalanceBefore0 + totalWithdraw0, userBalanceAfter0, "removeLiq user balance currency0");
-        assertEq(userBalanceBefore1 + totalWithdraw1, userBalanceAfter1, "removeLiq user balance currency1");
-        assertEq(poolBalanceBefore0 - uint128(-delta.amount0()), poolBalanceAfter0, "removeLiq pool balance currency0");
-        assertEq(poolBalanceBefore1 - uint128(-delta.amount1()), poolBalanceAfter1, "removeLiq pool balance currency1");
-        assertEq(reservesBefore0 - uint128(-delta.amount0()), reservesAfter0, "removeLiq reserves currency0");
-        assertEq(reservesBefore1 - uint128(-delta.amount1()), reservesAfter1, "removeLiq reserves currency1");
-    }
-
-    function test_hookFees_takesFeeOnInputOfSwap() public {
-        (key,) = initPool(
-            currency0, currency1, IHooks(address(accessLockFeeHook)), Constants.FEE_MEDIUM, SQRT_RATIO_1_1, ZERO_BYTES
-        );
-
-        // add liquidity
-        delta = modifyPositionRouter.modifyPosition(key, LIQ_PARAMS, ZERO_BYTES);
-
-        // now swap, with a hook fee of 55 bips
-        (uint256 userBalanceBefore0, uint256 poolBalanceBefore0, uint256 reservesBefore0) = _fetchBalances(currency0);
-        (uint256 userBalanceBefore1, uint256 poolBalanceBefore1, uint256 reservesBefore1) = _fetchBalances(currency1);
-
-        delta = swapRouter.swap(
-            key,
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100000, sqrtPriceLimitX96: SQRT_RATIO_1_2}),
-            PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false}),
-            ZERO_BYTES
-        );
-
-        assert(delta.amount0() > 0 && delta.amount1() < 0);
-
-        uint256 amountIn0 = uint128(delta.amount0());
-        uint256 userAmountOut1 = uint128(-delta.amount1()) - (uint128(-delta.amount1()) * 55 / 10000);
-
-        (uint256 userBalanceAfter0, uint256 poolBalanceAfter0, uint256 reservesAfter0) = _fetchBalances(currency0);
-        (uint256 userBalanceAfter1, uint256 poolBalanceAfter1, uint256 reservesAfter1) = _fetchBalances(currency1);
-
-        assertEq(userBalanceBefore0 - amountIn0, userBalanceAfter0, "swap user balance currency0");
-        assertEq(userBalanceBefore1 + userAmountOut1, userBalanceAfter1, "swap user balance currency1");
-        assertEq(poolBalanceBefore0 + amountIn0, poolBalanceAfter0, "swap pool balance currency0");
-        assertEq(poolBalanceBefore1 - uint128(-delta.amount1()), poolBalanceAfter1, "swap pool balance currency1");
-        assertEq(reservesBefore0 + amountIn0, reservesAfter0, "swap reserves currency0");
-        assertEq(reservesBefore1 - uint128(-delta.amount1()), reservesAfter1, "swap reserves currency1");
-    }
-
-    /**
-     *
-     * EDGE CASE TESTS
-     *
-     */
-
-    function test_onlyByLocker_revertsWhenHookIsNotCurrentHook() public {
-        // Call first access lock hook. Should succeed.
-        uint256 balanceOfBefore1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-        uint256 balanceOfBefore0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-
-        delta = modifyPositionRouter.modifyPosition(
-            key, IPoolManager.ModifyPositionParams(0, 60, 1e18), abi.encode(amount, AccessLockHook.LockAction.Mint)
-        );
-
-        uint256 balanceOfAfter0 = MockERC20(Currency.unwrap(currency0)).balanceOf(address(this));
-        uint256 balanceOfAfter1 = MockERC20(Currency.unwrap(currency1)).balanceOf(address(this));
-
-        assertEq(balanceOfBefore0 - balanceOfAfter0, uint256(uint128(delta.amount0())));
-        // The balance of our contract should be from the modifyPositionRouter (delta) AND the hook (amount).
-        assertEq(balanceOfBefore1 - balanceOfAfter1, uint256(amount + uint256(uint128(delta.amount1()))));
-
-        assertEq(manager.balanceOf(address(accessLockHook), currency1), amount);
-
-        assertEq(address(manager.getCurrentHook()), address(0));
-
-        (PoolKey memory keyAccessLockHook2,) =
-            initPool(currency0, currency1, IHooks(accessLockHook2), Constants.FEE_MEDIUM, SQRT_RATIO_1_1, ZERO_BYTES);
-
-        // Delegates the beforeModifyPosition call to the hook in `key` which tries to mint on manager
-        //  but reverts because hook in `key` is not the current hook.
-        vm.expectRevert(
-            abi.encodeWithSelector(
-                IPoolManager.LockedBy.selector, address(modifyPositionRouter), address(accessLockHook2)
-            )
-        );
-        delta = modifyPositionRouter.modifyPosition(
-            keyAccessLockHook2, IPoolManager.ModifyPositionParams(0, 60, 1e18), abi.encode(true, key)
-        );
-    }
-
-    function test_onlyByLocker_succeedsAfterHookMakesNestedCall() public {
-        (PoolKey memory keyWithNoHook,) =
-            initPool(currency0, currency1, IHooks(address(0)), Constants.FEE_MEDIUM, SQRT_RATIO_1_1, ZERO_BYTES);
-
-        (PoolKey memory keyAccessLockHook2,) =
-            initPool(currency0, currency1, IHooks(accessLockHook2), Constants.FEE_MEDIUM, SQRT_RATIO_1_1, ZERO_BYTES);
-
-        modifyPositionRouter.modifyPosition(
-            keyAccessLockHook2, IPoolManager.ModifyPositionParams(0, 60, 1e18), abi.encode(false, keyWithNoHook)
-        );
-        assertEq(manager.balanceOf(address(accessLockHook2), currency1), 10);
-    }
-
-    function test_onlyByLocker_revertsWhenThereIsNoOutsideLock() public {
-        modifyPositionRouter.modifyPosition(key, IPoolManager.ModifyPositionParams(0, 60, 1e18), ZERO_BYTES);
-        assertEq(address(manager.getCurrentHook()), address(0));
-
-        vm.expectRevert(abi.encodeWithSelector(IPoolManager.LockedBy.selector, address(0), address(0)));
-        vm.prank(address(key.hooks));
-        manager.modifyPosition(key, IPoolManager.ModifyPositionParams(0, 60, 1e18), ZERO_BYTES);
-    }
-
-    function test_getCurrentHook_isClearedAfterNestedLock() public {
-        // Create pool for AccessLockHook3.
-        (PoolKey memory keyAccessLockHook3,) =
-            initPool(currency0, currency1, IHooks(accessLockHook3), Constants.FEE_MEDIUM, SQRT_RATIO_1_1, ZERO_BYTES);
-        // Fund AccessLockHook3 with currency0.
-        MockERC20(Currency.unwrap(currency0)).transfer(address(accessLockHook3), 10);
-        assertEq(MockERC20(Currency.unwrap(currency0)).balanceOf(address(accessLockHook3)), 10);
-
-        // Create pool to donate 10 of currency0 to inside of AccessLockHook3. This means AccessLockHook3 must acquire a new lock and settle.
-        // The currentHook addresses are checked inside this nested lock.
-        (PoolKey memory _key,) =
-            initPool(currency0, currency1, IHooks(address(0)), Constants.FEE_MEDIUM, SQRT_RATIO_1_1, ZERO_BYTES);
-        // Add liquidity so that the AccessLockHook3 can donate to something.
-        modifyPositionRouter.modifyPosition(_key, IPoolManager.ModifyPositionParams(-60, 60, 10 * 10 ** 18), ZERO_BYTES);
-        accessLockHook3.setKey(_key);
-
-        // Asserts are in the AccessLockHook3.
-        modifyPositionRouter.modifyPosition(
-            keyAccessLockHook3, IPoolManager.ModifyPositionParams(0, 60, 1e18), ZERO_BYTES
-        );
-    }
-
-    function test_getCurrentHook_isClearedAfterNoOpOnAllHooks() public {
-        (PoolKey memory noOpKey,) =
-            initPool(currency0, currency1, IHooks(accessLockNoOpHook), Constants.FEE_MEDIUM, SQRT_RATIO_1_1, ZERO_BYTES);
-
-        // Assertions for current hook address in AccessLockHook and respective routers.
-        // beforeModifyPosition noOp
-        modifyPositionRouter.modifyPosition(
-            noOpKey,
-            IPoolManager.ModifyPositionParams({tickLower: 0, tickUpper: 60, liquidityDelta: 0}),
-            abi.encode(0, AccessLockHook.LockAction.NoOp)
-        );
-
-        // beforeDonate noOp
-        donateRouter.donate(noOpKey, 1e18, 1e18, abi.encode(0, AccessLockHook.LockAction.NoOp));
-
-        // beforeSwap noOp
-        swapRouter.swap(
-            noOpKey,
-            IPoolManager.SwapParams(true, 1, TickMath.MIN_SQRT_RATIO + 1),
-            PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false}),
-            abi.encode(0, AccessLockHook.LockAction.NoOp)
-        );
-    }
-
-    function _fetchBalances(Currency currency)
-        internal
-        view
-        returns (uint256 userBalance, uint256 poolBalance, uint256 reserves)
-    {
-        userBalance = currency.balanceOf(address(this));
-        poolBalance = currency.balanceOf(address(manager));
-        reserves = manager.reservesOf(currency);
-    }
-}
diff --git a/test/Hooks.t.sol b/test/Hooks.t.sol
index b6cc5d12a..5bc970ed1 100644
--- a/test/Hooks.t.sol
+++ b/test/Hooks.t.sol
@@ -19,7 +19,6 @@ import {Deployers} from "./utils/Deployers.sol";
 import {Fees} from "../src/Fees.sol";
 import {PoolId, PoolIdLibrary} from "../src/types/PoolId.sol";
 import {PoolKey} from "../src/types/PoolKey.sol";
-import {AccessLockHook} from "../src/test/AccessLockHook.sol";
 import {IERC20Minimal} from "../src/interfaces/external/IERC20Minimal.sol";
 import {BalanceDelta} from "../src/types/BalanceDelta.sol";
 
@@ -151,8 +150,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: false,
                 beforeDonate: false,
                 afterDonate: false,
-                noOp: false,
-                accessLock: false
+                noOp: false
             })
         );
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -164,7 +162,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressBeforeInitialize(uint160 addr) public {
@@ -182,8 +179,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: false,
                 beforeDonate: false,
                 afterDonate: false,
-                noOp: false,
-                accessLock: false
+                noOp: false
             })
         );
         assertTrue(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -195,7 +191,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressAfterInitialize(uint160 addr) public {
@@ -213,8 +208,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: false,
                 beforeDonate: false,
                 afterDonate: false,
-                noOp: false,
-                accessLock: false
+                noOp: false
             })
         );
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -226,7 +220,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressBeforeAndAfterInitialize(uint160 addr) public {
@@ -243,8 +236,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: false,
                 beforeDonate: false,
                 afterDonate: false,
-                noOp: false,
-                accessLock: false
+                noOp: false
             })
         );
         assertTrue(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -256,7 +248,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressBeforeModify(uint160 addr) public {
@@ -273,8 +264,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: false,
                 beforeDonate: false,
                 afterDonate: false,
-                noOp: false,
-                accessLock: false
+                noOp: false
             })
         );
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -286,7 +276,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressAfterModify(uint160 addr) public {
@@ -303,8 +292,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: false,
                 beforeDonate: false,
                 afterDonate: false,
-                noOp: false,
-                accessLock: false
+                noOp: false
             })
         );
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -316,7 +304,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressBeforeAndAfterModify(uint160 addr) public {
@@ -334,8 +321,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: false,
                 beforeDonate: false,
                 afterDonate: false,
-                noOp: false,
-                accessLock: false
+                noOp: false
             })
         );
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -347,7 +333,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressBeforeInitializeAfterModify(uint160 addr) public {
@@ -365,8 +350,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: false,
                 beforeDonate: false,
                 afterDonate: false,
-                noOp: false,
-                accessLock: false
+                noOp: false
             })
         );
         assertTrue(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -378,7 +362,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressBeforeSwap(uint160 addr) public {
@@ -395,8 +378,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: false,
                 beforeDonate: false,
                 afterDonate: false,
-                noOp: false,
-                accessLock: false
+                noOp: false
             })
         );
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -408,7 +390,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressAfterSwap(uint160 addr) public {
@@ -425,8 +406,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: true,
                 beforeDonate: false,
                 afterDonate: false,
-                noOp: false,
-                accessLock: false
+                noOp: false
             })
         );
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -438,7 +418,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressBeforeAndAfterSwap(uint160 addr) public {
@@ -455,8 +434,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: true,
                 beforeDonate: false,
                 afterDonate: false,
-                noOp: false,
-                accessLock: false
+                noOp: false
             })
         );
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -468,7 +446,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressBeforeDonate(uint160 addr) public {
@@ -485,8 +462,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: false,
                 beforeDonate: true,
                 afterDonate: false,
-                noOp: false,
-                accessLock: false
+                noOp: false
             })
         );
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -498,7 +474,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertTrue(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressAfterDonate(uint160 addr) public {
@@ -515,8 +490,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: false,
                 beforeDonate: false,
                 afterDonate: true,
-                noOp: false,
-                accessLock: false
+                noOp: false
             })
         );
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -528,7 +502,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertTrue(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressBeforeAndAfterDonate(uint160 addr) public {
@@ -545,8 +518,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: false,
                 beforeDonate: true,
                 afterDonate: true,
-                noOp: false,
-                accessLock: false
+                noOp: false
             })
         );
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -558,37 +530,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertTrue(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertTrue(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
-    }
-
-    function test_validateHookAddress_accessLock(uint160 addr) public {
-        uint160 preAddr = uint160(uint256(addr) & clearAllHookPermisssionsMask);
-        IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.ACCESS_LOCK_FLAG)));
-        Hooks.validateHookPermissions(
-            hookAddr,
-            Hooks.Permissions({
-                beforeInitialize: false,
-                afterInitialize: false,
-                beforeModifyPosition: false,
-                afterModifyPosition: false,
-                beforeSwap: false,
-                afterSwap: false,
-                beforeDonate: false,
-                afterDonate: false,
-                noOp: false,
-                accessLock: true
-            })
-        );
-        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_MODIFY_POSITION_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.AFTER_MODIFY_POSITION_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertTrue(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressAllHooks(uint160 addr) public {
@@ -606,8 +547,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: true,
                 beforeDonate: true,
                 afterDonate: true,
-                noOp: true,
-                accessLock: true
+                noOp: true
             })
         );
         assertTrue(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -619,7 +559,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertTrue(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertTrue(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertTrue(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertTrue(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressNoOp(uint160 addr) public {
@@ -643,8 +582,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: false,
                 beforeDonate: true,
                 afterDonate: false,
-                noOp: true,
-                accessLock: false
+                noOp: true
             })
         );
         assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
@@ -656,7 +594,6 @@ contract HooksTest is Test, Deployers, GasSnapshot {
         assertTrue(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
         assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
         assertTrue(hookAddr.hasPermission(Hooks.NO_OP_FLAG));
-        assertFalse(hookAddr.hasPermission(Hooks.ACCESS_LOCK_FLAG));
     }
 
     function testValidateHookAddressFailsAllHooks(uint152 addr, uint8 mask) public {
@@ -675,8 +612,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: true,
                 beforeDonate: true,
                 afterDonate: true,
-                noOp: true,
-                accessLock: true
+                noOp: true
             })
         );
     }
@@ -698,8 +634,7 @@ contract HooksTest is Test, Deployers, GasSnapshot {
                 afterSwap: false,
                 beforeDonate: false,
                 afterDonate: false,
-                noOp: false,
-                accessLock: false
+                noOp: false
             })
         );
     }

From 13642d8d06dc481ae718de971ea318d3be4a4155 Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Mon, 11 Dec 2023 13:48:55 -0300
Subject: [PATCH 02/19] remove current hook

---
 ...swap hook, already cached dynamic fee.snap |  2 +-
 .../cached dynamic fee, no hooks.snap         |  2 +-
 .forge-snapshots/donate gas with 1 token.snap |  2 +-
 .../donate gas with 2 tokens.snap             |  2 +-
 .forge-snapshots/initialize.snap              |  2 +-
 .forge-snapshots/mint with empty hook.snap    |  2 +-
 .forge-snapshots/mint with native token.snap  |  2 +-
 .forge-snapshots/mint.snap                    |  2 +-
 .../mintWithEmptyHookEOAInitiated.snap        |  2 +-
 .../modify position with noop.snap            |  2 +-
 .../poolManager bytecode size.snap            |  2 +-
 .forge-snapshots/simple swap with native.snap |  2 +-
 .forge-snapshots/simple swap.snap             |  2 +-
 .forge-snapshots/simpleSwapEOAInitiated.snap  |  2 +-
 .../simpleSwapNativeEOAInitiated.snap         |  2 +-
 ...p against liquidity with native token.snap |  2 +-
 .forge-snapshots/swap against liquidity.snap  |  2 +-
 .../swap burn claim for input.snap            |  2 +-
 .../swap mint output as claim.snap            |  2 +-
 .forge-snapshots/swap with dynamic fee.snap   |  2 +-
 .forge-snapshots/swap with hooks.snap         |  2 +-
 .forge-snapshots/swap with noop.snap          |  2 +-
 .../update dynamic fee in before swap.snap    |  2 +-
 src/PoolManager.sol                           | 10 ++--
 src/interfaces/IPoolManager.sol               |  6 +--
 src/libraries/Hooks.sol                       |  5 --
 src/libraries/Lockers.sol                     | 23 ----------
 src/test/PoolDonateTest.sol                   |  3 --
 src/test/PoolModifyPositionTest.sol           |  2 -
 src/test/PoolSwapTest.sol                     |  3 --
 test/CurrentHookAddress.t.sol                 | 46 -------------------
 31 files changed, 27 insertions(+), 117 deletions(-)
 delete mode 100644 test/CurrentHookAddress.t.sol

diff --git a/.forge-snapshots/before swap hook, already cached dynamic fee.snap b/.forge-snapshots/before swap hook, already cached dynamic fee.snap
index c6604068b..a51e4dc7d 100644
--- a/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
+++ b/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
@@ -1 +1 @@
-194810
\ No newline at end of file
+190172
\ No newline at end of file
diff --git a/.forge-snapshots/cached dynamic fee, no hooks.snap b/.forge-snapshots/cached dynamic fee, no hooks.snap
index 7e5695e17..116e65dbf 100644
--- a/.forge-snapshots/cached dynamic fee, no hooks.snap	
+++ b/.forge-snapshots/cached dynamic fee, no hooks.snap	
@@ -1 +1 @@
-147155
\ No newline at end of file
+144157
\ No newline at end of file
diff --git a/.forge-snapshots/donate gas with 1 token.snap b/.forge-snapshots/donate gas with 1 token.snap
index 5124469c5..1a6d6c7ee 100644
--- a/.forge-snapshots/donate gas with 1 token.snap	
+++ b/.forge-snapshots/donate gas with 1 token.snap	
@@ -1 +1 @@
-137830
\ No newline at end of file
+135379
\ No newline at end of file
diff --git a/.forge-snapshots/donate gas with 2 tokens.snap b/.forge-snapshots/donate gas with 2 tokens.snap
index 750c16b17..2a457206c 100644
--- a/.forge-snapshots/donate gas with 2 tokens.snap	
+++ b/.forge-snapshots/donate gas with 2 tokens.snap	
@@ -1 +1 @@
-185252
\ No newline at end of file
+182276
\ No newline at end of file
diff --git a/.forge-snapshots/initialize.snap b/.forge-snapshots/initialize.snap
index 680d86780..4da269400 100644
--- a/.forge-snapshots/initialize.snap
+++ b/.forge-snapshots/initialize.snap
@@ -1 +1 @@
-74213
\ No newline at end of file
+73620
\ No newline at end of file
diff --git a/.forge-snapshots/mint with empty hook.snap b/.forge-snapshots/mint with empty hook.snap
index b6a7df0e2..49fa9cf5c 100644
--- a/.forge-snapshots/mint with empty hook.snap	
+++ b/.forge-snapshots/mint with empty hook.snap	
@@ -1 +1 @@
-323124
\ No newline at end of file
+316830
\ No newline at end of file
diff --git a/.forge-snapshots/mint with native token.snap b/.forge-snapshots/mint with native token.snap
index 71f46d1e2..ee8d8fc5e 100644
--- a/.forge-snapshots/mint with native token.snap	
+++ b/.forge-snapshots/mint with native token.snap	
@@ -1 +1 @@
-199962
\ No newline at end of file
+196948
\ No newline at end of file
diff --git a/.forge-snapshots/mint.snap b/.forge-snapshots/mint.snap
index 80422fda2..b57aba5d1 100644
--- a/.forge-snapshots/mint.snap
+++ b/.forge-snapshots/mint.snap
@@ -1 +1 @@
-199904
\ No newline at end of file
+196890
\ No newline at end of file
diff --git a/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap b/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
index eb0cff75d..e66edc99e 100644
--- a/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
+++ b/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
@@ -1 +1 @@
-255020
\ No newline at end of file
+249251
\ No newline at end of file
diff --git a/.forge-snapshots/modify position with noop.snap b/.forge-snapshots/modify position with noop.snap
index 417bccb67..7fbc53aff 100644
--- a/.forge-snapshots/modify position with noop.snap	
+++ b/.forge-snapshots/modify position with noop.snap	
@@ -1 +1 @@
-58063
\ No newline at end of file
+54459
\ No newline at end of file
diff --git a/.forge-snapshots/poolManager bytecode size.snap b/.forge-snapshots/poolManager bytecode size.snap
index c1302049f..2bb5ec788 100644
--- a/.forge-snapshots/poolManager bytecode size.snap	
+++ b/.forge-snapshots/poolManager bytecode size.snap	
@@ -1 +1 @@
-23544
\ No newline at end of file
+23211
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap with native.snap b/.forge-snapshots/simple swap with native.snap
index d9d1efec5..53c9731f5 100644
--- a/.forge-snapshots/simple swap with native.snap	
+++ b/.forge-snapshots/simple swap with native.snap	
@@ -1 +1 @@
-195697
\ No newline at end of file
+192699
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap.snap b/.forge-snapshots/simple swap.snap
index 2e51f4d43..324b12693 100644
--- a/.forge-snapshots/simple swap.snap	
+++ b/.forge-snapshots/simple swap.snap	
@@ -1 +1 @@
-204265
\ No newline at end of file
+201267
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapEOAInitiated.snap b/.forge-snapshots/simpleSwapEOAInitiated.snap
index 17442dc1e..1cd5f151e 100644
--- a/.forge-snapshots/simpleSwapEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapEOAInitiated.snap
@@ -1 +1 @@
-175531
\ No newline at end of file
+172533
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
index 73521e106..4787f4032 100644
--- a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
@@ -1 +1 @@
-172193
\ No newline at end of file
+169195
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity with native token.snap b/.forge-snapshots/swap against liquidity with native token.snap
index 419176d5f..a7f63ed6b 100644
--- a/.forge-snapshots/swap against liquidity with native token.snap	
+++ b/.forge-snapshots/swap against liquidity with native token.snap	
@@ -1 +1 @@
-126325
\ No newline at end of file
+123327
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity.snap b/.forge-snapshots/swap against liquidity.snap
index 42b5a458b..99e49a2b9 100644
--- a/.forge-snapshots/swap against liquidity.snap	
+++ b/.forge-snapshots/swap against liquidity.snap	
@@ -1 +1 @@
-113816
\ No newline at end of file
+110818
\ No newline at end of file
diff --git a/.forge-snapshots/swap burn claim for input.snap b/.forge-snapshots/swap burn claim for input.snap
index 71512a224..f34da438c 100644
--- a/.forge-snapshots/swap burn claim for input.snap	
+++ b/.forge-snapshots/swap burn claim for input.snap	
@@ -1 +1 @@
-132989
\ No newline at end of file
+129969
\ No newline at end of file
diff --git a/.forge-snapshots/swap mint output as claim.snap b/.forge-snapshots/swap mint output as claim.snap
index 6b4d61781..e58b14bf3 100644
--- a/.forge-snapshots/swap mint output as claim.snap	
+++ b/.forge-snapshots/swap mint output as claim.snap	
@@ -1 +1 @@
-216458
\ No newline at end of file
+213460
\ No newline at end of file
diff --git a/.forge-snapshots/swap with dynamic fee.snap b/.forge-snapshots/swap with dynamic fee.snap
index a3be9998f..4fb6d0ab1 100644
--- a/.forge-snapshots/swap with dynamic fee.snap	
+++ b/.forge-snapshots/swap with dynamic fee.snap	
@@ -1 +1 @@
-193911
\ No newline at end of file
+189273
\ No newline at end of file
diff --git a/.forge-snapshots/swap with hooks.snap b/.forge-snapshots/swap with hooks.snap
index 9fffbdfcd..716127b41 100644
--- a/.forge-snapshots/swap with hooks.snap	
+++ b/.forge-snapshots/swap with hooks.snap	
@@ -1 +1 @@
-113794
\ No newline at end of file
+110796
\ No newline at end of file
diff --git a/.forge-snapshots/swap with noop.snap b/.forge-snapshots/swap with noop.snap
index ae6e82e41..c9c77bffb 100644
--- a/.forge-snapshots/swap with noop.snap	
+++ b/.forge-snapshots/swap with noop.snap	
@@ -1 +1 @@
-51408
\ No newline at end of file
+47842
\ No newline at end of file
diff --git a/.forge-snapshots/update dynamic fee in before swap.snap b/.forge-snapshots/update dynamic fee in before swap.snap
index bafcf12e7..9c08b20d9 100644
--- a/.forge-snapshots/update dynamic fee in before swap.snap	
+++ b/.forge-snapshots/update dynamic fee in before swap.snap	
@@ -1 +1 @@
-200654
\ No newline at end of file
+195993
\ No newline at end of file
diff --git a/src/PoolManager.sol b/src/PoolManager.sol
index 14f57bbbe..3ed315e3d 100644
--- a/src/PoolManager.sol
+++ b/src/PoolManager.sol
@@ -94,13 +94,13 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, Claims {
 
     /// @notice This will revert if a function is called by any address other than the current locker OR the most recently called, pre-permissioned hook.
     modifier onlyByLocker() {
-        _checkLocker(msg.sender, Lockers.getCurrentLocker(), Lockers.getCurrentHook());
+        _checkLocker(msg.sender, Lockers.getCurrentLocker());
         _;
     }
 
-    function _checkLocker(address caller, address locker, IHooks hook) internal pure {
+    function _checkLocker(address caller, address locker) internal pure {
         if (caller == locker) return;
-        revert LockedBy(locker, address(hook));
+        revert LockedBy(locker);
     }
 
     /// @inheritdoc IPoolManager
@@ -345,10 +345,6 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, Claims {
         return Lockers.nonzeroDeltaCount();
     }
 
-    function getCurrentHook() external view returns (IHooks) {
-        return Lockers.getCurrentHook();
-    }
-
     function getPoolTickInfo(PoolId id, int24 tick) external view returns (Pool.TickInfo memory) {
         return pools[id].getPoolTickInfo(tick);
     }
diff --git a/src/interfaces/IPoolManager.sol b/src/interfaces/IPoolManager.sol
index c8d7998ec..82142f7fe 100644
--- a/src/interfaces/IPoolManager.sol
+++ b/src/interfaces/IPoolManager.sol
@@ -23,8 +23,7 @@ interface IPoolManager is IFees, IClaims {
 
     /// @notice Thrown when a function is called by an address that is not the current locker
     /// @param locker The current locker
-    /// @param currentHook The most recently called hook
-    error LockedBy(address locker, address currentHook);
+    error LockedBy(address locker);
 
     /// @notice The ERC1155 being deposited is not the Uniswap ERC1155
     error NotPoolManagerToken();
@@ -119,9 +118,6 @@ interface IPoolManager is IFees, IClaims {
     /// @notice Returns the length of the lockers array, which is the number of locks open on the PoolManager.
     function getLockLength() external view returns (uint256 _length);
 
-    /// @notice Returns the most recently called hook.
-    function getCurrentHook() external view returns (IHooks _currentHook);
-
     /// @notice Returns the number of nonzero deltas open on the PoolManager that must be zerod by the close of the initial lock.
     function getLockNonzeroDeltaCount() external view returns (uint256 _nonzeroDeltaCount);
 
diff --git a/src/libraries/Hooks.sol b/src/libraries/Hooks.sol
index 5627b7bda..361bbbb67 100644
--- a/src/libraries/Hooks.sol
+++ b/src/libraries/Hooks.sol
@@ -91,8 +91,6 @@ library Hooks {
     /// @return expectedSelector The selector that the hook is expected to return
     /// @return selector The selector that the hook actually returned
     function _callHook(IHooks self, bytes memory data) private returns (bytes4 expectedSelector, bytes4 selector) {
-        bool set = Lockers.setCurrentHook(self);
-
         assembly {
             expectedSelector := mload(add(data, 0x20))
         }
@@ -101,9 +99,6 @@ library Hooks {
         if (!success) _revert(result);
 
         selector = abi.decode(result, (bytes4));
-
-        // We only want to clear the current hook if it was set in setCurrentHook in this execution frame.
-        if (set) Lockers.clearCurrentHook();
     }
 
     /// @notice performs a hook call using the given calldata on the given hook
diff --git a/src/libraries/Lockers.sol b/src/libraries/Lockers.sol
index fff26695b..43e60842c 100644
--- a/src/libraries/Lockers.sol
+++ b/src/libraries/Lockers.sol
@@ -121,33 +121,10 @@ library Lockers {
         }
     }
 
-    function getCurrentHook() internal view returns (IHooks currentHook) {
-        return IHooks(getHook(length()));
-    }
-
     function getHook(uint256 i) internal view returns (address hook) {
         uint256 slot = HOOK_ADDRESS_SLOT + i;
         assembly {
             hook := tload(slot)
         }
     }
-
-    function setCurrentHook(IHooks currentHook) internal returns (bool set) {
-        // Set the hook address for the current locker if the address is 0.
-        // If the address is nonzero, a hook has already been set for this lock, and is not allowed to be updated or cleared at the end of the call.
-        if (address(getCurrentHook()) == address(0)) {
-            uint256 slot = HOOK_ADDRESS_SLOT + length();
-            assembly {
-                tstore(slot, currentHook)
-            }
-            return true;
-        }
-    }
-
-    function clearCurrentHook() internal {
-        uint256 slot = HOOK_ADDRESS_SLOT + length();
-        assembly {
-            tstore(slot, 0)
-        }
-    }
 }
diff --git a/src/test/PoolDonateTest.sol b/src/test/PoolDonateTest.sol
index a6b2eac42..726104d6e 100644
--- a/src/test/PoolDonateTest.sol
+++ b/src/test/PoolDonateTest.sol
@@ -53,9 +53,6 @@ contract PoolDonateTest is PoolTestBase, Test {
 
         BalanceDelta delta = manager.donate(data.key, data.amount0, data.amount1, data.hookData);
 
-        // Checks that the current hook is cleared if there is an access lock. Note that if this router is ever used in a nested lock this will fail.
-        assertEq(address(manager.getCurrentHook()), address(0));
-
         (,, uint256 reserveAfter0, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender);
         (,, uint256 reserveAfter1, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender);
 
diff --git a/src/test/PoolModifyPositionTest.sol b/src/test/PoolModifyPositionTest.sol
index 866768298..6480730f5 100644
--- a/src/test/PoolModifyPositionTest.sol
+++ b/src/test/PoolModifyPositionTest.sol
@@ -46,8 +46,6 @@ contract PoolModifyPositionTest is Test, PoolTestBase {
         CallbackData memory data = abi.decode(rawData, (CallbackData));
 
         BalanceDelta delta = manager.modifyPosition(data.key, data.params, data.hookData);
-        // Checks that the current hook is cleared if there is an access lock. Note that if this router is ever used in a nested lock this will fail.
-        assertEq(address(manager.getCurrentHook()), address(0));
 
         (,,, int256 delta0) = _fetchBalances(data.key.currency0, data.sender);
         (,,, int256 delta1) = _fetchBalances(data.key.currency1, data.sender);
diff --git a/src/test/PoolSwapTest.sol b/src/test/PoolSwapTest.sol
index 8e568466f..01715c6b1 100644
--- a/src/test/PoolSwapTest.sol
+++ b/src/test/PoolSwapTest.sol
@@ -62,9 +62,6 @@ contract PoolSwapTest is Test, PoolTestBase {
 
         BalanceDelta delta = manager.swap(data.key, data.params, data.hookData);
 
-        // Checks that the current hook is cleared if there is an access lock. Note that if this router is ever used in a nested lock this will fail.
-        assertEq(address(manager.getCurrentHook()), address(0));
-
         (,, uint256 reserveAfter0, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender);
         (,, uint256 reserveAfter1, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender);
 
diff --git a/test/CurrentHookAddress.t.sol b/test/CurrentHookAddress.t.sol
deleted file mode 100644
index 591027474..000000000
--- a/test/CurrentHookAddress.t.sol
+++ /dev/null
@@ -1,46 +0,0 @@
-// SPDX-License-Identifier: UNLICENSED
-pragma solidity ^0.8.20;
-
-import {Test} from "forge-std/Test.sol";
-import {Lockers} from "../src/libraries/Lockers.sol";
-import {IHooks} from "../src/interfaces/IHooks.sol";
-
-contract CurrentHookAddressTest is Test {
-    function test_getCurrentHook() public {
-        assertEq(address(Lockers.getCurrentHook()), address(0));
-    }
-
-    function test_setCurrentHook() public {
-        Lockers.setCurrentHook(IHooks(address(1)));
-        assertEq(address(Lockers.getCurrentHook()), address(1));
-    }
-
-    function test_setCurrentHook_TwiceDoesNotSucceed() public {
-        (bool set) = Lockers.setCurrentHook(IHooks(address(1)));
-        assertTrue(set);
-        set = Lockers.setCurrentHook(IHooks(address(2)));
-        assertFalse(set);
-        assertEq(address(Lockers.getCurrentHook()), address(1));
-    }
-
-    function test_clearCurrentHook() public {
-        Lockers.setCurrentHook(IHooks(address(1)));
-        assertEq(address(Lockers.getCurrentHook()), address(1));
-        Lockers.clearCurrentHook();
-        assertEq(address(Lockers.getCurrentHook()), address(0));
-    }
-
-    function test_setCurrentHook_afterLock() public {
-        Lockers.push(address(this), address(this));
-        Lockers.setCurrentHook(IHooks(address(1)));
-        assertEq(address(Lockers.getCurrentHook()), address(1));
-    }
-
-    function test_setCurrentHook_beforeAndAfterLock() public {
-        Lockers.push(address(this), address(this));
-        Lockers.setCurrentHook(IHooks(address(2)));
-        assertEq(address(Lockers.getCurrentHook()), address(2));
-        Lockers.push(address(1), address(1));
-        assertEq(address(Lockers.getCurrentHook()), address(0));
-    }
-}

From cd92291f2a70160f17b9ca579c8c034d06ca08b0 Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Mon, 11 Dec 2023 14:57:53 -0300
Subject: [PATCH 03/19] Remove nested locking

---
 ...swap hook, already cached dynamic fee.snap |   2 +-
 .../cached dynamic fee, no hooks.snap         |   2 +-
 .forge-snapshots/donate gas with 1 token.snap |   2 +-
 .../donate gas with 2 tokens.snap             |   2 +-
 .../gas overhead of no-op lock.snap           |   2 +-
 .forge-snapshots/initialize.snap              |   2 +-
 .forge-snapshots/mint with empty hook.snap    |   2 +-
 .forge-snapshots/mint with native token.snap  |   2 +-
 .forge-snapshots/mint.snap                    |   2 +-
 .../mintWithEmptyHookEOAInitiated.snap        |   2 +-
 .../modify position with noop.snap            |   2 +-
 .../poolManager bytecode size.snap            |   2 +-
 .forge-snapshots/simple swap with native.snap |   2 +-
 .forge-snapshots/simple swap.snap             |   2 +-
 .forge-snapshots/simpleSwapEOAInitiated.snap  |   2 +-
 .../simpleSwapNativeEOAInitiated.snap         |   2 +-
 ...p against liquidity with native token.snap |   2 +-
 .forge-snapshots/swap against liquidity.snap  |   2 +-
 .../swap burn claim for input.snap            |   2 +-
 .../swap mint output as claim.snap            |   2 +-
 .forge-snapshots/swap with dynamic fee.snap   |   2 +-
 .forge-snapshots/swap with hooks.snap         |   2 +-
 .forge-snapshots/swap with noop.snap          |   2 +-
 .../update dynamic fee in before swap.snap    |   2 +-
 src/PoolManager.sol                           |  59 +++---
 src/interfaces/IPoolManager.sol               |  10 +-
 src/libraries/Hooks.sol                       |   2 +-
 src/libraries/Locker.sol                      |  81 +++++++++
 src/libraries/Lockers.sol                     | 130 -------------
 test/LockersLibrary.t.sol                     | 104 ++---------
 test/PoolManagerReentrancyTest.t.sol          | 171 ------------------
 31 files changed, 149 insertions(+), 456 deletions(-)
 create mode 100644 src/libraries/Locker.sol
 delete mode 100644 src/libraries/Lockers.sol
 delete mode 100644 test/PoolManagerReentrancyTest.t.sol

diff --git a/.forge-snapshots/before swap hook, already cached dynamic fee.snap b/.forge-snapshots/before swap hook, already cached dynamic fee.snap
index a51e4dc7d..49651fee8 100644
--- a/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
+++ b/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
@@ -1 +1 @@
-190172
\ No newline at end of file
+186339
\ No newline at end of file
diff --git a/.forge-snapshots/cached dynamic fee, no hooks.snap b/.forge-snapshots/cached dynamic fee, no hooks.snap
index 116e65dbf..0ca1c73f5 100644
--- a/.forge-snapshots/cached dynamic fee, no hooks.snap	
+++ b/.forge-snapshots/cached dynamic fee, no hooks.snap	
@@ -1 +1 @@
-144157
\ No newline at end of file
+140324
\ No newline at end of file
diff --git a/.forge-snapshots/donate gas with 1 token.snap b/.forge-snapshots/donate gas with 1 token.snap
index 1a6d6c7ee..73790f19f 100644
--- a/.forge-snapshots/donate gas with 1 token.snap	
+++ b/.forge-snapshots/donate gas with 1 token.snap	
@@ -1 +1 @@
-135379
\ No newline at end of file
+133211
\ No newline at end of file
diff --git a/.forge-snapshots/donate gas with 2 tokens.snap b/.forge-snapshots/donate gas with 2 tokens.snap
index 2a457206c..6c5a6b118 100644
--- a/.forge-snapshots/donate gas with 2 tokens.snap	
+++ b/.forge-snapshots/donate gas with 2 tokens.snap	
@@ -1 +1 @@
-182276
\ No newline at end of file
+178421
\ No newline at end of file
diff --git a/.forge-snapshots/gas overhead of no-op lock.snap b/.forge-snapshots/gas overhead of no-op lock.snap
index 1a78998d5..1d3443815 100644
--- a/.forge-snapshots/gas overhead of no-op lock.snap	
+++ b/.forge-snapshots/gas overhead of no-op lock.snap	
@@ -1 +1 @@
-15246
\ No newline at end of file
+15120
\ No newline at end of file
diff --git a/.forge-snapshots/initialize.snap b/.forge-snapshots/initialize.snap
index 4da269400..3acc92fa5 100644
--- a/.forge-snapshots/initialize.snap
+++ b/.forge-snapshots/initialize.snap
@@ -1 +1 @@
-73620
\ No newline at end of file
+73162
\ No newline at end of file
diff --git a/.forge-snapshots/mint with empty hook.snap b/.forge-snapshots/mint with empty hook.snap
index 49fa9cf5c..5fa2837ed 100644
--- a/.forge-snapshots/mint with empty hook.snap	
+++ b/.forge-snapshots/mint with empty hook.snap	
@@ -1 +1 @@
-316830
\ No newline at end of file
+312975
\ No newline at end of file
diff --git a/.forge-snapshots/mint with native token.snap b/.forge-snapshots/mint with native token.snap
index ee8d8fc5e..655b85cd6 100644
--- a/.forge-snapshots/mint with native token.snap	
+++ b/.forge-snapshots/mint with native token.snap	
@@ -1 +1 @@
-196948
\ No newline at end of file
+193093
\ No newline at end of file
diff --git a/.forge-snapshots/mint.snap b/.forge-snapshots/mint.snap
index b57aba5d1..95b04a94a 100644
--- a/.forge-snapshots/mint.snap
+++ b/.forge-snapshots/mint.snap
@@ -1 +1 @@
-196890
\ No newline at end of file
+193035
\ No newline at end of file
diff --git a/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap b/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
index e66edc99e..efb2e0bff 100644
--- a/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
+++ b/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
@@ -1 +1 @@
-249251
\ No newline at end of file
+247083
\ No newline at end of file
diff --git a/.forge-snapshots/modify position with noop.snap b/.forge-snapshots/modify position with noop.snap
index 7fbc53aff..7c1d70534 100644
--- a/.forge-snapshots/modify position with noop.snap	
+++ b/.forge-snapshots/modify position with noop.snap	
@@ -1 +1 @@
-54459
\ No newline at end of file
+53978
\ No newline at end of file
diff --git a/.forge-snapshots/poolManager bytecode size.snap b/.forge-snapshots/poolManager bytecode size.snap
index 2bb5ec788..4efec4b44 100644
--- a/.forge-snapshots/poolManager bytecode size.snap	
+++ b/.forge-snapshots/poolManager bytecode size.snap	
@@ -1 +1 @@
-23211
\ No newline at end of file
+23132
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap with native.snap b/.forge-snapshots/simple swap with native.snap
index 53c9731f5..90b62aa48 100644
--- a/.forge-snapshots/simple swap with native.snap	
+++ b/.forge-snapshots/simple swap with native.snap	
@@ -1 +1 @@
-192699
\ No newline at end of file
+188866
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap.snap b/.forge-snapshots/simple swap.snap
index 324b12693..3a15f03d9 100644
--- a/.forge-snapshots/simple swap.snap	
+++ b/.forge-snapshots/simple swap.snap	
@@ -1 +1 @@
-201267
\ No newline at end of file
+197434
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapEOAInitiated.snap b/.forge-snapshots/simpleSwapEOAInitiated.snap
index 1cd5f151e..f40b6a487 100644
--- a/.forge-snapshots/simpleSwapEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapEOAInitiated.snap
@@ -1 +1 @@
-172533
\ No newline at end of file
+168722
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
index 4787f4032..d3e4b0504 100644
--- a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
@@ -1 +1 @@
-169195
\ No newline at end of file
+165384
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity with native token.snap b/.forge-snapshots/swap against liquidity with native token.snap
index a7f63ed6b..647f29ebc 100644
--- a/.forge-snapshots/swap against liquidity with native token.snap	
+++ b/.forge-snapshots/swap against liquidity with native token.snap	
@@ -1 +1 @@
-123327
\ No newline at end of file
+119494
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity.snap b/.forge-snapshots/swap against liquidity.snap
index 99e49a2b9..ff97d120f 100644
--- a/.forge-snapshots/swap against liquidity.snap	
+++ b/.forge-snapshots/swap against liquidity.snap	
@@ -1 +1 @@
-110818
\ No newline at end of file
+106985
\ No newline at end of file
diff --git a/.forge-snapshots/swap burn claim for input.snap b/.forge-snapshots/swap burn claim for input.snap
index f34da438c..35c806bf3 100644
--- a/.forge-snapshots/swap burn claim for input.snap	
+++ b/.forge-snapshots/swap burn claim for input.snap	
@@ -1 +1 @@
-129969
\ No newline at end of file
+126158
\ No newline at end of file
diff --git a/.forge-snapshots/swap mint output as claim.snap b/.forge-snapshots/swap mint output as claim.snap
index e58b14bf3..3b23424b0 100644
--- a/.forge-snapshots/swap mint output as claim.snap	
+++ b/.forge-snapshots/swap mint output as claim.snap	
@@ -1 +1 @@
-213460
\ No newline at end of file
+209649
\ No newline at end of file
diff --git a/.forge-snapshots/swap with dynamic fee.snap b/.forge-snapshots/swap with dynamic fee.snap
index 4fb6d0ab1..a0decf59e 100644
--- a/.forge-snapshots/swap with dynamic fee.snap	
+++ b/.forge-snapshots/swap with dynamic fee.snap	
@@ -1 +1 @@
-189273
\ No newline at end of file
+185440
\ No newline at end of file
diff --git a/.forge-snapshots/swap with hooks.snap b/.forge-snapshots/swap with hooks.snap
index 716127b41..4ebfef2b9 100644
--- a/.forge-snapshots/swap with hooks.snap	
+++ b/.forge-snapshots/swap with hooks.snap	
@@ -1 +1 @@
-110796
\ No newline at end of file
+106963
\ No newline at end of file
diff --git a/.forge-snapshots/swap with noop.snap b/.forge-snapshots/swap with noop.snap
index c9c77bffb..1053b45e4 100644
--- a/.forge-snapshots/swap with noop.snap	
+++ b/.forge-snapshots/swap with noop.snap	
@@ -1 +1 @@
-47842
\ No newline at end of file
+47361
\ No newline at end of file
diff --git a/.forge-snapshots/update dynamic fee in before swap.snap b/.forge-snapshots/update dynamic fee in before swap.snap
index 9c08b20d9..cb5df9a3e 100644
--- a/.forge-snapshots/update dynamic fee in before swap.snap	
+++ b/.forge-snapshots/update dynamic fee in before swap.snap	
@@ -1 +1 @@
-195993
\ No newline at end of file
+192160
\ No newline at end of file
diff --git a/src/PoolManager.sol b/src/PoolManager.sol
index 3ed315e3d..374fda1ec 100644
--- a/src/PoolManager.sol
+++ b/src/PoolManager.sol
@@ -19,7 +19,7 @@ import {Fees} from "./Fees.sol";
 import {Claims} from "./Claims.sol";
 import {PoolId, PoolIdLibrary} from "./types/PoolId.sol";
 import {BalanceDelta, BalanceDeltaLibrary} from "./types/BalanceDelta.sol";
-import {Lockers} from "./libraries/Lockers.sol";
+import {Locker} from "./libraries/Locker.sol";
 import {PoolGetters} from "./libraries/PoolGetters.sol";
 
 /// @notice Holds the state for all pools
@@ -88,26 +88,21 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, Claims {
     }
 
     /// @inheritdoc IPoolManager
-    function getLock(uint256 i) external view override returns (address locker, address lockCaller) {
-        return (Lockers.getLocker(i), Lockers.getLockCaller(i));
+    function getLock() external view override returns (address locker, address lockCaller) {
+        return (Locker.getLocker(), Locker.getLockCaller());
     }
 
     /// @notice This will revert if a function is called by any address other than the current locker OR the most recently called, pre-permissioned hook.
-    modifier onlyByLocker() {
-        _checkLocker(msg.sender, Lockers.getCurrentLocker());
+    modifier isLocked() {
+        if (!Locker.isLocked()) revert ManagerNotLocked();
         _;
     }
 
-    function _checkLocker(address caller, address locker) internal pure {
-        if (caller == locker) return;
-        revert LockedBy(locker);
-    }
-
     /// @inheritdoc IPoolManager
     function initialize(PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData)
         external
         override
-        onlyByLocker
+        isLocked
         returns (int24 tick)
     {
         if (key.fee.isStaticFeeTooLarge()) revert FeeTooLarge();
@@ -134,35 +129,33 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, Claims {
 
     /// @inheritdoc IPoolManager
     function lock(address lockTarget, bytes calldata data) external payable override returns (bytes memory result) {
-        Lockers.push(lockTarget, msg.sender);
+        // Get the lock caller because thats an EOA and is not user-controlable
+        if (Locker.isLocked()) revert LockedBy(Locker.getLocker());
+
+        Locker.setLockerAndCaller(lockTarget, msg.sender);
 
         // the caller does everything in this callback, including paying what they owe via calls to settle
         result = ILockCallback(lockTarget).lockAcquired(msg.sender, data);
 
-        if (Lockers.length() == 1) {
-            if (Lockers.nonzeroDeltaCount() != 0) revert CurrencyNotSettled();
-            Lockers.clear();
-        } else {
-            Lockers.pop();
-        }
+        if (Locker.nonzeroDeltaCount() != 0) revert CurrencyNotSettled();
+        Locker.clearLockerAndCaller();
     }
 
     function _accountDelta(Currency currency, int128 delta) internal {
         if (delta == 0) return;
 
-        address locker = Lockers.getCurrentLocker();
-        int256 current = currencyDelta[locker][currency];
+        int256 current = currencyDelta[msg.sender][currency];
         int256 next = current + delta;
 
         unchecked {
             if (next == 0) {
-                Lockers.decrementNonzeroDeltaCount();
+                Locker.decrementNonzeroDeltaCount();
             } else if (current == 0) {
-                Lockers.incrementNonzeroDeltaCount();
+                Locker.incrementNonzeroDeltaCount();
             }
         }
 
-        currencyDelta[locker][currency] = next;
+        currencyDelta[msg.sender][currency] = next;
     }
 
     /// @dev Accumulates a balance change to a map of currency to balance changes
@@ -180,7 +173,7 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, Claims {
         PoolKey memory key,
         IPoolManager.ModifyPositionParams memory params,
         bytes calldata hookData
-    ) external override noDelegateCall onlyByLocker returns (BalanceDelta delta) {
+    ) external override noDelegateCall isLocked returns (BalanceDelta delta) {
         PoolId id = key.toId();
         _checkPoolInitialized(id);
 
@@ -210,7 +203,7 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, Claims {
         external
         override
         noDelegateCall
-        onlyByLocker
+        isLocked
         returns (BalanceDelta delta)
     {
         PoolId id = key.toId();
@@ -253,7 +246,7 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, Claims {
         external
         override
         noDelegateCall
-        onlyByLocker
+        isLocked
         returns (BalanceDelta delta)
     {
         PoolId id = key.toId();
@@ -271,14 +264,14 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, Claims {
     }
 
     /// @inheritdoc IPoolManager
-    function take(Currency currency, address to, uint256 amount) external override noDelegateCall onlyByLocker {
+    function take(Currency currency, address to, uint256 amount) external override noDelegateCall isLocked {
         _accountDelta(currency, amount.toInt128());
         reservesOf[currency] -= amount;
         currency.transfer(to, amount);
     }
 
     /// @inheritdoc IPoolManager
-    function settle(Currency currency) external payable override noDelegateCall onlyByLocker returns (uint256 paid) {
+    function settle(Currency currency) external payable override noDelegateCall isLocked returns (uint256 paid) {
         uint256 reservesBefore = reservesOf[currency];
         reservesOf[currency] = currency.balanceOfSelf();
         paid = reservesOf[currency] - reservesBefore;
@@ -287,13 +280,13 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, Claims {
     }
 
     /// @inheritdoc IPoolManager
-    function mint(Currency currency, address to, uint256 amount) external noDelegateCall onlyByLocker {
+    function mint(Currency currency, address to, uint256 amount) external noDelegateCall isLocked {
         _accountDelta(currency, amount.toInt128());
         _mint(to, currency, amount);
     }
 
     /// @inheritdoc IPoolManager
-    function burn(Currency currency, uint256 amount) external noDelegateCall onlyByLocker {
+    function burn(Currency currency, uint256 amount) external noDelegateCall isLocked {
         _accountDelta(currency, -(amount.toInt128()));
         _burn(currency, amount);
     }
@@ -337,12 +330,8 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, Claims {
         return value;
     }
 
-    function getLockLength() external view returns (uint256 _length) {
-        return Lockers.length();
-    }
-
     function getLockNonzeroDeltaCount() external view returns (uint256 _nonzeroDeltaCount) {
-        return Lockers.nonzeroDeltaCount();
+        return Locker.nonzeroDeltaCount();
     }
 
     function getPoolTickInfo(PoolId id, int24 tick) external view returns (Pool.TickInfo memory) {
diff --git a/src/interfaces/IPoolManager.sol b/src/interfaces/IPoolManager.sol
index 82142f7fe..f9121676f 100644
--- a/src/interfaces/IPoolManager.sol
+++ b/src/interfaces/IPoolManager.sol
@@ -25,6 +25,9 @@ interface IPoolManager is IFees, IClaims {
     /// @param locker The current locker
     error LockedBy(address locker);
 
+    /// @notice Thrown when a function is called by an address that is not the current locker
+    error ManagerNotLocked();
+
     /// @notice The ERC1155 being deposited is not the Uniswap ERC1155
     error NotPoolManagerToken();
 
@@ -112,11 +115,8 @@ interface IPoolManager is IFees, IClaims {
     /// @notice Returns the reserves for a given ERC20 currency
     function reservesOf(Currency currency) external view returns (uint256);
 
-    /// @notice Returns the locker in the ith position of the locker queue.
-    function getLock(uint256 i) external view returns (address locker, address lockCaller);
-
-    /// @notice Returns the length of the lockers array, which is the number of locks open on the PoolManager.
-    function getLockLength() external view returns (uint256 _length);
+    /// @notice Returns the locker and lockCaller of the pool
+    function getLock() external view returns (address locker, address lockCaller);
 
     /// @notice Returns the number of nonzero deltas open on the PoolManager that must be zerod by the close of the initial lock.
     function getLockNonzeroDeltaCount() external view returns (uint256 _nonzeroDeltaCount);
diff --git a/src/libraries/Hooks.sol b/src/libraries/Hooks.sol
index 361bbbb67..e0c7b9f6a 100644
--- a/src/libraries/Hooks.sol
+++ b/src/libraries/Hooks.sol
@@ -6,7 +6,7 @@ import {IHooks} from "../interfaces/IHooks.sol";
 import {FeeLibrary} from "./FeeLibrary.sol";
 import {BalanceDelta} from "../types/BalanceDelta.sol";
 import {IPoolManager} from "../interfaces/IPoolManager.sol";
-import {Lockers} from "./Lockers.sol";
+import {Locker} from "./Locker.sol";
 
 /// @notice V4 decides whether to invoke specific hooks by inspecting the leading bits of the address that
 /// the hooks contract is deployed to.
diff --git a/src/libraries/Locker.sol b/src/libraries/Locker.sol
new file mode 100644
index 000000000..e1320f933
--- /dev/null
+++ b/src/libraries/Locker.sol
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: BUSL-1.1
+pragma solidity ^0.8.20;
+
+import {IHooks} from "../interfaces/IHooks.sol";
+
+/// @notice This is a temporary library that allows us to use transient storage (tstore/tload)
+/// for the lockers array and nonzero delta count.
+/// TODO: This library can be deleted when we have the transient keyword support in solidity.
+library Locker {
+    // The slot holding the locker, transiently, and the lock caller in the next slot
+    uint256 constant LOCKER_SLOT = uint256(keccak256("Locker")) - 2;
+    uint256 constant LOCK_CALLER_SLOT = LOCKER_SLOT + 1;
+
+    // The slot holding the number of nonzero deltas.
+    uint256 constant NONZERO_DELTA_COUNT = uint256(keccak256("NonzeroDeltaCount")) - 1;
+
+    function setLockerAndCaller(address locker, address lockCaller) internal {
+        uint256 slot = LOCKER_SLOT;
+
+        assembly {
+            // set the locker
+            tstore(slot, locker)
+
+            // set the lock caller
+            tstore(add(slot, 1), lockCaller)
+        }
+    }
+
+    function clearLockerAndCaller() internal {
+        uint256 slot = LOCKER_SLOT;
+        assembly {
+            tstore(slot, 0)
+            tstore(add(slot, 1), 0)
+        }
+    }
+
+    function getLocker() internal view returns (address locker) {
+        uint256 slot = LOCKER_SLOT;
+        assembly {
+            locker := tload(slot)
+        }
+    }
+
+    function isLocked() internal view returns (bool) {
+        return Locker.getLockCaller() != address(0);
+    }
+
+    function getLockCaller() internal view returns (address locker) {
+        uint256 slot = LOCK_CALLER_SLOT;
+        assembly {
+            locker := tload(slot)
+        }
+    }
+
+    function nonzeroDeltaCount() internal view returns (uint256 count) {
+        uint256 slot = NONZERO_DELTA_COUNT;
+        assembly {
+            count := tload(slot)
+        }
+    }
+
+    function incrementNonzeroDeltaCount() internal {
+        uint256 slot = NONZERO_DELTA_COUNT;
+        assembly {
+            let count := tload(slot)
+            count := add(count, 1)
+            tstore(slot, count)
+        }
+    }
+
+    /// @notice Potential to underflow.
+    /// Current usage ensures this will not happen because we call decrememnt with known boundaries (only up to the numer of times we call increment).
+    function decrementNonzeroDeltaCount() internal {
+        uint256 slot = NONZERO_DELTA_COUNT;
+        assembly {
+            let count := tload(slot)
+            count := sub(count, 1)
+            tstore(slot, count)
+        }
+    }
+}
diff --git a/src/libraries/Lockers.sol b/src/libraries/Lockers.sol
deleted file mode 100644
index 43e60842c..000000000
--- a/src/libraries/Lockers.sol
+++ /dev/null
@@ -1,130 +0,0 @@
-// SPDX-License-Identifier: BUSL-1.1
-pragma solidity ^0.8.20;
-
-import {IHooks} from "../interfaces/IHooks.sol";
-
-/// @notice This is a temporary library that allows us to use transient storage (tstore/tload)
-/// for the lockers array and nonzero delta count.
-/// TODO: This library can be deleted when we have the transient keyword support in solidity.
-library Lockers {
-    // The starting slot for an array of lockers, stored transiently.
-    uint256 constant LOCKERS_SLOT = uint256(keccak256("Lockers")) - 1;
-
-    // The number of slots per item in the lockers array
-    uint256 constant LOCKER_STRUCT_SIZE = 2;
-
-    // The starting slot for an array of hook addresses per locker, stored transiently.
-    uint256 constant HOOK_ADDRESS_SLOT = uint256(keccak256("HookAddress")) - 1;
-
-    // The slot holding the number of nonzero deltas.
-    uint256 constant NONZERO_DELTA_COUNT = uint256(keccak256("NonzeroDeltaCount")) - 1;
-
-    // pushes an address tuple (address locker, address lockCaller)
-    // to the locker array, so each length of the array represents 2 slots of tstorage
-    function push(address locker, address lockCaller) internal {
-        uint256 slot = LOCKERS_SLOT;
-
-        uint256 newLength;
-        uint256 thisLockerSlot;
-
-        unchecked {
-            newLength = length() + 1;
-            thisLockerSlot = LOCKERS_SLOT + (newLength * LOCKER_STRUCT_SIZE);
-        }
-
-        assembly {
-            // add the locker
-            tstore(thisLockerSlot, locker)
-
-            // add the lock caller
-            tstore(add(thisLockerSlot, 1), lockCaller)
-
-            // increase the length
-            tstore(slot, newLength)
-        }
-    }
-
-    function pop() internal {
-        // decrease the length
-        uint256 slot = LOCKERS_SLOT;
-        uint256 newLength;
-        unchecked {
-            newLength = length() - 1;
-        }
-        assembly {
-            tstore(slot, newLength)
-        }
-    }
-
-    function length() internal view returns (uint256 _length) {
-        uint256 slot = LOCKERS_SLOT;
-        assembly {
-            _length := tload(slot)
-        }
-    }
-
-    function clear() internal {
-        uint256 slot = LOCKERS_SLOT;
-        assembly {
-            tstore(slot, 0)
-        }
-    }
-
-    function getLocker(uint256 i) internal view returns (address locker) {
-        // first slot of the ith array item
-        uint256 slot = LOCKERS_SLOT + (i * LOCKER_STRUCT_SIZE);
-        assembly {
-            locker := tload(slot)
-        }
-    }
-
-    function getLockCaller(uint256 i) internal view returns (address locker) {
-        // second slot of the ith array item
-        uint256 slot = LOCKERS_SLOT + (i * LOCKER_STRUCT_SIZE + 1);
-        assembly {
-            locker := tload(slot)
-        }
-    }
-
-    function getCurrentLocker() internal view returns (address locker) {
-        return getLocker(length());
-    }
-
-    function getCurrentLockCaller() internal view returns (address locker) {
-        return getLockCaller(length());
-    }
-
-    function nonzeroDeltaCount() internal view returns (uint256 count) {
-        uint256 slot = NONZERO_DELTA_COUNT;
-        assembly {
-            count := tload(slot)
-        }
-    }
-
-    function incrementNonzeroDeltaCount() internal {
-        uint256 slot = NONZERO_DELTA_COUNT;
-        assembly {
-            let count := tload(slot)
-            count := add(count, 1)
-            tstore(slot, count)
-        }
-    }
-
-    /// @notice Potential to underflow.
-    /// Current usage ensures this will not happen because we call decrememnt with known boundaries (only up to the numer of times we call increment).
-    function decrementNonzeroDeltaCount() internal {
-        uint256 slot = NONZERO_DELTA_COUNT;
-        assembly {
-            let count := tload(slot)
-            count := sub(count, 1)
-            tstore(slot, count)
-        }
-    }
-
-    function getHook(uint256 i) internal view returns (address hook) {
-        uint256 slot = HOOK_ADDRESS_SLOT + i;
-        assembly {
-            hook := tload(slot)
-        }
-    }
-}
diff --git a/test/LockersLibrary.t.sol b/test/LockersLibrary.t.sol
index a2d73cf09..00791bb60 100644
--- a/test/LockersLibrary.t.sol
+++ b/test/LockersLibrary.t.sol
@@ -10,7 +10,7 @@ import {Currency, CurrencyLibrary} from "../src/types/Currency.sol";
 import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
 import {PoolKey} from "../src/types/PoolKey.sol";
 import {IHooks} from "../src/interfaces/IHooks.sol";
-import {Lockers} from "../src/libraries/Lockers.sol";
+import {Locker} from "../src/libraries/Locker.sol";
 
 contract LockersLibraryTest is Test, Deployers, ILockCallback {
     using CurrencyLibrary for Currency;
@@ -22,126 +22,50 @@ contract LockersLibraryTest is Test, Deployers, ILockCallback {
     }
 
     function testLockerLengthAndNonzeroDeltaCount() public {
-        (uint256 lengthDuringLockCallback, uint256 nonzeroDeltaCountDuringCallback) =
-            abi.decode(manager.lock(address(this), ""), (uint256, uint256));
-        assertEq(lengthDuringLockCallback, 1);
+        (uint256 nonzeroDeltaCountDuringCallback) = abi.decode(manager.lock(address(this), ""), (uint256));
         assertEq(nonzeroDeltaCountDuringCallback, 1);
-        assertEq(manager.getLockLength(), 0);
         assertEq(manager.getLockNonzeroDeltaCount(), 0);
     }
 
     function lockAcquired(address, bytes calldata) public returns (bytes memory) {
-        uint256 len = manager.getLockLength();
-
         // apply a delta and save count
         manager.take(key.currency0, address(this), 1);
         uint256 count = manager.getLockNonzeroDeltaCount();
         key.currency0.transfer(address(manager), 1);
         manager.settle(key.currency0);
 
-        bytes memory data = abi.encode(len, count);
+        bytes memory data = abi.encode(count);
         return data;
     }
 
-    function test_push() public {
-        Lockers.push(address(this), address(1));
-        assertEq(Lockers.length(), 1);
-        assertEq(Lockers.getLocker(LOCKERS_OFFSET), address(this));
-        assertEq(Lockers.getLockCaller(LOCKERS_OFFSET), address(1));
-    }
-
-    function test_push_multipleAddressesFuzz(address[2][] memory addrs) public {
-        for (uint256 i = 0; i < addrs.length; i++) {
-            address[2] memory loopAddrs = addrs[i];
-            address locker = loopAddrs[0];
-            address lockCaller = loopAddrs[1];
-            assertEq(Lockers.length(), i);
-            Lockers.push(locker, lockCaller);
-            assertEq(Lockers.length(), LOCKERS_OFFSET + i);
-            assertEq(Lockers.getLocker(LOCKERS_OFFSET + i), locker);
-            assertEq(Lockers.getLockCaller(LOCKERS_OFFSET + i), lockCaller);
-        }
-    }
-
-    function test_getCurrentLocker_multipleAddressesFuzz(address[2][] memory addrs) public {
-        for (uint256 i = 0; i < addrs.length; i++) {
-            address[2] memory loopAddrs = addrs[i];
-            address locker = loopAddrs[0];
-            address lockCaller = loopAddrs[1];
-            assertEq(Lockers.length(), i);
-            Lockers.push(locker, lockCaller);
-            assertEq(Lockers.length(), LOCKERS_OFFSET + i);
-            assertEq(Lockers.getCurrentLocker(), locker);
-            assertEq(Lockers.getCurrentLockCaller(), lockCaller);
-        }
-    }
-
-    function test_pop() public {
-        Lockers.push(address(this), address(1));
-        assertEq(Lockers.length(), 1);
-        Lockers.pop();
-        assertEq(Lockers.length(), 0);
-    }
-
-    function test_pop_multipleAddressesFuzz(address[2][] memory addrs) public {
-        for (uint256 i = 0; i < addrs.length; i++) {
-            address[2] memory loopAddrs = addrs[i];
-            address locker = loopAddrs[0];
-            address lockCaller = loopAddrs[1];
-            Lockers.push(locker, lockCaller);
-        }
-
-        assertEq(Lockers.length(), addrs.length);
-
-        for (uint256 i = 0; i < addrs.length; i++) {
-            Lockers.pop();
-            assertEq(Lockers.length(), addrs.length - i - LOCKERS_OFFSET);
-        }
-
-        assertEq(Lockers.length(), 0);
-    }
-
-    function test_clear(address[2][] memory addrs) public {
-        for (uint256 i = 0; i < addrs.length; i++) {
-            address[2] memory loopAddrs = addrs[i];
-            address locker = loopAddrs[0];
-            address lockCaller = loopAddrs[1];
-            Lockers.push(locker, lockCaller);
-        }
-
-        assertEq(Lockers.length(), addrs.length);
-        Lockers.clear();
-        assertEq(Lockers.length(), 0);
-    }
-
     function test_incrementNonzeroDeltaCount() public {
-        Lockers.incrementNonzeroDeltaCount();
-        assertEq(Lockers.nonzeroDeltaCount(), 1);
+        Locker.incrementNonzeroDeltaCount();
+        assertEq(Locker.nonzeroDeltaCount(), 1);
     }
 
     function test_incrementNonzeroDeltaCountFuzz(uint8 count) public {
         for (uint256 i = 0; i < count; i++) {
-            Lockers.incrementNonzeroDeltaCount();
-            assertEq(Lockers.nonzeroDeltaCount(), i + 1);
+            Locker.incrementNonzeroDeltaCount();
+            assertEq(Locker.nonzeroDeltaCount(), i + 1);
         }
     }
 
     function test_decrementNonzeroDeltaCount() public {
-        Lockers.incrementNonzeroDeltaCount();
-        Lockers.decrementNonzeroDeltaCount();
-        assertEq(Lockers.nonzeroDeltaCount(), 0);
+        Locker.incrementNonzeroDeltaCount();
+        Locker.decrementNonzeroDeltaCount();
+        assertEq(Locker.nonzeroDeltaCount(), 0);
     }
 
     function test_decrementNonzeroDeltaCountFuzz(uint8 count) public {
         for (uint256 i = 0; i < count; i++) {
-            Lockers.incrementNonzeroDeltaCount();
+            Locker.incrementNonzeroDeltaCount();
         }
 
-        assertEq(Lockers.nonzeroDeltaCount(), count);
+        assertEq(Locker.nonzeroDeltaCount(), count);
 
         for (uint256 i = 0; i < count; i++) {
-            Lockers.decrementNonzeroDeltaCount();
-            assertEq(Lockers.nonzeroDeltaCount(), count - i - 1);
+            Locker.decrementNonzeroDeltaCount();
+            assertEq(Locker.nonzeroDeltaCount(), count - i - 1);
         }
     }
 }
diff --git a/test/PoolManagerReentrancyTest.t.sol b/test/PoolManagerReentrancyTest.t.sol
deleted file mode 100644
index 8eb25d4c6..000000000
--- a/test/PoolManagerReentrancyTest.t.sol
+++ /dev/null
@@ -1,171 +0,0 @@
-// SPDX-License-Identifier: UNLICENSED
-pragma solidity ^0.8.20;
-
-import {Test} from "forge-std/Test.sol";
-import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
-import {Currency, CurrencyLibrary} from "../src/types/Currency.sol";
-import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
-import {IHooks} from "../src/interfaces/IHooks.sol";
-import {ILockCallback} from "../src/interfaces/callback/ILockCallback.sol";
-import {PoolManager} from "../src/PoolManager.sol";
-import {Deployers} from "./utils/Deployers.sol";
-
-contract TokenLocker is ILockCallback {
-    using CurrencyLibrary for Currency;
-
-    function main(IPoolManager manager, Currency currency, bool reclaim) external {
-        manager.lock(address(this), abi.encode(currency, reclaim));
-    }
-
-    function lockAcquired(address, bytes calldata data) external returns (bytes memory) {
-        (Currency currency, bool reclaim) = abi.decode(data, (Currency, bool));
-
-        IPoolManager manager = IPoolManager(msg.sender);
-        uint256 count = manager.getLockNonzeroDeltaCount();
-        assert(count == 0);
-
-        int256 delta = manager.currencyDelta(address(this), currency);
-        assert(delta == 0);
-
-        // deposit some tokens
-        currency.transfer(address(manager), 1);
-        manager.settle(currency);
-        count = manager.getLockNonzeroDeltaCount();
-        assert(count == 1);
-        delta = manager.currencyDelta(address(this), currency);
-        assert(delta == -1);
-
-        // take them back
-        if (reclaim) {
-            manager.take(currency, address(this), 1);
-            count = manager.getLockNonzeroDeltaCount();
-            assert(count == 0);
-            delta = manager.currencyDelta(address(this), currency);
-            assert(delta == 0);
-        }
-
-        return "";
-    }
-}
-
-contract SimpleLinearLocker is ILockCallback {
-    function(uint256) external checker;
-
-    function main(IPoolManager manager, uint256 timesToReenter, function(uint256) external checker_) external {
-        checker = checker_;
-        manager.lock(address(this), abi.encode(timesToReenter, 0));
-    }
-
-    function lockAcquired(address, bytes calldata data) external returns (bytes memory) {
-        (uint256 timesToReenter, uint256 depth) = abi.decode(data, (uint256, uint256));
-        checker(depth);
-        if (depth < timesToReenter) {
-            IPoolManager manager = IPoolManager(msg.sender);
-            manager.lock(address(this), abi.encode(timesToReenter, depth + 1));
-        }
-        return "";
-    }
-}
-
-contract ParallelLocker is ILockCallback {
-    // We define an INDEX_OFFSET at 1 since the first locker is placed at index 1.
-    // The 0th index is used for storing the length.
-    uint256 constant INDEX_OFFSET = 1;
-    IPoolManager manager;
-
-    constructor(IPoolManager manager_) {
-        manager = manager_;
-    }
-
-    function main() external {
-        manager.lock(address(this), "");
-    }
-
-    function assertionChecker0(uint256) external view {
-        uint256 length = manager.getLockLength();
-        assert(length == 2);
-        (address locker,) = manager.getLock(INDEX_OFFSET + 1);
-        assert(locker == msg.sender);
-    }
-
-    function assertionChecker1(uint256 depth) external view {
-        uint256 length = manager.getLockLength();
-        assert(length == depth + 2);
-        (address locker,) = manager.getLock(INDEX_OFFSET + depth + 1);
-        assert(locker == msg.sender);
-    }
-
-    function assertionChecker2(uint256) external view {
-        uint256 length = manager.getLockLength();
-        assert(length == 2);
-        (address locker,) = manager.getLock(INDEX_OFFSET + 1);
-        assert(locker == msg.sender);
-    }
-
-    function lockAcquired(address, bytes calldata) external returns (bytes memory) {
-        SimpleLinearLocker locker0 = new SimpleLinearLocker();
-        SimpleLinearLocker locker1 = new SimpleLinearLocker();
-        SimpleLinearLocker locker2 = new SimpleLinearLocker();
-
-        uint256 length = manager.getLockLength();
-        assert(length == 1);
-        (address locker,) = manager.getLock(INDEX_OFFSET + 0);
-        assert(locker == address(this));
-
-        locker0.main(manager, 0, this.assertionChecker0);
-        uint256 length1 = manager.getLockLength();
-        assert(length1 == 1);
-
-        locker1.main(manager, 1, this.assertionChecker1);
-        uint256 length2 = manager.getLockLength();
-        assert(length2 == 1);
-
-        locker2.main(manager, 0, this.assertionChecker2);
-        uint256 length3 = manager.getLockLength();
-        assert(length3 == 1);
-
-        return "";
-    }
-}
-
-contract PoolManagerReentrancyTest is Test, Deployers {
-    uint256 constant INDEX_OFFSET = 1;
-
-    function setUp() public {
-        initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0)));
-    }
-
-    function testTokenLocker() public {
-        TokenLocker locker = new TokenLocker();
-        MockERC20(Currency.unwrap(currency0)).mint(address(locker), 1);
-        MockERC20(Currency.unwrap(currency0)).approve(address(locker), 1);
-        locker.main(manager, currency0, true);
-    }
-
-    function testTokenRevert() public {
-        TokenLocker locker = new TokenLocker();
-        MockERC20(Currency.unwrap(currency0)).mint(address(locker), 1);
-        MockERC20(Currency.unwrap(currency0)).approve(address(locker), 1);
-        vm.expectRevert(abi.encodeWithSelector(IPoolManager.CurrencyNotSettled.selector));
-        locker.main(manager, currency0, false);
-    }
-
-    function assertionChecker(uint256 depth) external {
-        uint256 length = manager.getLockLength();
-        assertEq(length, depth + 1);
-        (address locker,) = manager.getLock(INDEX_OFFSET + depth);
-        assertEq(locker, msg.sender);
-    }
-
-    function testSimpleLinearLocker() public {
-        SimpleLinearLocker locker = new SimpleLinearLocker();
-        locker.main(manager, 0, this.assertionChecker);
-        locker.main(manager, 1, this.assertionChecker);
-        locker.main(manager, 2, this.assertionChecker);
-    }
-
-    function testParallelLocker() public {
-        ParallelLocker locker = new ParallelLocker(manager);
-        locker.main();
-    }
-}

From 1f4961e127266dfc728af9412d0a798f090fff5f Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Tue, 12 Dec 2023 14:09:22 -0300
Subject: [PATCH 04/19] Locker library tests

---
 test/Locker.t.sol         | 81 +++++++++++++++++++++++++++++++++++++++
 test/LockersLibrary.t.sol | 71 ----------------------------------
 2 files changed, 81 insertions(+), 71 deletions(-)
 create mode 100644 test/Locker.t.sol
 delete mode 100644 test/LockersLibrary.t.sol

diff --git a/test/Locker.t.sol b/test/Locker.t.sol
new file mode 100644
index 000000000..fc9647cb5
--- /dev/null
+++ b/test/Locker.t.sol
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: UNLICENSED
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {Locker} from "../src/libraries/Locker.sol";
+
+contract CurrentHookAddressTest is Test {
+    address constant ADDRESS_AS = 0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa;
+    address constant ADDRESS_BS = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;
+
+    function test_setLockerAndCaller() public {
+        assertEq(address(Locker.getLocker()), address(0));
+        assertEq(address(Locker.getLockCaller()), address(0));
+
+        Locker.setLockerAndCaller(ADDRESS_AS, ADDRESS_BS);
+
+        assertEq(address(Locker.getLocker()), ADDRESS_AS);
+        assertEq(address(Locker.getLockCaller()), ADDRESS_BS);
+
+        // in the way this library is used in V4, this function will never be called when non-0
+        Locker.setLockerAndCaller(ADDRESS_BS, ADDRESS_AS);
+
+        assertEq(address(Locker.getLocker()), ADDRESS_BS);
+        assertEq(address(Locker.getLockCaller()), ADDRESS_AS);
+    }
+
+    function test_clearLockerAndCaller() public {
+        Locker.setLockerAndCaller(ADDRESS_AS, ADDRESS_BS);
+
+        assertEq(address(Locker.getLocker()), ADDRESS_AS);
+        assertEq(address(Locker.getLockCaller()), ADDRESS_BS);
+
+        Locker.clearLockerAndCaller();
+
+        assertEq(address(Locker.getLocker()), address(0));
+        assertEq(address(Locker.getLockCaller()), address(0));
+    }
+
+    function test_isLocked() public {
+        assertFalse(Locker.isLocked());
+
+        Locker.setLockerAndCaller(ADDRESS_AS, ADDRESS_BS);
+
+        assertTrue(Locker.isLocked());
+
+        Locker.clearLockerAndCaller();
+
+        assertFalse(Locker.isLocked());
+    }
+
+    function test_incrementNonzeroDeltaCount() public {
+        Locker.incrementNonzeroDeltaCount();
+        assertEq(Locker.nonzeroDeltaCount(), 1);
+    }
+
+    function test_decrementNonzeroDeltaCount() public {
+        Locker.incrementNonzeroDeltaCount();
+        Locker.decrementNonzeroDeltaCount();
+        assertEq(Locker.nonzeroDeltaCount(), 0);
+    }
+
+    // Reading from right to left. Bit of 0: call increase. Bit of 1: call decrease.
+    // The library allows over over/underflow so we dont check for that here
+    function test_nonZeroDeltaCount_fuzz(uint256 instructions) public {
+        uint256 expectedCount;
+        for (uint256 i = 0; i < 256; i++) {
+            if ((instructions & (1 << i)) == 0) {
+                Locker.incrementNonzeroDeltaCount();
+                unchecked {
+                    expectedCount++;
+                }
+            } else {
+                Locker.decrementNonzeroDeltaCount();
+                unchecked {
+                    expectedCount--;
+                }
+            }
+            assertEq(Locker.nonzeroDeltaCount(), expectedCount);
+        }
+    }
+}
diff --git a/test/LockersLibrary.t.sol b/test/LockersLibrary.t.sol
deleted file mode 100644
index 00791bb60..000000000
--- a/test/LockersLibrary.t.sol
+++ /dev/null
@@ -1,71 +0,0 @@
-pragma solidity ^0.8.20;
-
-import {Test} from "forge-std/Test.sol";
-import {Vm} from "forge-std/Vm.sol";
-import {PoolManager} from "../src/PoolManager.sol";
-import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
-import {Deployers} from "./utils/Deployers.sol";
-import {ILockCallback} from "../src/interfaces/callback/ILockCallback.sol";
-import {Currency, CurrencyLibrary} from "../src/types/Currency.sol";
-import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
-import {PoolKey} from "../src/types/PoolKey.sol";
-import {IHooks} from "../src/interfaces/IHooks.sol";
-import {Locker} from "../src/libraries/Locker.sol";
-
-contract LockersLibraryTest is Test, Deployers, ILockCallback {
-    using CurrencyLibrary for Currency;
-
-    uint256 constant LOCKERS_OFFSET = uint256(1);
-
-    function setUp() public {
-        initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0)));
-    }
-
-    function testLockerLengthAndNonzeroDeltaCount() public {
-        (uint256 nonzeroDeltaCountDuringCallback) = abi.decode(manager.lock(address(this), ""), (uint256));
-        assertEq(nonzeroDeltaCountDuringCallback, 1);
-        assertEq(manager.getLockNonzeroDeltaCount(), 0);
-    }
-
-    function lockAcquired(address, bytes calldata) public returns (bytes memory) {
-        // apply a delta and save count
-        manager.take(key.currency0, address(this), 1);
-        uint256 count = manager.getLockNonzeroDeltaCount();
-        key.currency0.transfer(address(manager), 1);
-        manager.settle(key.currency0);
-
-        bytes memory data = abi.encode(count);
-        return data;
-    }
-
-    function test_incrementNonzeroDeltaCount() public {
-        Locker.incrementNonzeroDeltaCount();
-        assertEq(Locker.nonzeroDeltaCount(), 1);
-    }
-
-    function test_incrementNonzeroDeltaCountFuzz(uint8 count) public {
-        for (uint256 i = 0; i < count; i++) {
-            Locker.incrementNonzeroDeltaCount();
-            assertEq(Locker.nonzeroDeltaCount(), i + 1);
-        }
-    }
-
-    function test_decrementNonzeroDeltaCount() public {
-        Locker.incrementNonzeroDeltaCount();
-        Locker.decrementNonzeroDeltaCount();
-        assertEq(Locker.nonzeroDeltaCount(), 0);
-    }
-
-    function test_decrementNonzeroDeltaCountFuzz(uint8 count) public {
-        for (uint256 i = 0; i < count; i++) {
-            Locker.incrementNonzeroDeltaCount();
-        }
-
-        assertEq(Locker.nonzeroDeltaCount(), count);
-
-        for (uint256 i = 0; i < count; i++) {
-            Locker.decrementNonzeroDeltaCount();
-            assertEq(Locker.nonzeroDeltaCount(), count - i - 1);
-        }
-    }
-}

From c0e2722590ba18223249ac0071c6e40399103387 Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Tue, 12 Dec 2023 14:34:57 -0300
Subject: [PATCH 05/19] Rename empty lock test

---
 src/libraries/Locker.sol                             |  2 +-
 src/test/{PoolLockTest.sol => PoolEmptyLockTest.sol} |  2 +-
 test/PoolManager.t.sol                               | 12 ++++++------
 3 files changed, 8 insertions(+), 8 deletions(-)
 rename src/test/{PoolLockTest.sol => PoolEmptyLockTest.sol} (93%)

diff --git a/src/libraries/Locker.sol b/src/libraries/Locker.sol
index e1320f933..c37ab411c 100644
--- a/src/libraries/Locker.sol
+++ b/src/libraries/Locker.sol
@@ -69,7 +69,7 @@ library Locker {
     }
 
     /// @notice Potential to underflow.
-    /// Current usage ensures this will not happen because we call decrememnt with known boundaries (only up to the numer of times we call increment).
+    /// Current usage ensures this will not happen because we call decrememnt with known boundaries (only up to the number of times we call increment).
     function decrementNonzeroDeltaCount() internal {
         uint256 slot = NONZERO_DELTA_COUNT;
         assembly {
diff --git a/src/test/PoolLockTest.sol b/src/test/PoolEmptyLockTest.sol
similarity index 93%
rename from src/test/PoolLockTest.sol
rename to src/test/PoolEmptyLockTest.sol
index a312fcf2f..3ff803336 100644
--- a/src/test/PoolLockTest.sol
+++ b/src/test/PoolEmptyLockTest.sol
@@ -4,7 +4,7 @@ pragma solidity ^0.8.20;
 import {IPoolManager} from "../interfaces/IPoolManager.sol";
 import {ILockCallback} from "../interfaces/callback/ILockCallback.sol";
 
-contract PoolLockTest is ILockCallback {
+contract PoolEmptyLockTest is ILockCallback {
     event LockAcquired();
 
     IPoolManager manager;
diff --git a/test/PoolManager.t.sol b/test/PoolManager.t.sol
index ba24f930a..96c60d738 100644
--- a/test/PoolManager.t.sol
+++ b/test/PoolManager.t.sol
@@ -22,7 +22,7 @@ import {BalanceDelta, BalanceDeltaLibrary} from "../src/types/BalanceDelta.sol";
 import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
 import {TestInvalidERC20} from "../src/test/TestInvalidERC20.sol";
 import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
-import {PoolLockTest} from "../src/test/PoolLockTest.sol";
+import {PoolEmptyLockTest} from "../src/test/PoolEmptyLockTest.sol";
 import {PoolId, PoolIdLibrary} from "../src/types/PoolId.sol";
 import {FeeLibrary} from "../src/libraries/FeeLibrary.sol";
 import {Position} from "../src/libraries/Position.sol";
@@ -52,7 +52,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
     event Burn(address indexed from, Currency indexed currency, uint256 amount);
     event ProtocolFeeUpdated(PoolId indexed id, uint16 protocolFee);
 
-    PoolLockTest lockTest;
+    PoolEmptyLockTest emptyLockRouter;
 
     address ADDRESS_ZERO = address(0);
     address EMPTY_HOOKS = address(0xf000000000000000000000000000000000000000);
@@ -61,7 +61,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
     function setUp() public {
         initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0)));
 
-        lockTest = new PoolLockTest(manager);
+        emptyLockRouter = new PoolEmptyLockTest(manager);
     }
 
     function test_bytecodeSize() public {
@@ -1115,16 +1115,16 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
         assertEq(manager.protocolFeesAccrued(nativeCurrency), 0);
     }
 
-    function test_lock_NoOpIsOk() public {
+    function test_lock_NoOp_gas() public {
         snapStart("gas overhead of no-op lock");
-        lockTest.lock();
+        emptyLockRouter.lock();
         snapEnd();
     }
 
     function test_lock_EmitsCorrectId() public {
         vm.expectEmit(false, false, false, true);
         emit LockAcquired();
-        lockTest.lock();
+        emptyLockRouter.lock();
     }
 
     // function testExtsloadForPoolPrice() public {

From 2237a48c1dfc1459bf0c2be2a579fb4919089427 Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Tue, 12 Dec 2023 20:18:25 -0300
Subject: [PATCH 06/19] Test skeleton

---
 src/interfaces/IPoolManager.sol    |   4 +-
 src/test/PoolNestedActionsTest.sol | 135 +++++++++++++++++++++++++++++
 test/NestedActions.t.sol           |  14 +++
 test/PoolManager.t.sol             |  31 ++++---
 test/PoolManagerInitialize.t.sol   |  14 ++-
 test/utils/Constants.sol           |   6 ++
 test/utils/Deployers.sol           |   6 +-
 7 files changed, 186 insertions(+), 24 deletions(-)
 create mode 100644 src/test/PoolNestedActionsTest.sol
 create mode 100644 test/NestedActions.t.sol

diff --git a/src/interfaces/IPoolManager.sol b/src/interfaces/IPoolManager.sol
index f9121676f..dfdb53107 100644
--- a/src/interfaces/IPoolManager.sol
+++ b/src/interfaces/IPoolManager.sol
@@ -21,11 +21,11 @@ interface IPoolManager is IFees, IClaims {
     /// @notice Thrown when trying to interact with a non-initialized pool
     error PoolNotInitialized();
 
-    /// @notice Thrown when a function is called by an address that is not the current locker
+    /// @notice Thrown when lock is called, but a lock is already open
     /// @param locker The current locker
     error LockedBy(address locker);
 
-    /// @notice Thrown when a function is called by an address that is not the current locker
+    /// @notice Thrown when a function is called outside of a lock
     error ManagerNotLocked();
 
     /// @notice The ERC1155 being deposited is not the Uniswap ERC1155
diff --git a/src/test/PoolNestedActionsTest.sol b/src/test/PoolNestedActionsTest.sol
new file mode 100644
index 000000000..7dab785b0
--- /dev/null
+++ b/src/test/PoolNestedActionsTest.sol
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: UNLICENSED
+pragma solidity ^0.8.20;
+
+import {IPoolManager} from "../interfaces/IPoolManager.sol";
+import {ILockCallback} from "../interfaces/callback/ILockCallback.sol";
+import {PoolTestBase} from "./PoolTestBase.sol";
+import {PoolKey} from "../types/PoolKey.sol";
+import {Constants} from "../../test/utils/Constants.sol";
+import {Test} from "forge-std/Test.sol";
+import {BalanceDelta} from "../types/BalanceDelta.sol";
+import {Currency} from "../types/Currency.sol";
+
+enum Action {
+    NESTED_SELF_LOCK,
+    NESTED_EXECUTOR_LOCK,
+    SWAP_AND_SETTLE,
+    DONATE_AND_SETTLE,
+    ADD_LIQ_AND_SETTLE,
+    REMOVE_LIQ_AND_SETTLE
+}
+
+contract PoolNestedActionsTest is Test, ILockCallback {
+    IPoolManager manager;
+    NestedActionExecutor public executor;
+
+    constructor(IPoolManager _manager) {
+        manager = _manager;
+        executor = new NestedActionExecutor(manager);
+    }
+
+    function lock(Action[] memory actions) external {
+        manager.lock(address(this), abi.encode(actions));
+    }
+
+    /// @notice Called by the pool manager on `msg.sender` when a lock is acquired
+    function lockAcquired(address, bytes calldata data) external override returns (bytes memory) {
+        Action[] memory actions = abi.decode(data, (Action[]));
+        if (actions.length == 1 && actions[0] == Action.NESTED_SELF_LOCK) {
+            _nestedLock();
+        } else {
+            executor.execute(actions);
+        }
+        return "";
+    }
+
+    function _nestedLock() internal {
+        (address locker, address lockCaller) = manager.getLock();
+        assertEq(locker, address(this));
+        assertEq(lockCaller, address(this));
+
+        vm.expectRevert(abi.encodeWithSelector(IPoolManager.LockedBy.selector, address(this)));
+        manager.lock(address(this), "");
+
+        (locker, lockCaller) = manager.getLock();
+        assertEq(locker, address(this));
+        assertEq(lockCaller, address(this));
+    }
+}
+
+contract NestedActionExecutor is Test, PoolTestBase {
+    PoolKey internal key;
+
+    error KeyNotSet();
+
+    IPoolManager.ModifyPositionParams internal ADD_LIQ_PARAMS =
+        IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1e18});
+
+    IPoolManager.ModifyPositionParams internal REMOVE_LIQ_PARAMS =
+        IPoolManager.ModifyPositionParams({tickLower: -120, tickUpper: 120, liquidityDelta: -1e18});
+
+    IPoolManager.SwapParams internal SWAP_PARAMS =
+        IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: Constants.SQRT_RATIO_1_2});
+
+    constructor(IPoolManager _manager) PoolTestBase(_manager) {}
+
+    function setKey(PoolKey memory _key) external {
+        key = _key;
+    }
+
+    function execute(Action[] memory actions) public {
+        if (Currency.unwrap(key.currency0) == address(0)) revert KeyNotSet();
+        for (uint256 i = 0; i < actions.length; i++) {
+            Action action = actions[i];
+            if (action == Action.NESTED_EXECUTOR_LOCK) _nestedLock();
+            else if (action == Action.SWAP_AND_SETTLE) _swap();
+            else if (action == Action.ADD_LIQ_AND_SETTLE) _addLiquidity();
+            else if (action == Action.REMOVE_LIQ_AND_SETTLE) _removeLiquidity();
+            else if (action == Action.DONATE_AND_SETTLE) _donate();
+        }
+    }
+
+    function _nestedLock() internal {
+        (address locker, address lockCaller) = manager.getLock();
+        assertEq(locker, msg.sender);
+        assertEq(lockCaller, msg.sender);
+
+        vm.expectRevert(abi.encodeWithSelector(IPoolManager.LockedBy.selector, msg.sender));
+        manager.lock(address(this), "");
+
+        (locker, lockCaller) = manager.getLock();
+        assertEq(locker, msg.sender);
+        assertEq(lockCaller, msg.sender);
+    }
+
+    function _swap() internal {
+        // swap without a lock, checking that the deltas are applied to this contract's address
+        (,,, int256 deltaLockerBefore0) = _fetchBalances(key.currency0, msg.sender);
+        (,,, int256 deltaLockerBefore1) = _fetchBalances(key.currency1, msg.sender);
+        (,,, int256 deltaThisBefore0) = _fetchBalances(key.currency0, address(this));
+        (,,, int256 deltaThisBefore1) = _fetchBalances(key.currency1, address(this));
+
+        BalanceDelta delta = manager.swap(key, SWAP_PARAMS, "");
+
+        (,,, int256 deltaLockerAfter0) = _fetchBalances(key.currency0, msg.sender);
+        (,,, int256 deltaLockerAfter1) = _fetchBalances(key.currency1, msg.sender);
+        (,,, int256 deltaThisAfter0) = _fetchBalances(key.currency0, address(this));
+        (,,, int256 deltaThisAfter1) = _fetchBalances(key.currency1, address(this));
+
+        assertEq(deltaLockerBefore0, deltaLockerAfter0);
+        assertEq(deltaLockerBefore1, deltaLockerAfter1);
+        assertEq(deltaThisBefore0 + SWAP_PARAMS.amountSpecified, deltaThisAfter0);
+        assertEq(deltaThisBefore1 - 98, deltaThisAfter1);
+        assertEq(delta.amount0(), deltaThisAfter0);
+        assertEq(delta.amount1(), deltaThisAfter1);
+    }
+
+    function _addLiquidity() internal {}
+    function _removeLiquidity() internal {}
+    function _donate() internal {}
+
+    // This will never actually be used - its just to allow us to use the PoolTestBase helper contact
+    function lockAcquired(address, bytes calldata) external pure override returns (bytes memory) {
+        return "";
+    }
+}
diff --git a/test/NestedActions.t.sol b/test/NestedActions.t.sol
new file mode 100644
index 000000000..411e433bc
--- /dev/null
+++ b/test/NestedActions.t.sol
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: UNLICENSED
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {Deployers} from "./utils/Deployers.sol";
+import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
+import {Action} from "../src/test/PoolNestedActionsTest.sol";
+import {IHooks} from "../src/interfaces/IHooks.sol";
+
+contract NestedActions is Test, Deployers, GasSnapshot {
+    function setUp() public {
+        initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0)));
+    }
+}
diff --git a/test/PoolManager.t.sol b/test/PoolManager.t.sol
index 96c60d738..9680112b7 100644
--- a/test/PoolManager.t.sol
+++ b/test/PoolManager.t.sol
@@ -2,13 +2,10 @@
 pragma solidity ^0.8.20;
 
 import {Test} from "forge-std/Test.sol";
-import {Vm} from "forge-std/Vm.sol";
 import {IHooks} from "../src/interfaces/IHooks.sol";
 import {Hooks} from "../src/libraries/Hooks.sol";
 import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
 import {IFees} from "../src/interfaces/IFees.sol";
-import {IProtocolFeeController} from "../src/interfaces/IProtocolFeeController.sol";
-import {PoolManager} from "../src/PoolManager.sol";
 import {TickMath} from "../src/libraries/TickMath.sol";
 import {Pool} from "../src/libraries/Pool.sol";
 import {Deployers} from "./utils/Deployers.sol";
@@ -23,9 +20,11 @@ import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
 import {TestInvalidERC20} from "../src/test/TestInvalidERC20.sol";
 import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
 import {PoolEmptyLockTest} from "../src/test/PoolEmptyLockTest.sol";
+import {Action} from "../src/test/PoolNestedActionsTest.sol";
 import {PoolId, PoolIdLibrary} from "../src/types/PoolId.sol";
 import {FeeLibrary} from "../src/libraries/FeeLibrary.sol";
 import {Position} from "../src/libraries/Position.sol";
+import {Constants} from "./utils/Constants.sol";
 
 contract PoolManagerTest is Test, Deployers, GasSnapshot {
     using Hooks for IHooks;
@@ -54,10 +53,6 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
     PoolEmptyLockTest emptyLockRouter;
 
-    address ADDRESS_ZERO = address(0);
-    address EMPTY_HOOKS = address(0xf000000000000000000000000000000000000000);
-    address MOCK_HOOKS = address(0xfF00000000000000000000000000000000000000);
-
     function setUp() public {
         initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0)));
 
@@ -117,7 +112,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
         address payable mockAddr =
             payable(address(uint160(Hooks.BEFORE_MODIFY_POSITION_FLAG | Hooks.AFTER_MODIFY_POSITION_FLAG)));
-        address payable hookAddr = payable(MOCK_HOOKS);
+        address payable hookAddr = payable(Constants.MOCK_HOOKS);
 
         vm.etch(hookAddr, vm.getDeployedCode("EmptyTestHooks.sol:EmptyTestHooks"));
         MockContract mockContract = new MockContract();
@@ -199,7 +194,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
     }
 
     function test_mint_withHooks_gas() public {
-        address hookEmptyAddr = EMPTY_HOOKS;
+        address hookEmptyAddr = Constants.EMPTY_HOOKS;
         MockHooks impl = new MockHooks();
         vm.etch(hookEmptyAddr, address(impl).code);
         MockHooks mockHooks = MockHooks(hookEmptyAddr);
@@ -212,7 +207,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
     }
 
     function test_mint_withHooks_EOAInitiated() public {
-        address hookEmptyAddr = EMPTY_HOOKS;
+        address hookEmptyAddr = Constants.EMPTY_HOOKS;
         MockHooks impl = new MockHooks();
         vm.etch(hookEmptyAddr, address(impl).code);
         MockHooks mockHooks = MockHooks(hookEmptyAddr);
@@ -363,7 +358,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
     function test_swap_succeedsWithHooksIfInitialized() public {
         address payable mockAddr = payable(address(uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.AFTER_SWAP_FLAG)));
-        address payable hookAddr = payable(MOCK_HOOKS);
+        address payable hookAddr = payable(Constants.MOCK_HOOKS);
 
         vm.etch(hookAddr, vm.getDeployedCode("EmptyTestHooks.sol:EmptyTestHooks"));
         MockContract mockContract = new MockContract();
@@ -470,7 +465,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
     }
 
     function test_swap_withHooks_gas() public {
-        address hookEmptyAddr = EMPTY_HOOKS;
+        address hookEmptyAddr = Constants.EMPTY_HOOKS;
 
         MockHooks impl = new MockHooks();
         vm.etch(hookEmptyAddr, address(impl).code);
@@ -1127,6 +1122,18 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
         emptyLockRouter.lock();
     }
 
+    Action[] actions;
+
+    function test_lock_cannotBeCalledTwiceByLocker() public {
+        actions = [Action.NESTED_SELF_LOCK];
+        nestedActionRouter.lock(actions);
+    }
+
+    function test_lock_cannotBeCalledTwiceByDifferentLockers() public {
+        actions = [Action.NESTED_EXECUTOR_LOCK];
+        nestedActionRouter.lock(actions);
+    }
+
     // function testExtsloadForPoolPrice() public {
     //     IPoolManager.key = IPoolManager.PoolKey({
     //         currency0: currency0,
diff --git a/test/PoolManagerInitialize.t.sol b/test/PoolManagerInitialize.t.sol
index 313e439d7..75a8d8544 100644
--- a/test/PoolManagerInitialize.t.sol
+++ b/test/PoolManagerInitialize.t.sol
@@ -10,6 +10,7 @@ import {PoolManager} from "../src/PoolManager.sol";
 import {TickMath} from "../src/libraries/TickMath.sol";
 import {Pool} from "../src/libraries/Pool.sol";
 import {Deployers} from "./utils/Deployers.sol";
+import {Constants} from "./utils/Constants.sol";
 import {Currency, CurrencyLibrary} from "../src/types/Currency.sol";
 import {MockHooks} from "../src/test/MockHooks.sol";
 import {MockContract} from "../src/test/MockContract.sol";
@@ -35,11 +36,6 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot {
         IHooks hooks
     );
 
-    address ADDRESS_ZERO = address(0);
-    address EMPTY_HOOKS = address(0xf000000000000000000000000000000000000000);
-    address ALL_HOOKS = address(0xff00000000000000000000000000000000000001);
-    address MOCK_HOOKS = address(0xfF00000000000000000000000000000000000000);
-
     function setUp() public {
         deployFreshManagerAndRouters();
         (currency0, currency1) = deployMintAndApprove2Currencies();
@@ -48,7 +44,7 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot {
             currency0: currency0,
             currency1: currency1,
             fee: 3000,
-            hooks: IHooks(ADDRESS_ZERO),
+            hooks: IHooks(Constants.ADDRESS_ZERO),
             tickSpacing: 60
         });
     }
@@ -58,7 +54,7 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot {
         sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_RATIO, TickMath.MAX_SQRT_RATIO - 1));
 
         // tested in Hooks.t.sol
-        key0.hooks = IHooks(ADDRESS_ZERO);
+        key0.hooks = IHooks(Constants.ADDRESS_ZERO);
 
         if (key0.fee & FeeLibrary.STATIC_FEE_MASK >= 1000000) {
             vm.expectRevert(abi.encodeWithSelector(IFees.FeeTooLarge.selector));
@@ -113,7 +109,7 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot {
         sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_RATIO, TickMath.MAX_SQRT_RATIO - 1));
 
         address payable mockAddr = payable(address(uint160(Hooks.BEFORE_INITIALIZE_FLAG | Hooks.AFTER_INITIALIZE_FLAG)));
-        address payable hookAddr = payable(MOCK_HOOKS);
+        address payable hookAddr = payable(Constants.MOCK_HOOKS);
 
         vm.etch(hookAddr, vm.getDeployedCode("EmptyTestHooks.sol:EmptyTestHooks"));
         MockContract mockContract = new MockContract();
@@ -163,7 +159,7 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot {
         // Assumptions tested in Pool.t.sol
         sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_RATIO, TickMath.MAX_SQRT_RATIO - 1));
 
-        address hookEmptyAddr = EMPTY_HOOKS;
+        address hookEmptyAddr = Constants.EMPTY_HOOKS;
 
         MockHooks impl = new MockHooks();
         vm.etch(hookEmptyAddr, address(impl).code);
diff --git a/test/utils/Constants.sol b/test/utils/Constants.sol
index 354a2d394..5df565aac 100644
--- a/test/utils/Constants.sol
+++ b/test/utils/Constants.sol
@@ -13,10 +13,16 @@ library Constants {
     uint128 constant MAX_UINT128 = type(uint128).max;
     uint160 constant MAX_UINT160 = type(uint160).max;
 
+    address constant ADDRESS_ZERO = address(0);
+    address constant EMPTY_HOOKS = address(0xf000000000000000000000000000000000000000);
+    address constant MOCK_HOOKS = address(0xfF00000000000000000000000000000000000000);
+
     uint256 constant POOL_SLOT = 10;
     uint256 constant TICKS_OFFSET = 4;
 
     uint24 constant FEE_LOW = 500;
     uint24 constant FEE_MEDIUM = 3000;
     uint24 constant FEE_HIGH = 10000;
+
+    bytes constant ZERO_BYTES = new bytes(0);
 }
diff --git a/test/utils/Deployers.sol b/test/utils/Deployers.sol
index a891bf6c5..e676b08a1 100644
--- a/test/utils/Deployers.sol
+++ b/test/utils/Deployers.sol
@@ -16,6 +16,7 @@ import {PoolModifyPositionTest} from "../../src/test/PoolModifyPositionTest.sol"
 import {PoolSwapTest} from "../../src/test/PoolSwapTest.sol";
 import {PoolInitializeTest} from "../../src/test/PoolInitializeTest.sol";
 import {PoolDonateTest} from "../../src/test/PoolDonateTest.sol";
+import {PoolNestedActionsTest} from "../../src/test/PoolNestedActionsTest.sol";
 import {PoolTakeTest} from "../../src/test/PoolTakeTest.sol";
 import {
     ProtocolFeeControllerTest,
@@ -30,7 +31,7 @@ contract Deployers {
     using PoolIdLibrary for PoolKey;
 
     // Helpful test constants
-    bytes constant ZERO_BYTES = new bytes(0);
+    bytes constant ZERO_BYTES = Constants.ZERO_BYTES;
     uint160 constant SQRT_RATIO_1_1 = Constants.SQRT_RATIO_1_1;
     uint160 constant SQRT_RATIO_1_2 = Constants.SQRT_RATIO_1_2;
     uint160 constant SQRT_RATIO_1_4 = Constants.SQRT_RATIO_1_4;
@@ -48,6 +49,7 @@ contract Deployers {
     PoolDonateTest donateRouter;
     PoolTakeTest takeRouter;
     PoolInitializeTest initializeRouter;
+    PoolNestedActionsTest nestedActionRouter;
     ProtocolFeeControllerTest feeController;
     RevertingProtocolFeeControllerTest revertingFeeController;
     OutOfBoundsProtocolFeeControllerTest outOfBoundsFeeController;
@@ -70,6 +72,7 @@ contract Deployers {
         donateRouter = new PoolDonateTest(manager);
         takeRouter = new PoolTakeTest(manager);
         initializeRouter = new PoolInitializeTest(manager);
+        nestedActionRouter = new PoolNestedActionsTest(manager);
         feeController = new ProtocolFeeControllerTest();
         revertingFeeController = new RevertingProtocolFeeControllerTest();
         outOfBoundsFeeController = new OutOfBoundsProtocolFeeControllerTest();
@@ -150,6 +153,7 @@ contract Deployers {
         // sets the global currencyies and key
         (currency0, currency1) = deployMintAndApprove2Currencies();
         (key,) = initPoolAndAddLiquidity(currency0, currency1, hooks, 3000, SQRT_RATIO_1_1, ZERO_BYTES);
+        nestedActionRouter.executor().setKey(key);
         (nativeKey,) = initPoolAndAddLiquidityETH(
             CurrencyLibrary.NATIVE, currency1, hooks, 3000, SQRT_RATIO_1_1, ZERO_BYTES, 1 ether
         );

From df58a4560a44c4f27597f7022248d4e205b86ab3 Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Wed, 13 Dec 2023 15:59:03 -0300
Subject: [PATCH 07/19] Test for a nested swap

---
 ...swap hook, already cached dynamic fee.snap |  2 +-
 .../cached dynamic fee, no hooks.snap         |  2 +-
 .forge-snapshots/donate gas with 1 token.snap |  2 +-
 .../donate gas with 2 tokens.snap             |  2 +-
 .forge-snapshots/mint with empty hook.snap    |  2 +-
 .forge-snapshots/mint with native token.snap  |  2 +-
 .forge-snapshots/mint.snap                    |  2 +-
 .../mintWithEmptyHookEOAInitiated.snap        |  2 +-
 .../modify position with noop.snap            |  2 +-
 .forge-snapshots/simple swap with native.snap |  2 +-
 .forge-snapshots/simple swap.snap             |  2 +-
 .forge-snapshots/simpleSwapEOAInitiated.snap  |  2 +-
 .../simpleSwapNativeEOAInitiated.snap         |  2 +-
 ...p against liquidity with native token.snap |  2 +-
 .forge-snapshots/swap against liquidity.snap  |  2 +-
 .../swap burn claim for input.snap            |  2 +-
 .../swap mint output as claim.snap            |  2 +-
 .forge-snapshots/swap with dynamic fee.snap   |  2 +-
 .forge-snapshots/swap with hooks.snap         |  2 +-
 .forge-snapshots/swap with noop.snap          |  2 +-
 .../update dynamic fee in before swap.snap    |  2 +-
 src/test/PoolDonateTest.sol                   | 10 ++--
 src/test/PoolModifyPositionTest.sol           |  4 +-
 src/test/PoolNestedActionsTest.sol            | 60 +++++++++++--------
 src/test/PoolSwapTest.sol                     | 10 ++--
 src/test/PoolTakeTest.sol                     |  4 +-
 src/test/PoolTestBase.sol                     |  4 +-
 test/Claims.t.sol                             |  2 +-
 test/NestedActions.t.sol                      |  7 +++
 test/PoolManager.t.sol                        |  4 +-
 test/utils/Deployers.sol                      | 12 +++-
 31 files changed, 93 insertions(+), 66 deletions(-)

diff --git a/.forge-snapshots/before swap hook, already cached dynamic fee.snap b/.forge-snapshots/before swap hook, already cached dynamic fee.snap
index 49651fee8..e744af944 100644
--- a/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
+++ b/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
@@ -1 +1 @@
-186339
\ No newline at end of file
+186371
\ No newline at end of file
diff --git a/.forge-snapshots/cached dynamic fee, no hooks.snap b/.forge-snapshots/cached dynamic fee, no hooks.snap
index 0ca1c73f5..91a45478c 100644
--- a/.forge-snapshots/cached dynamic fee, no hooks.snap	
+++ b/.forge-snapshots/cached dynamic fee, no hooks.snap	
@@ -1 +1 @@
-140324
\ No newline at end of file
+140356
\ No newline at end of file
diff --git a/.forge-snapshots/donate gas with 1 token.snap b/.forge-snapshots/donate gas with 1 token.snap
index 73790f19f..496f8cfa1 100644
--- a/.forge-snapshots/donate gas with 1 token.snap	
+++ b/.forge-snapshots/donate gas with 1 token.snap	
@@ -1 +1 @@
-133211
\ No newline at end of file
+133243
\ No newline at end of file
diff --git a/.forge-snapshots/donate gas with 2 tokens.snap b/.forge-snapshots/donate gas with 2 tokens.snap
index 6c5a6b118..d856f5032 100644
--- a/.forge-snapshots/donate gas with 2 tokens.snap	
+++ b/.forge-snapshots/donate gas with 2 tokens.snap	
@@ -1 +1 @@
-178421
\ No newline at end of file
+178453
\ No newline at end of file
diff --git a/.forge-snapshots/mint with empty hook.snap b/.forge-snapshots/mint with empty hook.snap
index 5fa2837ed..362a8928c 100644
--- a/.forge-snapshots/mint with empty hook.snap	
+++ b/.forge-snapshots/mint with empty hook.snap	
@@ -1 +1 @@
-312975
\ No newline at end of file
+312991
\ No newline at end of file
diff --git a/.forge-snapshots/mint with native token.snap b/.forge-snapshots/mint with native token.snap
index 655b85cd6..28a16f7f2 100644
--- a/.forge-snapshots/mint with native token.snap	
+++ b/.forge-snapshots/mint with native token.snap	
@@ -1 +1 @@
-193093
\ No newline at end of file
+193109
\ No newline at end of file
diff --git a/.forge-snapshots/mint.snap b/.forge-snapshots/mint.snap
index 95b04a94a..6f56e397c 100644
--- a/.forge-snapshots/mint.snap
+++ b/.forge-snapshots/mint.snap
@@ -1 +1 @@
-193035
\ No newline at end of file
+193051
\ No newline at end of file
diff --git a/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap b/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
index efb2e0bff..e5201eeda 100644
--- a/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
+++ b/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
@@ -1 +1 @@
-247083
\ No newline at end of file
+247099
\ No newline at end of file
diff --git a/.forge-snapshots/modify position with noop.snap b/.forge-snapshots/modify position with noop.snap
index 7c1d70534..57114e0b6 100644
--- a/.forge-snapshots/modify position with noop.snap	
+++ b/.forge-snapshots/modify position with noop.snap	
@@ -1 +1 @@
-53978
\ No newline at end of file
+53994
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap with native.snap b/.forge-snapshots/simple swap with native.snap
index 90b62aa48..ded864bdb 100644
--- a/.forge-snapshots/simple swap with native.snap	
+++ b/.forge-snapshots/simple swap with native.snap	
@@ -1 +1 @@
-188866
\ No newline at end of file
+188898
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap.snap b/.forge-snapshots/simple swap.snap
index 3a15f03d9..207dd1533 100644
--- a/.forge-snapshots/simple swap.snap	
+++ b/.forge-snapshots/simple swap.snap	
@@ -1 +1 @@
-197434
\ No newline at end of file
+197466
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapEOAInitiated.snap b/.forge-snapshots/simpleSwapEOAInitiated.snap
index f40b6a487..247afd567 100644
--- a/.forge-snapshots/simpleSwapEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapEOAInitiated.snap
@@ -1 +1 @@
-168722
\ No newline at end of file
+168754
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
index d3e4b0504..ff96fb216 100644
--- a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
@@ -1 +1 @@
-165384
\ No newline at end of file
+165416
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity with native token.snap b/.forge-snapshots/swap against liquidity with native token.snap
index 647f29ebc..4397e15d9 100644
--- a/.forge-snapshots/swap against liquidity with native token.snap	
+++ b/.forge-snapshots/swap against liquidity with native token.snap	
@@ -1 +1 @@
-119494
\ No newline at end of file
+119526
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity.snap b/.forge-snapshots/swap against liquidity.snap
index ff97d120f..e7b48f7f1 100644
--- a/.forge-snapshots/swap against liquidity.snap	
+++ b/.forge-snapshots/swap against liquidity.snap	
@@ -1 +1 @@
-106985
\ No newline at end of file
+107017
\ No newline at end of file
diff --git a/.forge-snapshots/swap burn claim for input.snap b/.forge-snapshots/swap burn claim for input.snap
index 35c806bf3..24657ba24 100644
--- a/.forge-snapshots/swap burn claim for input.snap	
+++ b/.forge-snapshots/swap burn claim for input.snap	
@@ -1 +1 @@
-126158
\ No newline at end of file
+126190
\ No newline at end of file
diff --git a/.forge-snapshots/swap mint output as claim.snap b/.forge-snapshots/swap mint output as claim.snap
index 3b23424b0..977ecd4f7 100644
--- a/.forge-snapshots/swap mint output as claim.snap	
+++ b/.forge-snapshots/swap mint output as claim.snap	
@@ -1 +1 @@
-209649
\ No newline at end of file
+209681
\ No newline at end of file
diff --git a/.forge-snapshots/swap with dynamic fee.snap b/.forge-snapshots/swap with dynamic fee.snap
index a0decf59e..6342b3e61 100644
--- a/.forge-snapshots/swap with dynamic fee.snap	
+++ b/.forge-snapshots/swap with dynamic fee.snap	
@@ -1 +1 @@
-185440
\ No newline at end of file
+185472
\ No newline at end of file
diff --git a/.forge-snapshots/swap with hooks.snap b/.forge-snapshots/swap with hooks.snap
index 4ebfef2b9..6aeeee515 100644
--- a/.forge-snapshots/swap with hooks.snap	
+++ b/.forge-snapshots/swap with hooks.snap	
@@ -1 +1 @@
-106963
\ No newline at end of file
+106995
\ No newline at end of file
diff --git a/.forge-snapshots/swap with noop.snap b/.forge-snapshots/swap with noop.snap
index 1053b45e4..b5aea2f8c 100644
--- a/.forge-snapshots/swap with noop.snap	
+++ b/.forge-snapshots/swap with noop.snap	
@@ -1 +1 @@
-47361
\ No newline at end of file
+47393
\ No newline at end of file
diff --git a/.forge-snapshots/update dynamic fee in before swap.snap b/.forge-snapshots/update dynamic fee in before swap.snap
index cb5df9a3e..0ef257265 100644
--- a/.forge-snapshots/update dynamic fee in before swap.snap	
+++ b/.forge-snapshots/update dynamic fee in before swap.snap	
@@ -1 +1 @@
-192160
\ No newline at end of file
+192192
\ No newline at end of file
diff --git a/src/test/PoolDonateTest.sol b/src/test/PoolDonateTest.sol
index 726104d6e..e1299b17b 100644
--- a/src/test/PoolDonateTest.sol
+++ b/src/test/PoolDonateTest.sol
@@ -45,16 +45,18 @@ contract PoolDonateTest is PoolTestBase, Test {
 
         CallbackData memory data = abi.decode(rawData, (CallbackData));
 
-        (,, uint256 reserveBefore0, int256 deltaBefore0) = _fetchBalances(data.key.currency0, data.sender);
-        (,, uint256 reserveBefore1, int256 deltaBefore1) = _fetchBalances(data.key.currency1, data.sender);
+        (,, uint256 reserveBefore0, int256 deltaBefore0) =
+            _fetchBalances(data.key.currency0, data.sender, address(this));
+        (,, uint256 reserveBefore1, int256 deltaBefore1) =
+            _fetchBalances(data.key.currency1, data.sender, address(this));
 
         assertEq(deltaBefore0, 0);
         assertEq(deltaBefore1, 0);
 
         BalanceDelta delta = manager.donate(data.key, data.amount0, data.amount1, data.hookData);
 
-        (,, uint256 reserveAfter0, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender);
-        (,, uint256 reserveAfter1, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender);
+        (,, uint256 reserveAfter0, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender, address(this));
+        (,, uint256 reserveAfter1, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender, address(this));
 
         assertEq(reserveBefore0, reserveAfter0);
         assertEq(reserveBefore1, reserveAfter1);
diff --git a/src/test/PoolModifyPositionTest.sol b/src/test/PoolModifyPositionTest.sol
index 6480730f5..780850e7d 100644
--- a/src/test/PoolModifyPositionTest.sol
+++ b/src/test/PoolModifyPositionTest.sol
@@ -47,8 +47,8 @@ contract PoolModifyPositionTest is Test, PoolTestBase {
 
         BalanceDelta delta = manager.modifyPosition(data.key, data.params, data.hookData);
 
-        (,,, int256 delta0) = _fetchBalances(data.key.currency0, data.sender);
-        (,,, int256 delta1) = _fetchBalances(data.key.currency1, data.sender);
+        (,,, int256 delta0) = _fetchBalances(data.key.currency0, data.sender, address(this));
+        (,,, int256 delta1) = _fetchBalances(data.key.currency1, data.sender, address(this));
 
         if (data.params.liquidityDelta > 0) {
             assert(delta0 > 0 || delta1 > 0 || data.key.hooks.hasPermission(Hooks.NO_OP_FLAG));
diff --git a/src/test/PoolNestedActionsTest.sol b/src/test/PoolNestedActionsTest.sol
index 7dab785b0..1db0e92a2 100644
--- a/src/test/PoolNestedActionsTest.sol
+++ b/src/test/PoolNestedActionsTest.sol
@@ -22,14 +22,12 @@ enum Action {
 contract PoolNestedActionsTest is Test, ILockCallback {
     IPoolManager manager;
     NestedActionExecutor public executor;
+    address user;
 
     constructor(IPoolManager _manager) {
         manager = _manager;
-        executor = new NestedActionExecutor(manager);
-    }
-
-    function lock(Action[] memory actions) external {
-        manager.lock(address(this), abi.encode(actions));
+        user = msg.sender;
+        executor = new NestedActionExecutor(manager, user);
     }
 
     /// @notice Called by the pool manager on `msg.sender` when a lock is acquired
@@ -46,19 +44,20 @@ contract PoolNestedActionsTest is Test, ILockCallback {
     function _nestedLock() internal {
         (address locker, address lockCaller) = manager.getLock();
         assertEq(locker, address(this));
-        assertEq(lockCaller, address(this));
+        assertEq(lockCaller, user);
 
         vm.expectRevert(abi.encodeWithSelector(IPoolManager.LockedBy.selector, address(this)));
         manager.lock(address(this), "");
 
         (locker, lockCaller) = manager.getLock();
         assertEq(locker, address(this));
-        assertEq(lockCaller, address(this));
+        assertEq(lockCaller, user);
     }
 }
 
 contract NestedActionExecutor is Test, PoolTestBase {
     PoolKey internal key;
+    address user;
 
     error KeyNotSet();
 
@@ -71,7 +70,9 @@ contract NestedActionExecutor is Test, PoolTestBase {
     IPoolManager.SwapParams internal SWAP_PARAMS =
         IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: Constants.SQRT_RATIO_1_2});
 
-    constructor(IPoolManager _manager) PoolTestBase(_manager) {}
+    constructor(IPoolManager _manager, address _user) PoolTestBase(_manager) {
+        user = _user;
+    }
 
     function setKey(PoolKey memory _key) external {
         key = _key;
@@ -92,36 +93,43 @@ contract NestedActionExecutor is Test, PoolTestBase {
     function _nestedLock() internal {
         (address locker, address lockCaller) = manager.getLock();
         assertEq(locker, msg.sender);
-        assertEq(lockCaller, msg.sender);
+        assertEq(lockCaller, user);
 
         vm.expectRevert(abi.encodeWithSelector(IPoolManager.LockedBy.selector, msg.sender));
         manager.lock(address(this), "");
 
         (locker, lockCaller) = manager.getLock();
         assertEq(locker, msg.sender);
-        assertEq(lockCaller, msg.sender);
+        assertEq(lockCaller, user);
     }
 
     function _swap() internal {
-        // swap without a lock, checking that the deltas are applied to this contract's address
-        (,,, int256 deltaLockerBefore0) = _fetchBalances(key.currency0, msg.sender);
-        (,,, int256 deltaLockerBefore1) = _fetchBalances(key.currency1, msg.sender);
-        (,,, int256 deltaThisBefore0) = _fetchBalances(key.currency0, address(this));
-        (,,, int256 deltaThisBefore1) = _fetchBalances(key.currency1, address(this));
+        (address locker, address lockCaller) = manager.getLock();
+
+        // swap without a lock, checking that the deltas are applied to this contract's address not the locker's address
+        assertTrue(locker != address(this), "Locker wrong");
+        assertEq(lockCaller, user);
+        (,,, int256 deltaLockerBefore0) = _fetchBalances(key.currency0, user, locker);
+        (,,, int256 deltaLockerBefore1) = _fetchBalances(key.currency1, user, locker);
+        (,,, int256 deltaThisBefore0) = _fetchBalances(key.currency0, user, address(this));
+        (,,, int256 deltaThisBefore1) = _fetchBalances(key.currency1, user, address(this));
 
         BalanceDelta delta = manager.swap(key, SWAP_PARAMS, "");
 
-        (,,, int256 deltaLockerAfter0) = _fetchBalances(key.currency0, msg.sender);
-        (,,, int256 deltaLockerAfter1) = _fetchBalances(key.currency1, msg.sender);
-        (,,, int256 deltaThisAfter0) = _fetchBalances(key.currency0, address(this));
-        (,,, int256 deltaThisAfter1) = _fetchBalances(key.currency1, address(this));
-
-        assertEq(deltaLockerBefore0, deltaLockerAfter0);
-        assertEq(deltaLockerBefore1, deltaLockerAfter1);
-        assertEq(deltaThisBefore0 + SWAP_PARAMS.amountSpecified, deltaThisAfter0);
-        assertEq(deltaThisBefore1 - 98, deltaThisAfter1);
-        assertEq(delta.amount0(), deltaThisAfter0);
-        assertEq(delta.amount1(), deltaThisAfter1);
+        (,,, int256 deltaLockerAfter0) = _fetchBalances(key.currency0, user, locker);
+        (,,, int256 deltaLockerAfter1) = _fetchBalances(key.currency1, user, locker);
+        (,,, int256 deltaThisAfter0) = _fetchBalances(key.currency0, user, address(this));
+        (,,, int256 deltaThisAfter1) = _fetchBalances(key.currency1, user, address(this));
+
+        assertEq(deltaLockerBefore0, deltaLockerAfter0, "Locker delta 0");
+        assertEq(deltaLockerBefore1, deltaLockerAfter1, "Locker delta 1");
+        assertEq(deltaThisBefore0 + SWAP_PARAMS.amountSpecified, deltaThisAfter0, "Executor delta 0");
+        assertEq(deltaThisBefore1 - 98, deltaThisAfter1, "Executor delta 1");
+        assertEq(delta.amount0(), deltaThisAfter0, "Swap delta 0");
+        assertEq(delta.amount1(), deltaThisAfter1, "Swap delta 1");
+
+        _settle(key.currency0, user, int128(deltaThisAfter0), true);
+        _take(key.currency1, user, int128(deltaThisAfter1), true);
     }
 
     function _addLiquidity() internal {}
diff --git a/src/test/PoolSwapTest.sol b/src/test/PoolSwapTest.sol
index 01715c6b1..34a64a652 100644
--- a/src/test/PoolSwapTest.sol
+++ b/src/test/PoolSwapTest.sol
@@ -54,16 +54,18 @@ contract PoolSwapTest is Test, PoolTestBase {
 
         CallbackData memory data = abi.decode(rawData, (CallbackData));
 
-        (,, uint256 reserveBefore0, int256 deltaBefore0) = _fetchBalances(data.key.currency0, data.sender);
-        (,, uint256 reserveBefore1, int256 deltaBefore1) = _fetchBalances(data.key.currency1, data.sender);
+        (,, uint256 reserveBefore0, int256 deltaBefore0) =
+            _fetchBalances(data.key.currency0, data.sender, address(this));
+        (,, uint256 reserveBefore1, int256 deltaBefore1) =
+            _fetchBalances(data.key.currency1, data.sender, address(this));
 
         assertEq(deltaBefore0, 0);
         assertEq(deltaBefore1, 0);
 
         BalanceDelta delta = manager.swap(data.key, data.params, data.hookData);
 
-        (,, uint256 reserveAfter0, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender);
-        (,, uint256 reserveAfter1, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender);
+        (,, uint256 reserveAfter0, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender, address(this));
+        (,, uint256 reserveAfter1, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender, address(this));
 
         assertEq(reserveBefore0, reserveAfter0);
         assertEq(reserveBefore1, reserveAfter1);
diff --git a/src/test/PoolTakeTest.sol b/src/test/PoolTakeTest.sol
index 40b763891..dd26a06ad 100644
--- a/src/test/PoolTakeTest.sol
+++ b/src/test/PoolTakeTest.sol
@@ -38,13 +38,13 @@ contract PoolTakeTest is Test, PoolTestBase {
 
     function _testTake(Currency currency, address sender, uint256 amount) internal {
         (uint256 userBalBefore, uint256 pmBalBefore, uint256 reserveBefore, int256 deltaBefore) =
-            _fetchBalances(currency, sender);
+            _fetchBalances(currency, sender, address(this));
         assertEq(deltaBefore, 0);
 
         _take(currency, sender, -(amount.toInt128()), true);
 
         (uint256 userBalAfter, uint256 pmBalAfter, uint256 reserveAfter, int256 deltaAfter) =
-            _fetchBalances(currency, sender);
+            _fetchBalances(currency, sender, address(this));
         assertEq(deltaAfter, amount.toInt128());
 
         assertEq(userBalAfter - userBalBefore, amount);
diff --git a/src/test/PoolTestBase.sol b/src/test/PoolTestBase.sol
index 43fc61be5..4d5815400 100644
--- a/src/test/PoolTestBase.sol
+++ b/src/test/PoolTestBase.sol
@@ -38,7 +38,7 @@ abstract contract PoolTestBase is ILockCallback {
         }
     }
 
-    function _fetchBalances(Currency currency, address user)
+    function _fetchBalances(Currency currency, address user, address deltaHolder)
         internal
         view
         returns (uint256 userBalance, uint256 poolBalance, uint256 reserves, int256 delta)
@@ -46,6 +46,6 @@ abstract contract PoolTestBase is ILockCallback {
         userBalance = currency.balanceOf(user);
         poolBalance = currency.balanceOf(address(manager));
         reserves = manager.reservesOf(currency);
-        delta = manager.currencyDelta(address(this), currency);
+        delta = manager.currencyDelta(deltaHolder, currency);
     }
 }
diff --git a/test/Claims.t.sol b/test/Claims.t.sol
index 436c671ea..2395fda50 100644
--- a/test/Claims.t.sol
+++ b/test/Claims.t.sol
@@ -18,7 +18,7 @@ contract ClaimsTest is Test, Deployers {
     event Transfer(address indexed from, address indexed to, Currency indexed currency, uint256 amount);
 
     function setUp() public {
-        (currency0, currency1) = deployMintAndApprove2Currencies();
+        (currency0, currency1) = deployAndMint2Currencies();
     }
 
     function testCanBurn(uint256 amount) public {
diff --git a/test/NestedActions.t.sol b/test/NestedActions.t.sol
index 411e433bc..59102ad9c 100644
--- a/test/NestedActions.t.sol
+++ b/test/NestedActions.t.sol
@@ -8,7 +8,14 @@ import {Action} from "../src/test/PoolNestedActionsTest.sol";
 import {IHooks} from "../src/interfaces/IHooks.sol";
 
 contract NestedActions is Test, Deployers, GasSnapshot {
+    Action[] actions;
+
     function setUp() public {
         initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0)));
     }
+
+    function test_nestedSwap() public {
+        actions = [Action.SWAP_AND_SETTLE];
+        manager.lock(address(nestedActionRouter), abi.encode(actions));
+    }
 }
diff --git a/test/PoolManager.t.sol b/test/PoolManager.t.sol
index 9680112b7..5dd1b60a2 100644
--- a/test/PoolManager.t.sol
+++ b/test/PoolManager.t.sol
@@ -1126,12 +1126,12 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
     function test_lock_cannotBeCalledTwiceByLocker() public {
         actions = [Action.NESTED_SELF_LOCK];
-        nestedActionRouter.lock(actions);
+        manager.lock(address(nestedActionRouter), abi.encode(actions));
     }
 
     function test_lock_cannotBeCalledTwiceByDifferentLockers() public {
         actions = [Action.NESTED_EXECUTOR_LOCK];
-        nestedActionRouter.lock(actions);
+        manager.lock(address(nestedActionRouter), abi.encode(actions));
     }
 
     // function testExtsloadForPoolPrice() public {
diff --git a/test/utils/Deployers.sol b/test/utils/Deployers.sol
index e676b08a1..63584fc46 100644
--- a/test/utils/Deployers.sol
+++ b/test/utils/Deployers.sol
@@ -82,15 +82,18 @@ contract Deployers {
         manager.setProtocolFeeController(feeController);
     }
 
+    // You must have first initialised the routers with deployFreshManagerAndRouters
+    // If you only need the currencies (and not approvals) call deployAndMint2Currencies
     function deployMintAndApprove2Currencies() internal returns (Currency, Currency) {
         MockERC20[] memory tokens = deployTokens(2, 2 ** 255);
 
-        address[5] memory toApprove = [
+        address[6] memory toApprove = [
             address(swapRouter),
             address(modifyPositionRouter),
             address(donateRouter),
             address(takeRouter),
-            address(initializeRouter)
+            address(initializeRouter),
+            address(nestedActionRouter.executor())
         ];
 
         for (uint256 i = 0; i < toApprove.length; i++) {
@@ -101,6 +104,11 @@ contract Deployers {
         return SortTokens.sort(tokens[0], tokens[1]);
     }
 
+    function deployAndMint2Currencies() internal returns (Currency, Currency) {
+        MockERC20[] memory tokens = deployTokens(2, 2 ** 255);
+        return SortTokens.sort(tokens[0], tokens[1]);
+    }
+
     function deployTokens(uint8 count, uint256 totalSupply) internal returns (MockERC20[] memory tokens) {
         tokens = new MockERC20[](count);
         for (uint8 i = 0; i < count; i++) {

From 99243a1484c6296ecc79ca42f055cf7bc98e1de2 Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Thu, 14 Dec 2023 12:30:38 -0300
Subject: [PATCH 08/19] Tests for nested function calls

---
 src/test/PoolNestedActionsTest.sol | 89 ++++++++++++++++++++++++++++--
 test/NestedActions.t.sol           | 17 ++++++
 2 files changed, 101 insertions(+), 5 deletions(-)

diff --git a/src/test/PoolNestedActionsTest.sol b/src/test/PoolNestedActionsTest.sol
index 1db0e92a2..ebee5af1a 100644
--- a/src/test/PoolNestedActionsTest.sol
+++ b/src/test/PoolNestedActionsTest.sol
@@ -70,6 +70,9 @@ contract NestedActionExecutor is Test, PoolTestBase {
     IPoolManager.SwapParams internal SWAP_PARAMS =
         IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: Constants.SQRT_RATIO_1_2});
 
+    uint256 internal DONATE_AMOUNT0 = 12345e6;
+    uint256 internal DONATE_AMOUNT1 = 98765e4;
+
     constructor(IPoolManager _manager, address _user) PoolTestBase(_manager) {
         user = _user;
     }
@@ -105,10 +108,9 @@ contract NestedActionExecutor is Test, PoolTestBase {
 
     function _swap() internal {
         (address locker, address lockCaller) = manager.getLock();
-
-        // swap without a lock, checking that the deltas are applied to this contract's address not the locker's address
         assertTrue(locker != address(this), "Locker wrong");
         assertEq(lockCaller, user);
+
         (,,, int256 deltaLockerBefore0) = _fetchBalances(key.currency0, user, locker);
         (,,, int256 deltaLockerBefore1) = _fetchBalances(key.currency1, user, locker);
         (,,, int256 deltaThisBefore0) = _fetchBalances(key.currency0, user, address(this));
@@ -132,9 +134,86 @@ contract NestedActionExecutor is Test, PoolTestBase {
         _take(key.currency1, user, int128(deltaThisAfter1), true);
     }
 
-    function _addLiquidity() internal {}
-    function _removeLiquidity() internal {}
-    function _donate() internal {}
+    function _addLiquidity() internal {
+        (address locker, address lockCaller) = manager.getLock();
+        assertTrue(locker != address(this), "Locker wrong");
+        assertEq(lockCaller, user);
+
+        (,,, int256 deltaLockerBefore0) = _fetchBalances(key.currency0, user, locker);
+        (,,, int256 deltaLockerBefore1) = _fetchBalances(key.currency1, user, locker);
+        (,,, int256 deltaThisBefore0) = _fetchBalances(key.currency0, user, address(this));
+        (,,, int256 deltaThisBefore1) = _fetchBalances(key.currency1, user, address(this));
+
+        BalanceDelta delta = manager.modifyPosition(key, ADD_LIQ_PARAMS, "");
+
+        (,,, int256 deltaLockerAfter0) = _fetchBalances(key.currency0, user, locker);
+        (,,, int256 deltaLockerAfter1) = _fetchBalances(key.currency1, user, locker);
+        (,,, int256 deltaThisAfter0) = _fetchBalances(key.currency0, user, address(this));
+        (,,, int256 deltaThisAfter1) = _fetchBalances(key.currency1, user, address(this));
+
+        assertEq(deltaLockerBefore0, deltaLockerAfter0, "Locker delta 0");
+        assertEq(deltaLockerBefore1, deltaLockerAfter1, "Locker delta 1");
+        assertEq(deltaThisBefore0 + delta.amount0(), deltaThisAfter0, "Executor delta 0");
+        assertEq(deltaThisBefore1 + delta.amount1(), deltaThisAfter1, "Executor delta 1");
+
+        _settle(key.currency0, user, int128(deltaThisAfter0), true);
+        _settle(key.currency1, user, int128(deltaThisAfter1), true);
+    }
+
+    // cannot remove non-existent liquidity - need to perform an add before this removal
+    function _removeLiquidity() internal {
+        (address locker, address lockCaller) = manager.getLock();
+        assertTrue(locker != address(this), "Locker wrong");
+        assertEq(lockCaller, user);
+
+        (,,, int256 deltaLockerBefore0) = _fetchBalances(key.currency0, user, locker);
+        (,,, int256 deltaLockerBefore1) = _fetchBalances(key.currency1, user, locker);
+        (,,, int256 deltaThisBefore0) = _fetchBalances(key.currency0, user, address(this));
+        (,,, int256 deltaThisBefore1) = _fetchBalances(key.currency1, user, address(this));
+
+        BalanceDelta delta = manager.modifyPosition(key, REMOVE_LIQ_PARAMS, "");
+
+        (,,, int256 deltaLockerAfter0) = _fetchBalances(key.currency0, user, locker);
+        (,,, int256 deltaLockerAfter1) = _fetchBalances(key.currency1, user, locker);
+        (,,, int256 deltaThisAfter0) = _fetchBalances(key.currency0, user, address(this));
+        (,,, int256 deltaThisAfter1) = _fetchBalances(key.currency1, user, address(this));
+
+        assertEq(deltaLockerBefore0, deltaLockerAfter0, "Locker delta 0");
+        assertEq(deltaLockerBefore1, deltaLockerAfter1, "Locker delta 1");
+        assertEq(deltaThisBefore0 + delta.amount0(), deltaThisAfter0, "Executor delta 0");
+        assertEq(deltaThisBefore1 + delta.amount1(), deltaThisAfter1, "Executor delta 1");
+
+        _take(key.currency0, user, int128(deltaThisAfter0), true);
+        _take(key.currency1, user, int128(deltaThisAfter1), true);
+    }
+
+    function _donate() internal {
+        (address locker, address lockCaller) = manager.getLock();
+        assertTrue(locker != address(this), "Locker wrong");
+        assertEq(lockCaller, user);
+
+        (,,, int256 deltaLockerBefore0) = _fetchBalances(key.currency0, user, locker);
+        (,,, int256 deltaLockerBefore1) = _fetchBalances(key.currency1, user, locker);
+        (,,, int256 deltaThisBefore0) = _fetchBalances(key.currency0, user, address(this));
+        (,,, int256 deltaThisBefore1) = _fetchBalances(key.currency1, user, address(this));
+
+        BalanceDelta delta = manager.donate(key, DONATE_AMOUNT0, DONATE_AMOUNT1, "");
+
+        (,,, int256 deltaLockerAfter0) = _fetchBalances(key.currency0, user, locker);
+        (,,, int256 deltaLockerAfter1) = _fetchBalances(key.currency1, user, locker);
+        (,,, int256 deltaThisAfter0) = _fetchBalances(key.currency0, user, address(this));
+        (,,, int256 deltaThisAfter1) = _fetchBalances(key.currency1, user, address(this));
+
+        assertEq(deltaLockerBefore0, deltaLockerAfter0, "Locker delta 0");
+        assertEq(deltaLockerBefore1, deltaLockerAfter1, "Locker delta 1");
+        assertEq(deltaThisBefore0 + int256(DONATE_AMOUNT0), deltaThisAfter0, "Executor delta 0");
+        assertEq(deltaThisBefore1 + int256(DONATE_AMOUNT1), deltaThisAfter1, "Executor delta 1");
+        assertEq(delta.amount0(), int256(DONATE_AMOUNT0), "Donate delta 0");
+        assertEq(delta.amount1(), int256(DONATE_AMOUNT1), "Donate delta 1");
+
+        _settle(key.currency0, user, int128(deltaThisAfter0), true);
+        _settle(key.currency1, user, int128(deltaThisAfter1), true);
+    }
 
     // This will never actually be used - its just to allow us to use the PoolTestBase helper contact
     function lockAcquired(address, bytes calldata) external pure override returns (bytes memory) {
diff --git a/test/NestedActions.t.sol b/test/NestedActions.t.sol
index 59102ad9c..e2e8cd5fc 100644
--- a/test/NestedActions.t.sol
+++ b/test/NestedActions.t.sol
@@ -14,8 +14,25 @@ contract NestedActions is Test, Deployers, GasSnapshot {
         initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0)));
     }
 
+    // Asserts and expected outcomes are tested inside the nestedActionRouter
+
     function test_nestedSwap() public {
         actions = [Action.SWAP_AND_SETTLE];
         manager.lock(address(nestedActionRouter), abi.encode(actions));
     }
+
+    function test_nestedAddLiquidity() public {
+        actions = [Action.ADD_LIQ_AND_SETTLE];
+        manager.lock(address(nestedActionRouter), abi.encode(actions));
+    }
+
+    function test_nestedRemoveLiquidity() public {
+        actions = [Action.ADD_LIQ_AND_SETTLE, Action.REMOVE_LIQ_AND_SETTLE];
+        manager.lock(address(nestedActionRouter), abi.encode(actions));
+    }
+
+    function test_nestedDonate() public {
+        actions = [Action.DONATE_AND_SETTLE];
+        manager.lock(address(nestedActionRouter), abi.encode(actions));
+    }
 }

From 56f60441fd8a8d2dd53e54a66c3070135920a8ba Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Mon, 18 Dec 2023 12:47:11 -0300
Subject: [PATCH 09/19] snapshots

---
 .forge-snapshots/addLiquidity with empty hook.snap              | 2 +-
 .forge-snapshots/addLiquidity with native token.snap            | 2 +-
 .forge-snapshots/addLiquidity.snap                              | 2 +-
 .../before swap hook, already cached dynamic fee.snap           | 2 +-
 .forge-snapshots/cached dynamic fee, no hooks.snap              | 2 +-
 .forge-snapshots/donate gas with 1 token.snap                   | 2 +-
 .forge-snapshots/donate gas with 2 tokens.snap                  | 2 +-
 .forge-snapshots/gas overhead of no-op lock.snap                | 2 +-
 .forge-snapshots/initialize.snap                                | 2 +-
 .forge-snapshots/mintWithEmptyHookEOAInitiated.snap             | 2 +-
 .forge-snapshots/modify position with noop.snap                 | 2 +-
 .forge-snapshots/poolManager bytecode size.snap                 | 2 +-
 .forge-snapshots/removeLiquidity with empty hook.snap           | 2 +-
 .forge-snapshots/removeLiquidity with native token.snap         | 2 +-
 .forge-snapshots/removeLiquidity.snap                           | 2 +-
 .forge-snapshots/simple swap with native.snap                   | 2 +-
 .forge-snapshots/simple swap.snap                               | 2 +-
 .forge-snapshots/simpleSwapEOAInitiated.snap                    | 2 +-
 .forge-snapshots/simpleSwapNativeEOAInitiated.snap              | 2 +-
 .forge-snapshots/swap against liquidity with native token.snap  | 2 +-
 .forge-snapshots/swap against liquidity.snap                    | 2 +-
 .forge-snapshots/swap burn 6909 for input.snap                  | 2 +-
 .forge-snapshots/swap burn native 6909 for input.snap           | 2 +-
 .forge-snapshots/swap mint native output as 6909.snap           | 2 +-
 .forge-snapshots/swap mint output as 6909.snap                  | 2 +-
 .forge-snapshots/swap with dynamic fee.snap                     | 2 +-
 .forge-snapshots/swap with hooks.snap                           | 2 +-
 .forge-snapshots/swap with noop.snap                            | 2 +-
 .forge-snapshots/update dynamic fee in before swap.snap         | 2 +-
 29 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/.forge-snapshots/addLiquidity with empty hook.snap b/.forge-snapshots/addLiquidity with empty hook.snap
index 4b2bb2fdf..79e9c2ed3 100644
--- a/.forge-snapshots/addLiquidity with empty hook.snap	
+++ b/.forge-snapshots/addLiquidity with empty hook.snap	
@@ -1 +1 @@
-313066
+313136
\ No newline at end of file
diff --git a/.forge-snapshots/addLiquidity with native token.snap b/.forge-snapshots/addLiquidity with native token.snap
index 93ddda50d..3d07131b6 100644
--- a/.forge-snapshots/addLiquidity with native token.snap	
+++ b/.forge-snapshots/addLiquidity with native token.snap	
@@ -1 +1 @@
-200111
+193250
\ No newline at end of file
diff --git a/.forge-snapshots/addLiquidity.snap b/.forge-snapshots/addLiquidity.snap
index 62cee4de8..6af02359a 100644
--- a/.forge-snapshots/addLiquidity.snap
+++ b/.forge-snapshots/addLiquidity.snap
@@ -1 +1 @@
-200079
+193218
\ No newline at end of file
diff --git a/.forge-snapshots/before swap hook, already cached dynamic fee.snap b/.forge-snapshots/before swap hook, already cached dynamic fee.snap
index 075530451..d739f8c1b 100644
--- a/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
+++ b/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
@@ -1 +1 @@
-194367
+186327
\ No newline at end of file
diff --git a/.forge-snapshots/cached dynamic fee, no hooks.snap b/.forge-snapshots/cached dynamic fee, no hooks.snap
index 75d8913df..9f57e41db 100644
--- a/.forge-snapshots/cached dynamic fee, no hooks.snap	
+++ b/.forge-snapshots/cached dynamic fee, no hooks.snap	
@@ -1 +1 @@
-146705
+140305
\ No newline at end of file
diff --git a/.forge-snapshots/donate gas with 1 token.snap b/.forge-snapshots/donate gas with 1 token.snap
index 108aa608b..ff057d01e 100644
--- a/.forge-snapshots/donate gas with 1 token.snap	
+++ b/.forge-snapshots/donate gas with 1 token.snap	
@@ -1 +1 @@
-137750
+133155
\ No newline at end of file
diff --git a/.forge-snapshots/donate gas with 2 tokens.snap b/.forge-snapshots/donate gas with 2 tokens.snap
index fa69246bf..6e44c51c2 100644
--- a/.forge-snapshots/donate gas with 2 tokens.snap	
+++ b/.forge-snapshots/donate gas with 2 tokens.snap	
@@ -1 +1 @@
-185163
+178356
\ No newline at end of file
diff --git a/.forge-snapshots/gas overhead of no-op lock.snap b/.forge-snapshots/gas overhead of no-op lock.snap
index 7c187c391..f6afc4b52 100644
--- a/.forge-snapshots/gas overhead of no-op lock.snap	
+++ b/.forge-snapshots/gas overhead of no-op lock.snap	
@@ -1 +1 @@
-15223
+15119
\ No newline at end of file
diff --git a/.forge-snapshots/initialize.snap b/.forge-snapshots/initialize.snap
index 256e73e37..7da428eaf 100644
--- a/.forge-snapshots/initialize.snap
+++ b/.forge-snapshots/initialize.snap
@@ -1 +1 @@
-74274
+73279
\ No newline at end of file
diff --git a/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap b/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
index e04c9baeb..ef0a0e6db 100644
--- a/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
+++ b/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
@@ -1 +1 @@
-255189
+247260
\ No newline at end of file
diff --git a/.forge-snapshots/modify position with noop.snap b/.forge-snapshots/modify position with noop.snap
index 86304fed0..f1273a4d9 100644
--- a/.forge-snapshots/modify position with noop.snap	
+++ b/.forge-snapshots/modify position with noop.snap	
@@ -1 +1 @@
-58076
+53999
\ No newline at end of file
diff --git a/.forge-snapshots/poolManager bytecode size.snap b/.forge-snapshots/poolManager bytecode size.snap
index dce960779..bd9b8d797 100644
--- a/.forge-snapshots/poolManager bytecode size.snap	
+++ b/.forge-snapshots/poolManager bytecode size.snap	
@@ -1 +1 @@
-25102
+24674
\ No newline at end of file
diff --git a/.forge-snapshots/removeLiquidity with empty hook.snap b/.forge-snapshots/removeLiquidity with empty hook.snap
index 9479e469d..d3458b39a 100644
--- a/.forge-snapshots/removeLiquidity with empty hook.snap	
+++ b/.forge-snapshots/removeLiquidity with empty hook.snap	
@@ -1 +1 @@
-106952
+100091
\ No newline at end of file
diff --git a/.forge-snapshots/removeLiquidity with native token.snap b/.forge-snapshots/removeLiquidity with native token.snap
index cea785cd4..47b3444dd 100644
--- a/.forge-snapshots/removeLiquidity with native token.snap	
+++ b/.forge-snapshots/removeLiquidity with native token.snap	
@@ -1 +1 @@
-208312
+201451
\ No newline at end of file
diff --git a/.forge-snapshots/removeLiquidity.snap b/.forge-snapshots/removeLiquidity.snap
index 28c001393..1aa3020ff 100644
--- a/.forge-snapshots/removeLiquidity.snap
+++ b/.forge-snapshots/removeLiquidity.snap
@@ -1 +1 @@
-204602
+197741
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap with native.snap b/.forge-snapshots/simple swap with native.snap
index e91ee7d11..3cf5fc30c 100644
--- a/.forge-snapshots/simple swap with native.snap	
+++ b/.forge-snapshots/simple swap with native.snap	
@@ -1 +1 @@
-195676
+188847
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap.snap b/.forge-snapshots/simple swap.snap
index 85d1947de..a9920c39e 100644
--- a/.forge-snapshots/simple swap.snap	
+++ b/.forge-snapshots/simple swap.snap	
@@ -1 +1 @@
-204244
+197415
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapEOAInitiated.snap b/.forge-snapshots/simpleSwapEOAInitiated.snap
index 20fdb6b72..984d5c7d7 100644
--- a/.forge-snapshots/simpleSwapEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapEOAInitiated.snap
@@ -1 +1 @@
-174149
+167308
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
index 6b59faba1..f976859af 100644
--- a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
@@ -1 +1 @@
-172798
+165924
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity with native token.snap b/.forge-snapshots/swap against liquidity with native token.snap
index f1e6c84d3..e62462eb7 100644
--- a/.forge-snapshots/swap against liquidity with native token.snap	
+++ b/.forge-snapshots/swap against liquidity with native token.snap	
@@ -1 +1 @@
-126304
+119475
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity.snap b/.forge-snapshots/swap against liquidity.snap
index 1c4234f99..ed6a63a18 100644
--- a/.forge-snapshots/swap against liquidity.snap	
+++ b/.forge-snapshots/swap against liquidity.snap	
@@ -1 +1 @@
-113795
+106966
\ No newline at end of file
diff --git a/.forge-snapshots/swap burn 6909 for input.snap b/.forge-snapshots/swap burn 6909 for input.snap
index 3afc4c5e8..8ce54e1ea 100644
--- a/.forge-snapshots/swap burn 6909 for input.snap	
+++ b/.forge-snapshots/swap burn 6909 for input.snap	
@@ -1 +1 @@
-133995
\ No newline at end of file
+127166
\ No newline at end of file
diff --git a/.forge-snapshots/swap burn native 6909 for input.snap b/.forge-snapshots/swap burn native 6909 for input.snap
index 1d3904e93..a63827696 100644
--- a/.forge-snapshots/swap burn native 6909 for input.snap	
+++ b/.forge-snapshots/swap burn native 6909 for input.snap	
@@ -1 +1 @@
-129926
\ No newline at end of file
+123097
\ No newline at end of file
diff --git a/.forge-snapshots/swap mint native output as 6909.snap b/.forge-snapshots/swap mint native output as 6909.snap
index d1c7601b0..795321aee 100644
--- a/.forge-snapshots/swap mint native output as 6909.snap	
+++ b/.forge-snapshots/swap mint native output as 6909.snap	
@@ -1 +1 @@
-198205
\ No newline at end of file
+191331
\ No newline at end of file
diff --git a/.forge-snapshots/swap mint output as 6909.snap b/.forge-snapshots/swap mint output as 6909.snap
index 4dc0c4c51..fbc2e5c73 100644
--- a/.forge-snapshots/swap mint output as 6909.snap	
+++ b/.forge-snapshots/swap mint output as 6909.snap	
@@ -1 +1 @@
-215075
\ No newline at end of file
+208201
\ No newline at end of file
diff --git a/.forge-snapshots/swap with dynamic fee.snap b/.forge-snapshots/swap with dynamic fee.snap
index 743acaa21..b24746598 100644
--- a/.forge-snapshots/swap with dynamic fee.snap	
+++ b/.forge-snapshots/swap with dynamic fee.snap	
@@ -1 +1 @@
-193468
+185428
\ No newline at end of file
diff --git a/.forge-snapshots/swap with hooks.snap b/.forge-snapshots/swap with hooks.snap
index f3ff2b1fe..3fee59267 100644
--- a/.forge-snapshots/swap with hooks.snap	
+++ b/.forge-snapshots/swap with hooks.snap	
@@ -1 +1 @@
-113773
+106944
\ No newline at end of file
diff --git a/.forge-snapshots/swap with noop.snap b/.forge-snapshots/swap with noop.snap
index 0216360d7..54b98947e 100644
--- a/.forge-snapshots/swap with noop.snap	
+++ b/.forge-snapshots/swap with noop.snap	
@@ -1 +1 @@
-51425
+47380
\ No newline at end of file
diff --git a/.forge-snapshots/update dynamic fee in before swap.snap b/.forge-snapshots/update dynamic fee in before swap.snap
index ce9b7091f..bfe5196db 100644
--- a/.forge-snapshots/update dynamic fee in before swap.snap	
+++ b/.forge-snapshots/update dynamic fee in before swap.snap	
@@ -1 +1 @@
-200232
+192148
\ No newline at end of file

From 6ce20c4086ecfa67362515cf06db3c3128df380f Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Wed, 31 Jan 2024 12:46:38 -0300
Subject: [PATCH 10/19] Separate libs, rename error

---
 .../poolManager bytecode size.snap            |  2 +-
 .forge-snapshots/simpleSwapEOAInitiated.snap  |  2 +-
 src/PoolManager.sol                           | 11 ++---
 src/interfaces/IPoolManager.sol               |  3 +-
 src/libraries/Locker.sol                      | 32 +--------------
 src/libraries/NonZeroDeltaCount.sol           | 39 ++++++++++++++++++
 src/test/PoolNestedActionsTest.sol            |  4 +-
 test/Locker.t.sol                             | 33 +--------------
 test/NonZeroDeltaCount.t.sol                  | 41 +++++++++++++++++++
 9 files changed, 93 insertions(+), 74 deletions(-)
 create mode 100644 src/libraries/NonZeroDeltaCount.sol
 create mode 100644 test/NonZeroDeltaCount.t.sol

diff --git a/.forge-snapshots/poolManager bytecode size.snap b/.forge-snapshots/poolManager bytecode size.snap
index bd9b8d797..9e4e8cc2d 100644
--- a/.forge-snapshots/poolManager bytecode size.snap	
+++ b/.forge-snapshots/poolManager bytecode size.snap	
@@ -1 +1 @@
-24674
\ No newline at end of file
+24654
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapEOAInitiated.snap b/.forge-snapshots/simpleSwapEOAInitiated.snap
index 984d5c7d7..bedcd8a46 100644
--- a/.forge-snapshots/simpleSwapEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapEOAInitiated.snap
@@ -1 +1 @@
-167308
\ No newline at end of file
+167275
\ No newline at end of file
diff --git a/src/PoolManager.sol b/src/PoolManager.sol
index 6563b353c..460be3c93 100644
--- a/src/PoolManager.sol
+++ b/src/PoolManager.sol
@@ -20,6 +20,7 @@ import {ERC6909Claims} from "./ERC6909Claims.sol";
 import {PoolId, PoolIdLibrary} from "./types/PoolId.sol";
 import {BalanceDelta, BalanceDeltaLibrary} from "./types/BalanceDelta.sol";
 import {Locker} from "./libraries/Locker.sol";
+import {NonZeroDeltaCount} from "./libraries/NonZeroDeltaCount.sol";
 import {PoolGetters} from "./libraries/PoolGetters.sol";
 
 /// @notice Holds the state for all pools
@@ -130,14 +131,14 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC6909Claims {
     /// @inheritdoc IPoolManager
     function lock(address lockTarget, bytes calldata data) external payable override returns (bytes memory result) {
         // Get the lock caller because thats an EOA and is not user-controlable
-        if (Locker.isLocked()) revert LockedBy(Locker.getLocker());
+        if (Locker.isLocked()) revert AlreadyLocked();
 
         Locker.setLockerAndCaller(lockTarget, msg.sender);
 
         // the caller does everything in this callback, including paying what they owe via calls to settle
         result = ILockCallback(lockTarget).lockAcquired(msg.sender, data);
 
-        if (Locker.nonzeroDeltaCount() != 0) revert CurrencyNotSettled();
+        if (NonZeroDeltaCount.read() != 0) revert CurrencyNotSettled();
         Locker.clearLockerAndCaller();
     }
 
@@ -149,9 +150,9 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC6909Claims {
 
         unchecked {
             if (next == 0) {
-                Locker.decrementNonzeroDeltaCount();
+                NonZeroDeltaCount.decrement();
             } else if (current == 0) {
-                Locker.incrementNonzeroDeltaCount();
+                NonZeroDeltaCount.increment();
             }
         }
 
@@ -331,7 +332,7 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC6909Claims {
     }
 
     function getLockNonzeroDeltaCount() external view returns (uint256 _nonzeroDeltaCount) {
-        return Locker.nonzeroDeltaCount();
+        return NonZeroDeltaCount.read();
     }
 
     function getPoolTickInfo(PoolId id, int24 tick) external view returns (Pool.TickInfo memory) {
diff --git a/src/interfaces/IPoolManager.sol b/src/interfaces/IPoolManager.sol
index b6cab3ba5..f198a8433 100644
--- a/src/interfaces/IPoolManager.sol
+++ b/src/interfaces/IPoolManager.sol
@@ -23,8 +23,7 @@ interface IPoolManager is IFees, IERC6909Claims {
     error PoolNotInitialized();
 
     /// @notice Thrown when lock is called, but a lock is already open
-    /// @param locker The current locker
-    error LockedBy(address locker);
+    error AlreadyLocked();
 
     /// @notice Thrown when a function is called outside of a lock
     error ManagerNotLocked();
diff --git a/src/libraries/Locker.sol b/src/libraries/Locker.sol
index c37ab411c..e0386fb91 100644
--- a/src/libraries/Locker.sol
+++ b/src/libraries/Locker.sol
@@ -4,16 +4,13 @@ pragma solidity ^0.8.20;
 import {IHooks} from "../interfaces/IHooks.sol";
 
 /// @notice This is a temporary library that allows us to use transient storage (tstore/tload)
-/// for the lockers array and nonzero delta count.
+/// for the lockers array
 /// TODO: This library can be deleted when we have the transient keyword support in solidity.
 library Locker {
     // The slot holding the locker, transiently, and the lock caller in the next slot
     uint256 constant LOCKER_SLOT = uint256(keccak256("Locker")) - 2;
     uint256 constant LOCK_CALLER_SLOT = LOCKER_SLOT + 1;
 
-    // The slot holding the number of nonzero deltas.
-    uint256 constant NONZERO_DELTA_COUNT = uint256(keccak256("NonzeroDeltaCount")) - 1;
-
     function setLockerAndCaller(address locker, address lockCaller) internal {
         uint256 slot = LOCKER_SLOT;
 
@@ -51,31 +48,4 @@ library Locker {
             locker := tload(slot)
         }
     }
-
-    function nonzeroDeltaCount() internal view returns (uint256 count) {
-        uint256 slot = NONZERO_DELTA_COUNT;
-        assembly {
-            count := tload(slot)
-        }
-    }
-
-    function incrementNonzeroDeltaCount() internal {
-        uint256 slot = NONZERO_DELTA_COUNT;
-        assembly {
-            let count := tload(slot)
-            count := add(count, 1)
-            tstore(slot, count)
-        }
-    }
-
-    /// @notice Potential to underflow.
-    /// Current usage ensures this will not happen because we call decrememnt with known boundaries (only up to the number of times we call increment).
-    function decrementNonzeroDeltaCount() internal {
-        uint256 slot = NONZERO_DELTA_COUNT;
-        assembly {
-            let count := tload(slot)
-            count := sub(count, 1)
-            tstore(slot, count)
-        }
-    }
 }
diff --git a/src/libraries/NonZeroDeltaCount.sol b/src/libraries/NonZeroDeltaCount.sol
new file mode 100644
index 000000000..b1d31ca7d
--- /dev/null
+++ b/src/libraries/NonZeroDeltaCount.sol
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: BUSL-1.1
+pragma solidity ^0.8.20;
+
+import {IHooks} from "../interfaces/IHooks.sol";
+
+/// @notice This is a temporary library that allows us to use transient storage (tstore/tload)
+/// for the nonzero delta count.
+/// TODO: This library can be deleted when we have the transient keyword support in solidity.
+library NonZeroDeltaCount {
+    // The slot holding the number of nonzero deltas.
+    uint256 constant NONZERO_DELTA_COUNT = uint256(keccak256("NonzeroDeltaCount")) - 1;
+
+    function read() internal view returns (uint256 count) {
+        uint256 slot = NONZERO_DELTA_COUNT;
+        assembly {
+            count := tload(slot)
+        }
+    }
+
+    function increment() internal {
+        uint256 slot = NONZERO_DELTA_COUNT;
+        assembly {
+            let count := tload(slot)
+            count := add(count, 1)
+            tstore(slot, count)
+        }
+    }
+
+    /// @notice Potential to underflow.
+    /// Current usage ensures this will not happen because we call decrememnt with known boundaries (only up to the number of times we call increment).
+    function decrement() internal {
+        uint256 slot = NONZERO_DELTA_COUNT;
+        assembly {
+            let count := tload(slot)
+            count := sub(count, 1)
+            tstore(slot, count)
+        }
+    }
+}
diff --git a/src/test/PoolNestedActionsTest.sol b/src/test/PoolNestedActionsTest.sol
index 29fb62829..c96ef1a6d 100644
--- a/src/test/PoolNestedActionsTest.sol
+++ b/src/test/PoolNestedActionsTest.sol
@@ -46,7 +46,7 @@ contract PoolNestedActionsTest is Test, ILockCallback {
         assertEq(locker, address(this));
         assertEq(lockCaller, user);
 
-        vm.expectRevert(abi.encodeWithSelector(IPoolManager.LockedBy.selector, address(this)));
+        vm.expectRevert(abi.encodeWithSelector(IPoolManager.AlreadyLocked.selector));
         manager.lock(address(this), "");
 
         (locker, lockCaller) = manager.getLock();
@@ -98,7 +98,7 @@ contract NestedActionExecutor is Test, PoolTestBase {
         assertEq(locker, msg.sender);
         assertEq(lockCaller, user);
 
-        vm.expectRevert(abi.encodeWithSelector(IPoolManager.LockedBy.selector, msg.sender));
+        vm.expectRevert(abi.encodeWithSelector(IPoolManager.AlreadyLocked.selector));
         manager.lock(address(this), "");
 
         (locker, lockCaller) = manager.getLock();
diff --git a/test/Locker.t.sol b/test/Locker.t.sol
index fc9647cb5..69cb23152 100644
--- a/test/Locker.t.sol
+++ b/test/Locker.t.sol
@@ -4,7 +4,7 @@ pragma solidity ^0.8.20;
 import {Test} from "forge-std/Test.sol";
 import {Locker} from "../src/libraries/Locker.sol";
 
-contract CurrentHookAddressTest is Test {
+contract LockerTest is Test {
     address constant ADDRESS_AS = 0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa;
     address constant ADDRESS_BS = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;
 
@@ -47,35 +47,4 @@ contract CurrentHookAddressTest is Test {
 
         assertFalse(Locker.isLocked());
     }
-
-    function test_incrementNonzeroDeltaCount() public {
-        Locker.incrementNonzeroDeltaCount();
-        assertEq(Locker.nonzeroDeltaCount(), 1);
-    }
-
-    function test_decrementNonzeroDeltaCount() public {
-        Locker.incrementNonzeroDeltaCount();
-        Locker.decrementNonzeroDeltaCount();
-        assertEq(Locker.nonzeroDeltaCount(), 0);
-    }
-
-    // Reading from right to left. Bit of 0: call increase. Bit of 1: call decrease.
-    // The library allows over over/underflow so we dont check for that here
-    function test_nonZeroDeltaCount_fuzz(uint256 instructions) public {
-        uint256 expectedCount;
-        for (uint256 i = 0; i < 256; i++) {
-            if ((instructions & (1 << i)) == 0) {
-                Locker.incrementNonzeroDeltaCount();
-                unchecked {
-                    expectedCount++;
-                }
-            } else {
-                Locker.decrementNonzeroDeltaCount();
-                unchecked {
-                    expectedCount--;
-                }
-            }
-            assertEq(Locker.nonzeroDeltaCount(), expectedCount);
-        }
-    }
 }
diff --git a/test/NonZeroDeltaCount.t.sol b/test/NonZeroDeltaCount.t.sol
new file mode 100644
index 000000000..0ae1820a3
--- /dev/null
+++ b/test/NonZeroDeltaCount.t.sol
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: UNLICENSED
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {NonZeroDeltaCount} from "../src/libraries/NonZeroDeltaCount.sol";
+
+contract NonZeroDeltaCountTest is Test {
+    address constant ADDRESS_AS = 0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa;
+    address constant ADDRESS_BS = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;
+
+    function test_incrementNonzeroDeltaCount() public {
+        NonZeroDeltaCount.increment();
+        assertEq(NonZeroDeltaCount.read(), 1);
+    }
+
+    function test_decrementNonzeroDeltaCount() public {
+        NonZeroDeltaCount.increment();
+        NonZeroDeltaCount.decrement();
+        assertEq(NonZeroDeltaCount.read(), 0);
+    }
+
+    // Reading from right to left. Bit of 0: call increase. Bit of 1: call decrease.
+    // The library allows over over/underflow so we dont check for that here
+    function test_nonZeroDeltaCount_fuzz(uint256 instructions) public {
+        uint256 expectedCount;
+        for (uint256 i = 0; i < 256; i++) {
+            if ((instructions & (1 << i)) == 0) {
+                NonZeroDeltaCount.increment();
+                unchecked {
+                    expectedCount++;
+                }
+            } else {
+                NonZeroDeltaCount.decrement();
+                unchecked {
+                    expectedCount--;
+                }
+            }
+            assertEq(NonZeroDeltaCount.read(), expectedCount);
+        }
+    }
+}

From c802859132c18b9d6cc4923a120fdc963140452a Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Mon, 12 Feb 2024 16:45:20 -0300
Subject: [PATCH 11/19] Remove lock caller

---
 .../addLiquidity with empty hook.snap         |  2 +-
 .../addLiquidity with native token.snap       |  2 +-
 .forge-snapshots/addLiquidity.snap            |  2 +-
 ...swap hook, already cached dynamic fee.snap |  2 +-
 .../cached dynamic fee, no hooks.snap         |  2 +-
 .forge-snapshots/donate gas with 1 token.snap |  2 +-
 .../donate gas with 2 tokens.snap             |  2 +-
 .../gas overhead of no-op lock.snap           |  2 +-
 .forge-snapshots/initialize.snap              |  2 +-
 .../mintWithEmptyHookEOAInitiated.snap        |  2 +-
 .../modify position with noop.snap            |  2 +-
 .../poolManager bytecode size.snap            |  2 +-
 .../removeLiquidity with empty hook.snap      |  2 +-
 .../removeLiquidity with native token.snap    |  2 +-
 .forge-snapshots/removeLiquidity.snap         |  2 +-
 .forge-snapshots/simple swap with native.snap |  2 +-
 .forge-snapshots/simple swap.snap             |  2 +-
 .forge-snapshots/simpleSwapEOAInitiated.snap  |  2 +-
 .../simpleSwapNativeEOAInitiated.snap         |  2 +-
 ...p against liquidity with native token.snap |  2 +-
 .forge-snapshots/swap against liquidity.snap  |  2 +-
 .../swap burn 6909 for input.snap             |  2 +-
 .../swap burn native 6909 for input.snap      |  2 +-
 .../swap mint native output as 6909.snap      |  2 +-
 .../swap mint output as 6909.snap             |  2 +-
 .forge-snapshots/swap with dynamic fee.snap   |  2 +-
 .forge-snapshots/swap with hooks.snap         |  2 +-
 .forge-snapshots/swap with noop.snap          |  2 +-
 .../update dynamic fee in before swap.snap    |  2 +-
 src/PoolManager.sol                           |  8 ++--
 src/interfaces/IPoolManager.sol               |  4 +-
 src/libraries/Locker.sol                      | 25 +++++-------
 src/test/PoolNestedActionsTest.sol            | 24 ++++--------
 test/Locker.t.sol                             | 38 +++++++++----------
 34 files changed, 69 insertions(+), 88 deletions(-)

diff --git a/.forge-snapshots/addLiquidity with empty hook.snap b/.forge-snapshots/addLiquidity with empty hook.snap
index 9a19fe0ce..cfc6e3e4e 100644
--- a/.forge-snapshots/addLiquidity with empty hook.snap	
+++ b/.forge-snapshots/addLiquidity with empty hook.snap	
@@ -1 +1 @@
-313482
\ No newline at end of file
+313034
\ No newline at end of file
diff --git a/.forge-snapshots/addLiquidity with native token.snap b/.forge-snapshots/addLiquidity with native token.snap
index 15301c17e..de7c2ff33 100644
--- a/.forge-snapshots/addLiquidity with native token.snap	
+++ b/.forge-snapshots/addLiquidity with native token.snap	
@@ -1 +1 @@
-193637
\ No newline at end of file
+193189
\ No newline at end of file
diff --git a/.forge-snapshots/addLiquidity.snap b/.forge-snapshots/addLiquidity.snap
index 07a0648b1..1750a6692 100644
--- a/.forge-snapshots/addLiquidity.snap
+++ b/.forge-snapshots/addLiquidity.snap
@@ -1 +1 @@
-193615
\ No newline at end of file
+193167
\ No newline at end of file
diff --git a/.forge-snapshots/before swap hook, already cached dynamic fee.snap b/.forge-snapshots/before swap hook, already cached dynamic fee.snap
index 1a2ef0b94..3cbc98f73 100644
--- a/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
+++ b/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
@@ -1 +1 @@
-185924
\ No newline at end of file
+185454
\ No newline at end of file
diff --git a/.forge-snapshots/cached dynamic fee, no hooks.snap b/.forge-snapshots/cached dynamic fee, no hooks.snap
index 4fabf547a..298079c1f 100644
--- a/.forge-snapshots/cached dynamic fee, no hooks.snap	
+++ b/.forge-snapshots/cached dynamic fee, no hooks.snap	
@@ -1 +1 @@
-139924
\ No newline at end of file
+139454
\ No newline at end of file
diff --git a/.forge-snapshots/donate gas with 1 token.snap b/.forge-snapshots/donate gas with 1 token.snap
index 8f9327393..2923d0ce4 100644
--- a/.forge-snapshots/donate gas with 1 token.snap	
+++ b/.forge-snapshots/donate gas with 1 token.snap	
@@ -1 +1 @@
-132925
\ No newline at end of file
+132530
\ No newline at end of file
diff --git a/.forge-snapshots/donate gas with 2 tokens.snap b/.forge-snapshots/donate gas with 2 tokens.snap
index bf60db819..8b6772d67 100644
--- a/.forge-snapshots/donate gas with 2 tokens.snap	
+++ b/.forge-snapshots/donate gas with 2 tokens.snap	
@@ -1 +1 @@
-178082
\ No newline at end of file
+177634
\ No newline at end of file
diff --git a/.forge-snapshots/gas overhead of no-op lock.snap b/.forge-snapshots/gas overhead of no-op lock.snap
index ee6f4fd85..55ffc0c6e 100644
--- a/.forge-snapshots/gas overhead of no-op lock.snap	
+++ b/.forge-snapshots/gas overhead of no-op lock.snap	
@@ -1 +1 @@
-15077
\ No newline at end of file
+14810
\ No newline at end of file
diff --git a/.forge-snapshots/initialize.snap b/.forge-snapshots/initialize.snap
index 03c28dc28..d9dfed896 100644
--- a/.forge-snapshots/initialize.snap
+++ b/.forge-snapshots/initialize.snap
@@ -1 +1 @@
-73148
\ No newline at end of file
+72764
\ No newline at end of file
diff --git a/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap b/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
index 7c04a5009..2257feb13 100644
--- a/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
+++ b/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
@@ -1 +1 @@
-247546
\ No newline at end of file
+247151
\ No newline at end of file
diff --git a/.forge-snapshots/modify position with noop.snap b/.forge-snapshots/modify position with noop.snap
index 6ee5340d5..84e389dfe 100644
--- a/.forge-snapshots/modify position with noop.snap	
+++ b/.forge-snapshots/modify position with noop.snap	
@@ -1 +1 @@
-54443
\ No newline at end of file
+54101
\ No newline at end of file
diff --git a/.forge-snapshots/poolManager bytecode size.snap b/.forge-snapshots/poolManager bytecode size.snap
index 70341d9de..3b3195df2 100644
--- a/.forge-snapshots/poolManager bytecode size.snap	
+++ b/.forge-snapshots/poolManager bytecode size.snap	
@@ -1 +1 @@
-24173
\ No newline at end of file
+24093
\ No newline at end of file
diff --git a/.forge-snapshots/removeLiquidity with empty hook.snap b/.forge-snapshots/removeLiquidity with empty hook.snap
index 9297a8602..d2c53fce5 100644
--- a/.forge-snapshots/removeLiquidity with empty hook.snap	
+++ b/.forge-snapshots/removeLiquidity with empty hook.snap	
@@ -1 +1 @@
-100428
\ No newline at end of file
+99936
\ No newline at end of file
diff --git a/.forge-snapshots/removeLiquidity with native token.snap b/.forge-snapshots/removeLiquidity with native token.snap
index 61adfa7b6..baf590c91 100644
--- a/.forge-snapshots/removeLiquidity with native token.snap	
+++ b/.forge-snapshots/removeLiquidity with native token.snap	
@@ -1 +1 @@
-201801
\ No newline at end of file
+201309
\ No newline at end of file
diff --git a/.forge-snapshots/removeLiquidity.snap b/.forge-snapshots/removeLiquidity.snap
index f16e747f8..04918ec24 100644
--- a/.forge-snapshots/removeLiquidity.snap
+++ b/.forge-snapshots/removeLiquidity.snap
@@ -1 +1 @@
-198078
\ No newline at end of file
+197586
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap with native.snap b/.forge-snapshots/simple swap with native.snap
index 583cf05b1..6f27b91e1 100644
--- a/.forge-snapshots/simple swap with native.snap	
+++ b/.forge-snapshots/simple swap with native.snap	
@@ -1 +1 @@
-188497
\ No newline at end of file
+188027
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap.snap b/.forge-snapshots/simple swap.snap
index ca7e4e88f..7ce4b83c1 100644
--- a/.forge-snapshots/simple swap.snap	
+++ b/.forge-snapshots/simple swap.snap	
@@ -1 +1 @@
-197034
\ No newline at end of file
+196564
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapEOAInitiated.snap b/.forge-snapshots/simpleSwapEOAInitiated.snap
index 68f27b179..38c1a1eb5 100644
--- a/.forge-snapshots/simpleSwapEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapEOAInitiated.snap
@@ -1 +1 @@
-166955
\ No newline at end of file
+166450
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
index e0e48d71e..aaea2d8e3 100644
--- a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
@@ -1 +1 @@
-165602
\ No newline at end of file
+165132
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity with native token.snap b/.forge-snapshots/swap against liquidity with native token.snap
index 11afa3d31..0946afcde 100644
--- a/.forge-snapshots/swap against liquidity with native token.snap	
+++ b/.forge-snapshots/swap against liquidity with native token.snap	
@@ -1 +1 @@
-119160
\ No newline at end of file
+118690
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity.snap b/.forge-snapshots/swap against liquidity.snap
index c17ca5999..210a6bf3b 100644
--- a/.forge-snapshots/swap against liquidity.snap	
+++ b/.forge-snapshots/swap against liquidity.snap	
@@ -1 +1 @@
-106624
\ No newline at end of file
+106154
\ No newline at end of file
diff --git a/.forge-snapshots/swap burn 6909 for input.snap b/.forge-snapshots/swap burn 6909 for input.snap
index 9978f4e07..ab4b64fdb 100644
--- a/.forge-snapshots/swap burn 6909 for input.snap	
+++ b/.forge-snapshots/swap burn 6909 for input.snap	
@@ -1 +1 @@
-126836
\ No newline at end of file
+126344
\ No newline at end of file
diff --git a/.forge-snapshots/swap burn native 6909 for input.snap b/.forge-snapshots/swap burn native 6909 for input.snap
index cbe5a99ae..2baddebf2 100644
--- a/.forge-snapshots/swap burn native 6909 for input.snap	
+++ b/.forge-snapshots/swap burn native 6909 for input.snap	
@@ -1 +1 @@
-122789
\ No newline at end of file
+122297
\ No newline at end of file
diff --git a/.forge-snapshots/swap mint native output as 6909.snap b/.forge-snapshots/swap mint native output as 6909.snap
index 875660dde..f858065c5 100644
--- a/.forge-snapshots/swap mint native output as 6909.snap	
+++ b/.forge-snapshots/swap mint native output as 6909.snap	
@@ -1 +1 @@
-191024
\ No newline at end of file
+190554
\ No newline at end of file
diff --git a/.forge-snapshots/swap mint output as 6909.snap b/.forge-snapshots/swap mint output as 6909.snap
index d1a56c5b3..3ad1208f2 100644
--- a/.forge-snapshots/swap mint output as 6909.snap	
+++ b/.forge-snapshots/swap mint output as 6909.snap	
@@ -1 +1 @@
-207829
\ No newline at end of file
+207359
\ No newline at end of file
diff --git a/.forge-snapshots/swap with dynamic fee.snap b/.forge-snapshots/swap with dynamic fee.snap
index fb67a27a3..90130ac49 100644
--- a/.forge-snapshots/swap with dynamic fee.snap	
+++ b/.forge-snapshots/swap with dynamic fee.snap	
@@ -1 +1 @@
-185025
\ No newline at end of file
+184555
\ No newline at end of file
diff --git a/.forge-snapshots/swap with hooks.snap b/.forge-snapshots/swap with hooks.snap
index 16ae102fc..3803f5a6e 100644
--- a/.forge-snapshots/swap with hooks.snap	
+++ b/.forge-snapshots/swap with hooks.snap	
@@ -1 +1 @@
-106602
\ No newline at end of file
+106132
\ No newline at end of file
diff --git a/.forge-snapshots/swap with noop.snap b/.forge-snapshots/swap with noop.snap
index 90c4e6542..cd37cba40 100644
--- a/.forge-snapshots/swap with noop.snap	
+++ b/.forge-snapshots/swap with noop.snap	
@@ -1 +1 @@
-47175
\ No newline at end of file
+46833
\ No newline at end of file
diff --git a/.forge-snapshots/update dynamic fee in before swap.snap b/.forge-snapshots/update dynamic fee in before swap.snap
index f32d421b7..849cdfec2 100644
--- a/.forge-snapshots/update dynamic fee in before swap.snap	
+++ b/.forge-snapshots/update dynamic fee in before swap.snap	
@@ -1 +1 @@
-191729
\ No newline at end of file
+191259
\ No newline at end of file
diff --git a/src/PoolManager.sol b/src/PoolManager.sol
index 113980688..1e20b16ff 100644
--- a/src/PoolManager.sol
+++ b/src/PoolManager.sol
@@ -89,8 +89,8 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC6909Claims {
     }
 
     /// @inheritdoc IPoolManager
-    function getLock() external view override returns (address locker, address lockCaller) {
-        return (Locker.getLocker(), Locker.getLockCaller());
+    function getLocker() external view override returns (address locker) {
+        return Locker.getLocker();
     }
 
     /// @notice This will revert if a function is called by any address other than the current locker OR the most recently called, pre-permissioned hook.
@@ -133,13 +133,13 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC6909Claims {
         // Get the lock caller because thats an EOA and is not user-controlable
         if (Locker.isLocked()) revert AlreadyLocked();
 
-        Locker.setLockerAndCaller(lockTarget, msg.sender);
+        Locker.setLocker(lockTarget);
 
         // the caller does everything in this callback, including paying what they owe via calls to settle
         result = ILockCallback(lockTarget).lockAcquired(msg.sender, data);
 
         if (NonZeroDeltaCount.read() != 0) revert CurrencyNotSettled();
-        Locker.clearLockerAndCaller();
+        Locker.clearLocker();
     }
 
     function _accountDelta(Currency currency, int128 delta) internal {
diff --git a/src/interfaces/IPoolManager.sol b/src/interfaces/IPoolManager.sol
index f198a8433..40ff5ae72 100644
--- a/src/interfaces/IPoolManager.sol
+++ b/src/interfaces/IPoolManager.sol
@@ -121,8 +121,8 @@ interface IPoolManager is IFees, IERC6909Claims {
     /// @notice Returns the reserves for a given ERC20 currency
     function reservesOf(Currency currency) external view returns (uint256);
 
-    /// @notice Returns the locker and lockCaller of the pool
-    function getLock() external view returns (address locker, address lockCaller);
+    /// @notice Returns the locker of the pool
+    function getLocker() external view returns (address locker);
 
     /// @notice Returns the number of nonzero deltas open on the PoolManager that must be zerod by the close of the initial lock.
     function getLockNonzeroDeltaCount() external view returns (uint256 _nonzeroDeltaCount);
diff --git a/src/libraries/Locker.sol b/src/libraries/Locker.sol
index e0386fb91..2f45772f8 100644
--- a/src/libraries/Locker.sol
+++ b/src/libraries/Locker.sol
@@ -8,26 +8,26 @@ import {IHooks} from "../interfaces/IHooks.sol";
 /// TODO: This library can be deleted when we have the transient keyword support in solidity.
 library Locker {
     // The slot holding the locker, transiently, and the lock caller in the next slot
-    uint256 constant LOCKER_SLOT = uint256(keccak256("Locker")) - 2;
-    uint256 constant LOCK_CALLER_SLOT = LOCKER_SLOT + 1;
+    uint256 constant LOCKER_SLOT = uint256(keccak256("Locker")) - 1;
 
-    function setLockerAndCaller(address locker, address lockCaller) internal {
+    /// @notice Thrown when trying to set the lock target as address(0)
+    /// we use locker==address(0) to signal that the pool is not locked
+    error InvalidLocker();
+
+    function setLocker(address locker) internal {
+        if (locker == address(0)) revert InvalidLocker();
         uint256 slot = LOCKER_SLOT;
 
         assembly {
             // set the locker
             tstore(slot, locker)
-
-            // set the lock caller
-            tstore(add(slot, 1), lockCaller)
         }
     }
 
-    function clearLockerAndCaller() internal {
+    function clearLocker() internal {
         uint256 slot = LOCKER_SLOT;
         assembly {
             tstore(slot, 0)
-            tstore(add(slot, 1), 0)
         }
     }
 
@@ -39,13 +39,6 @@ library Locker {
     }
 
     function isLocked() internal view returns (bool) {
-        return Locker.getLockCaller() != address(0);
-    }
-
-    function getLockCaller() internal view returns (address locker) {
-        uint256 slot = LOCK_CALLER_SLOT;
-        assembly {
-            locker := tload(slot)
-        }
+        return getLocker() != address(0);
     }
 }
diff --git a/src/test/PoolNestedActionsTest.sol b/src/test/PoolNestedActionsTest.sol
index c96ef1a6d..e792e3e49 100644
--- a/src/test/PoolNestedActionsTest.sol
+++ b/src/test/PoolNestedActionsTest.sol
@@ -42,16 +42,14 @@ contract PoolNestedActionsTest is Test, ILockCallback {
     }
 
     function _nestedLock() internal {
-        (address locker, address lockCaller) = manager.getLock();
+        address locker = manager.getLocker();
         assertEq(locker, address(this));
-        assertEq(lockCaller, user);
 
         vm.expectRevert(abi.encodeWithSelector(IPoolManager.AlreadyLocked.selector));
         manager.lock(address(this), "");
 
-        (locker, lockCaller) = manager.getLock();
+        locker = manager.getLocker();
         assertEq(locker, address(this));
-        assertEq(lockCaller, user);
     }
 }
 
@@ -94,22 +92,19 @@ contract NestedActionExecutor is Test, PoolTestBase {
     }
 
     function _nestedLock() internal {
-        (address locker, address lockCaller) = manager.getLock();
+        (address locker) = manager.getLocker();
         assertEq(locker, msg.sender);
-        assertEq(lockCaller, user);
 
         vm.expectRevert(abi.encodeWithSelector(IPoolManager.AlreadyLocked.selector));
         manager.lock(address(this), "");
 
-        (locker, lockCaller) = manager.getLock();
+        (locker) = manager.getLocker();
         assertEq(locker, msg.sender);
-        assertEq(lockCaller, user);
     }
 
     function _swap() internal {
-        (address locker, address lockCaller) = manager.getLock();
+        (address locker) = manager.getLocker();
         assertTrue(locker != address(this), "Locker wrong");
-        assertEq(lockCaller, user);
 
         (,,, int256 deltaLockerBefore0) = _fetchBalances(key.currency0, user, locker);
         (,,, int256 deltaLockerBefore1) = _fetchBalances(key.currency1, user, locker);
@@ -135,9 +130,8 @@ contract NestedActionExecutor is Test, PoolTestBase {
     }
 
     function _addLiquidity() internal {
-        (address locker, address lockCaller) = manager.getLock();
+        address locker = manager.getLocker();
         assertTrue(locker != address(this), "Locker wrong");
-        assertEq(lockCaller, user);
 
         (,,, int256 deltaLockerBefore0) = _fetchBalances(key.currency0, user, locker);
         (,,, int256 deltaLockerBefore1) = _fetchBalances(key.currency1, user, locker);
@@ -162,9 +156,8 @@ contract NestedActionExecutor is Test, PoolTestBase {
 
     // cannot remove non-existent liquidity - need to perform an add before this removal
     function _removeLiquidity() internal {
-        (address locker, address lockCaller) = manager.getLock();
+        address locker = manager.getLocker();
         assertTrue(locker != address(this), "Locker wrong");
-        assertEq(lockCaller, user);
 
         (,,, int256 deltaLockerBefore0) = _fetchBalances(key.currency0, user, locker);
         (,,, int256 deltaLockerBefore1) = _fetchBalances(key.currency1, user, locker);
@@ -188,9 +181,8 @@ contract NestedActionExecutor is Test, PoolTestBase {
     }
 
     function _donate() internal {
-        (address locker, address lockCaller) = manager.getLock();
+        address locker = manager.getLocker();
         assertTrue(locker != address(this), "Locker wrong");
-        assertEq(lockCaller, user);
 
         (,,, int256 deltaLockerBefore0) = _fetchBalances(key.currency0, user, locker);
         (,,, int256 deltaLockerBefore1) = _fetchBalances(key.currency1, user, locker);
diff --git a/test/Locker.t.sol b/test/Locker.t.sol
index 69cb23152..1e63909b9 100644
--- a/test/Locker.t.sol
+++ b/test/Locker.t.sol
@@ -8,42 +8,38 @@ contract LockerTest is Test {
     address constant ADDRESS_AS = 0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa;
     address constant ADDRESS_BS = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;
 
-    function test_setLockerAndCaller() public {
+    function test_setLocker(address locker) public {
         assertEq(address(Locker.getLocker()), address(0));
-        assertEq(address(Locker.getLockCaller()), address(0));
 
-        Locker.setLockerAndCaller(ADDRESS_AS, ADDRESS_BS);
-
-        assertEq(address(Locker.getLocker()), ADDRESS_AS);
-        assertEq(address(Locker.getLockCaller()), ADDRESS_BS);
-
-        // in the way this library is used in V4, this function will never be called when non-0
-        Locker.setLockerAndCaller(ADDRESS_BS, ADDRESS_AS);
-
-        assertEq(address(Locker.getLocker()), ADDRESS_BS);
-        assertEq(address(Locker.getLockCaller()), ADDRESS_AS);
+        if (locker == address(0)) {
+            vm.expectRevert(Locker.InvalidLocker.selector);
+            Locker.setLocker(locker);
+        } else {
+            Locker.setLocker(locker);
+            assertEq(address(Locker.getLocker()), locker);
+        }
     }
 
-    function test_clearLockerAndCaller() public {
-        Locker.setLockerAndCaller(ADDRESS_AS, ADDRESS_BS);
+    function test_clearLocker(address locker) public {
+        vm.assume(locker != address(0));
+        Locker.setLocker(locker);
 
-        assertEq(address(Locker.getLocker()), ADDRESS_AS);
-        assertEq(address(Locker.getLockCaller()), ADDRESS_BS);
+        assertEq(address(Locker.getLocker()), locker);
 
-        Locker.clearLockerAndCaller();
+        Locker.clearLocker();
 
         assertEq(address(Locker.getLocker()), address(0));
-        assertEq(address(Locker.getLockCaller()), address(0));
     }
 
-    function test_isLocked() public {
+    function test_isLocked(address locker) public {
+        vm.assume(locker != address(0));
         assertFalse(Locker.isLocked());
 
-        Locker.setLockerAndCaller(ADDRESS_AS, ADDRESS_BS);
+        Locker.setLocker(locker);
 
         assertTrue(Locker.isLocked());
 
-        Locker.clearLockerAndCaller();
+        Locker.clearLocker();
 
         assertFalse(Locker.isLocked());
     }

From dff0d82d7ccb53b22735b4c1798b60054103938a Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Wed, 14 Feb 2024 11:43:31 -0300
Subject: [PATCH 12/19] merge errors

---
 .forge-snapshots/poolManager bytecode size.snap | 2 +-
 .forge-snapshots/simpleSwapEOAInitiated.snap    | 2 +-
 test/utils/SwapHelper.t.sol                     | 1 -
 3 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/.forge-snapshots/poolManager bytecode size.snap b/.forge-snapshots/poolManager bytecode size.snap
index 60ee0a347..09ce280b6 100644
--- a/.forge-snapshots/poolManager bytecode size.snap	
+++ b/.forge-snapshots/poolManager bytecode size.snap	
@@ -1 +1 @@
-24361
+23847
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapEOAInitiated.snap b/.forge-snapshots/simpleSwapEOAInitiated.snap
index 414f3217f..38c1a1eb5 100644
--- a/.forge-snapshots/simpleSwapEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapEOAInitiated.snap
@@ -1 +1 @@
-173759
+166450
\ No newline at end of file
diff --git a/test/utils/SwapHelper.t.sol b/test/utils/SwapHelper.t.sol
index 64fd4990c..e89950c72 100644
--- a/test/utils/SwapHelper.t.sol
+++ b/test/utils/SwapHelper.t.sol
@@ -18,7 +18,6 @@ import {Deployers} from "./Deployers.sol";
 import {Fees} from "../../src/Fees.sol";
 import {PoolId, PoolIdLibrary} from "../../src/types/PoolId.sol";
 import {PoolKey} from "../../src/types/PoolKey.sol";
-import {AccessLockHook} from "../../src/test/AccessLockHook.sol";
 import {IERC20Minimal} from "../../src/interfaces/external/IERC20Minimal.sol";
 import {BalanceDelta} from "../../src/types/BalanceDelta.sol";
 

From 47bea1a7035d03256c1371c26e97810f633df795 Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Wed, 14 Feb 2024 15:11:04 -0300
Subject: [PATCH 13/19] Flipping the sign of deltas

---
 .../addLiquidity with empty hook.snap         |  2 +-
 .../addLiquidity with native token.snap       |  2 +-
 .forge-snapshots/addLiquidity.snap            |  2 +-
 ...swap hook, already cached dynamic fee.snap |  2 +-
 .../cached dynamic fee, no hooks.snap         |  2 +-
 .forge-snapshots/donate gas with 1 token.snap |  2 +-
 .../donate gas with 2 tokens.snap             |  2 +-
 .../mintWithEmptyHookEOAInitiated.snap        |  2 +-
 .../modify position with noop.snap            |  2 +-
 .../poolManager bytecode size.snap            |  2 +-
 .../removeLiquidity with empty hook.snap      |  2 +-
 .../removeLiquidity with native token.snap    |  2 +-
 .forge-snapshots/removeLiquidity.snap         |  2 +-
 .forge-snapshots/simple swap with native.snap |  2 +-
 .forge-snapshots/simple swap.snap             |  2 +-
 .forge-snapshots/simpleSwapEOAInitiated.snap  |  2 +-
 .../simpleSwapNativeEOAInitiated.snap         |  2 +-
 ...p against liquidity with native token.snap |  2 +-
 .forge-snapshots/swap against liquidity.snap  |  2 +-
 .../swap burn 6909 for input.snap             |  2 +-
 .../swap burn native 6909 for input.snap      |  2 +-
 .../swap mint native output as 6909.snap      |  2 +-
 .../swap mint output as 6909.snap             |  2 +-
 .forge-snapshots/swap with dynamic fee.snap   |  2 +-
 .forge-snapshots/swap with hooks.snap         |  2 +-
 .../update dynamic fee in before swap.snap    |  2 +-
 src/PoolManager.sol                           | 15 +++++------
 src/libraries/Pool.sol                        | 19 +++++++-------
 src/libraries/SafeCast.sol                    |  8 ++++++
 src/test/PoolClaimsTest.sol                   |  2 +-
 src/test/PoolDonateTest.sol                   | 15 ++++++-----
 src/test/PoolModifyLiquidityTest.sol          | 10 ++++----
 src/test/PoolNestedActionsTest.sol            | 12 ++++-----
 src/test/PoolSwapTest.sol                     | 25 ++++++++++---------
 src/test/PoolTakeTest.sol                     |  6 ++---
 src/test/PoolTestBase.sol                     | 17 +++++++------
 test/utils/SwapHelper.t.sol                   | 22 ++++++++--------
 37 files changed, 107 insertions(+), 96 deletions(-)

diff --git a/.forge-snapshots/addLiquidity with empty hook.snap b/.forge-snapshots/addLiquidity with empty hook.snap
index cfc6e3e4e..e4a72be6b 100644
--- a/.forge-snapshots/addLiquidity with empty hook.snap	
+++ b/.forge-snapshots/addLiquidity with empty hook.snap	
@@ -1 +1 @@
-313034
\ No newline at end of file
+313169
\ No newline at end of file
diff --git a/.forge-snapshots/addLiquidity with native token.snap b/.forge-snapshots/addLiquidity with native token.snap
index de7c2ff33..e0597c136 100644
--- a/.forge-snapshots/addLiquidity with native token.snap	
+++ b/.forge-snapshots/addLiquidity with native token.snap	
@@ -1 +1 @@
-193189
\ No newline at end of file
+193321
\ No newline at end of file
diff --git a/.forge-snapshots/addLiquidity.snap b/.forge-snapshots/addLiquidity.snap
index 1750a6692..e6d46e2df 100644
--- a/.forge-snapshots/addLiquidity.snap
+++ b/.forge-snapshots/addLiquidity.snap
@@ -1 +1 @@
-193167
\ No newline at end of file
+193302
\ No newline at end of file
diff --git a/.forge-snapshots/before swap hook, already cached dynamic fee.snap b/.forge-snapshots/before swap hook, already cached dynamic fee.snap
index 3cbc98f73..e27ec07df 100644
--- a/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
+++ b/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
@@ -1 +1 @@
-185454
\ No newline at end of file
+186054
\ No newline at end of file
diff --git a/.forge-snapshots/cached dynamic fee, no hooks.snap b/.forge-snapshots/cached dynamic fee, no hooks.snap
index 298079c1f..f4e593d3e 100644
--- a/.forge-snapshots/cached dynamic fee, no hooks.snap	
+++ b/.forge-snapshots/cached dynamic fee, no hooks.snap	
@@ -1 +1 @@
-139454
\ No newline at end of file
+140054
\ No newline at end of file
diff --git a/.forge-snapshots/donate gas with 1 token.snap b/.forge-snapshots/donate gas with 1 token.snap
index 2923d0ce4..55d9dcc74 100644
--- a/.forge-snapshots/donate gas with 1 token.snap	
+++ b/.forge-snapshots/donate gas with 1 token.snap	
@@ -1 +1 @@
-132530
\ No newline at end of file
+132901
\ No newline at end of file
diff --git a/.forge-snapshots/donate gas with 2 tokens.snap b/.forge-snapshots/donate gas with 2 tokens.snap
index 8b6772d67..be4f7e2ad 100644
--- a/.forge-snapshots/donate gas with 2 tokens.snap	
+++ b/.forge-snapshots/donate gas with 2 tokens.snap	
@@ -1 +1 @@
-177634
\ No newline at end of file
+178078
\ No newline at end of file
diff --git a/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap b/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
index 2257feb13..1e7b8a0ec 100644
--- a/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
+++ b/.forge-snapshots/mintWithEmptyHookEOAInitiated.snap
@@ -1 +1 @@
-247151
\ No newline at end of file
+247213
\ No newline at end of file
diff --git a/.forge-snapshots/modify position with noop.snap b/.forge-snapshots/modify position with noop.snap
index 84e389dfe..1af8f8182 100644
--- a/.forge-snapshots/modify position with noop.snap	
+++ b/.forge-snapshots/modify position with noop.snap	
@@ -1 +1 @@
-54101
\ No newline at end of file
+54090
\ No newline at end of file
diff --git a/.forge-snapshots/poolManager bytecode size.snap b/.forge-snapshots/poolManager bytecode size.snap
index 09ce280b6..9c93ec591 100644
--- a/.forge-snapshots/poolManager bytecode size.snap	
+++ b/.forge-snapshots/poolManager bytecode size.snap	
@@ -1 +1 @@
-23847
\ No newline at end of file
+23925
\ No newline at end of file
diff --git a/.forge-snapshots/removeLiquidity with empty hook.snap b/.forge-snapshots/removeLiquidity with empty hook.snap
index d2c53fce5..b18073dc9 100644
--- a/.forge-snapshots/removeLiquidity with empty hook.snap	
+++ b/.forge-snapshots/removeLiquidity with empty hook.snap	
@@ -1 +1 @@
-99936
\ No newline at end of file
+99937
\ No newline at end of file
diff --git a/.forge-snapshots/removeLiquidity with native token.snap b/.forge-snapshots/removeLiquidity with native token.snap
index baf590c91..e8fbdf759 100644
--- a/.forge-snapshots/removeLiquidity with native token.snap	
+++ b/.forge-snapshots/removeLiquidity with native token.snap	
@@ -1 +1 @@
-201309
\ No newline at end of file
+201310
\ No newline at end of file
diff --git a/.forge-snapshots/removeLiquidity.snap b/.forge-snapshots/removeLiquidity.snap
index 04918ec24..1737edf65 100644
--- a/.forge-snapshots/removeLiquidity.snap
+++ b/.forge-snapshots/removeLiquidity.snap
@@ -1 +1 @@
-197586
\ No newline at end of file
+197587
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap with native.snap b/.forge-snapshots/simple swap with native.snap
index 6f27b91e1..f2b3e68b2 100644
--- a/.forge-snapshots/simple swap with native.snap	
+++ b/.forge-snapshots/simple swap with native.snap	
@@ -1 +1 @@
-188027
\ No newline at end of file
+188624
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap.snap b/.forge-snapshots/simple swap.snap
index 7ce4b83c1..a7b4db43b 100644
--- a/.forge-snapshots/simple swap.snap	
+++ b/.forge-snapshots/simple swap.snap	
@@ -1 +1 @@
-196564
\ No newline at end of file
+197164
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapEOAInitiated.snap b/.forge-snapshots/simpleSwapEOAInitiated.snap
index 38c1a1eb5..a856fb2a7 100644
--- a/.forge-snapshots/simpleSwapEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapEOAInitiated.snap
@@ -1 +1 @@
-166450
\ No newline at end of file
+167083
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
index aaea2d8e3..a7dbfb203 100644
--- a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
@@ -1 +1 @@
-165132
\ No newline at end of file
+165611
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity with native token.snap b/.forge-snapshots/swap against liquidity with native token.snap
index 0946afcde..504253c22 100644
--- a/.forge-snapshots/swap against liquidity with native token.snap	
+++ b/.forge-snapshots/swap against liquidity with native token.snap	
@@ -1 +1 @@
-118690
\ No newline at end of file
+119287
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity.snap b/.forge-snapshots/swap against liquidity.snap
index 210a6bf3b..399e9fac5 100644
--- a/.forge-snapshots/swap against liquidity.snap	
+++ b/.forge-snapshots/swap against liquidity.snap	
@@ -1 +1 @@
-106154
\ No newline at end of file
+106754
\ No newline at end of file
diff --git a/.forge-snapshots/swap burn 6909 for input.snap b/.forge-snapshots/swap burn 6909 for input.snap
index ab4b64fdb..cdddfb5d1 100644
--- a/.forge-snapshots/swap burn 6909 for input.snap	
+++ b/.forge-snapshots/swap burn 6909 for input.snap	
@@ -1 +1 @@
-126344
\ No newline at end of file
+126911
\ No newline at end of file
diff --git a/.forge-snapshots/swap burn native 6909 for input.snap b/.forge-snapshots/swap burn native 6909 for input.snap
index 2baddebf2..2b77700ea 100644
--- a/.forge-snapshots/swap burn native 6909 for input.snap	
+++ b/.forge-snapshots/swap burn native 6909 for input.snap	
@@ -1 +1 @@
-122297
\ No newline at end of file
+122864
\ No newline at end of file
diff --git a/.forge-snapshots/swap mint native output as 6909.snap b/.forge-snapshots/swap mint native output as 6909.snap
index f858065c5..10ae205d0 100644
--- a/.forge-snapshots/swap mint native output as 6909.snap	
+++ b/.forge-snapshots/swap mint native output as 6909.snap	
@@ -1 +1 @@
-190554
\ No newline at end of file
+191187
\ No newline at end of file
diff --git a/.forge-snapshots/swap mint output as 6909.snap b/.forge-snapshots/swap mint output as 6909.snap
index 3ad1208f2..d5a69193a 100644
--- a/.forge-snapshots/swap mint output as 6909.snap	
+++ b/.forge-snapshots/swap mint output as 6909.snap	
@@ -1 +1 @@
-207359
\ No newline at end of file
+207992
\ No newline at end of file
diff --git a/.forge-snapshots/swap with dynamic fee.snap b/.forge-snapshots/swap with dynamic fee.snap
index 90130ac49..7ee2664e2 100644
--- a/.forge-snapshots/swap with dynamic fee.snap	
+++ b/.forge-snapshots/swap with dynamic fee.snap	
@@ -1 +1 @@
-184555
\ No newline at end of file
+185155
\ No newline at end of file
diff --git a/.forge-snapshots/swap with hooks.snap b/.forge-snapshots/swap with hooks.snap
index 3803f5a6e..26c53291b 100644
--- a/.forge-snapshots/swap with hooks.snap	
+++ b/.forge-snapshots/swap with hooks.snap	
@@ -1 +1 @@
-106132
\ No newline at end of file
+106732
\ No newline at end of file
diff --git a/.forge-snapshots/update dynamic fee in before swap.snap b/.forge-snapshots/update dynamic fee in before swap.snap
index 849cdfec2..bf8a7f23d 100644
--- a/.forge-snapshots/update dynamic fee in before swap.snap	
+++ b/.forge-snapshots/update dynamic fee in before swap.snap	
@@ -1 +1 @@
-191259
\ No newline at end of file
+191859
\ No newline at end of file
diff --git a/src/PoolManager.sol b/src/PoolManager.sol
index 21b2fab1e..8c32dd114 100644
--- a/src/PoolManager.sol
+++ b/src/PoolManager.sol
@@ -227,8 +227,8 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC6909Claims {
         );
 
         _accountPoolBalanceDelta(key, delta);
-        // the fee is on the input currency
 
+        // the fee is on the input currency
         unchecked {
             if (feeForProtocol > 0) {
                 protocolFeesAccrued[params.zeroForOne ? key.currency0 : key.currency1] += feeForProtocol;
@@ -236,7 +236,7 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC6909Claims {
         }
 
         emit Swap(
-            id, msg.sender, delta.amount0(), delta.amount1(), state.sqrtPriceX96, state.liquidity, state.tick, swapFee
+            id, msg.sender, -delta.amount0(), -delta.amount1(), state.sqrtPriceX96, state.liquidity, state.tick, swapFee
         );
 
         key.hooks.afterSwap(key, params, delta, hookData);
@@ -266,7 +266,8 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC6909Claims {
 
     /// @inheritdoc IPoolManager
     function take(Currency currency, address to, uint256 amount) external override noDelegateCall isLocked {
-        _accountDelta(currency, amount.toInt128());
+        // flipping a postive number in an int is always safe
+        _accountDelta(currency, -(amount.toInt128()));
         reservesOf[currency] -= amount;
         currency.transfer(to, amount);
     }
@@ -276,19 +277,19 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC6909Claims {
         uint256 reservesBefore = reservesOf[currency];
         reservesOf[currency] = currency.balanceOfSelf();
         paid = reservesOf[currency] - reservesBefore;
-        // subtraction must be safe
-        _accountDelta(currency, -(paid.toInt128()));
+        _accountDelta(currency, paid.toInt128());
     }
 
     /// @inheritdoc IPoolManager
     function mint(address to, uint256 id, uint256 amount) external override noDelegateCall isLocked {
-        _accountDelta(CurrencyLibrary.fromId(id), amount.toInt128());
+        // flipping a postive number in an int is always safe
+        _accountDelta(CurrencyLibrary.fromId(id), -(amount.toInt128()));
         _mint(to, id, amount);
     }
 
     /// @inheritdoc IPoolManager
     function burn(address from, uint256 id, uint256 amount) external override noDelegateCall isLocked {
-        _accountDelta(CurrencyLibrary.fromId(id), -(amount.toInt128()));
+        _accountDelta(CurrencyLibrary.fromId(id), amount.toInt128());
         _burnFrom(from, id, amount);
     }
 
diff --git a/src/libraries/Pool.sol b/src/libraries/Pool.sol
index 89b437373..a0869394c 100644
--- a/src/libraries/Pool.sol
+++ b/src/libraries/Pool.sol
@@ -210,7 +210,7 @@ library Pool {
                 // current tick is below the passed range; liquidity can only become in range by crossing from left to
                 // right, when we'll need _more_ currency0 (it's becoming more valuable) so user must provide it
                 result = result
-                    + toBalanceDelta(
+                    - toBalanceDelta(
                         SqrtPriceMath.getAmount0Delta(
                             TickMath.getSqrtRatioAtTick(params.tickLower),
                             TickMath.getSqrtRatioAtTick(params.tickUpper),
@@ -220,7 +220,7 @@ library Pool {
                     );
             } else if (self.slot0.tick < params.tickUpper) {
                 result = result
-                    + toBalanceDelta(
+                    - toBalanceDelta(
                         SqrtPriceMath.getAmount0Delta(
                             self.slot0.sqrtPriceX96, TickMath.getSqrtRatioAtTick(params.tickUpper), params.liquidityDelta
                         ).toInt128(),
@@ -236,7 +236,7 @@ library Pool {
                 // current tick is above the passed range; liquidity can only become in range by crossing from right to
                 // left, when we'll need _more_ currency1 (it's becoming more valuable) so user must provide it
                 result = result
-                    + toBalanceDelta(
+                    - toBalanceDelta(
                         0,
                         SqrtPriceMath.getAmount1Delta(
                             TickMath.getSqrtRatioAtTick(params.tickLower),
@@ -248,7 +248,7 @@ library Pool {
         }
 
         // Fees earned from LPing are removed from the pool balance.
-        result = result - toBalanceDelta(feesOwed0.toInt128(), feesOwed1.toInt128());
+        result = result + toBalanceDelta(feesOwed0.toInt128(), feesOwed1.toInt128());
     }
 
     struct SwapCache {
@@ -444,16 +444,17 @@ library Pool {
             self.feeGrowthGlobal1X128 = state.feeGrowthGlobalX128;
         }
 
+        // in an unchecked block so sign flipping is not safe without a helper function
         unchecked {
             if (params.zeroForOne == exactInput) {
                 result = toBalanceDelta(
-                    (params.amountSpecified - state.amountSpecifiedRemaining).toInt128(),
-                    state.amountCalculated.toInt128()
+                    (params.amountSpecified - state.amountSpecifiedRemaining).toInt128().flipSign(),
+                    state.amountCalculated.toInt128().flipSign()
                 );
             } else {
                 result = toBalanceDelta(
-                    state.amountCalculated.toInt128(),
-                    (params.amountSpecified - state.amountSpecifiedRemaining).toInt128()
+                    state.amountCalculated.toInt128().flipSign(),
+                    (params.amountSpecified - state.amountSpecifiedRemaining).toInt128().flipSign()
                 );
             }
         }
@@ -462,7 +463,7 @@ library Pool {
     /// @notice Donates the given amount of currency0 and currency1 to the pool
     function donate(State storage state, uint256 amount0, uint256 amount1) internal returns (BalanceDelta delta) {
         if (state.liquidity == 0) revert NoLiquidityToReceiveFees();
-        delta = toBalanceDelta(amount0.toInt128(), amount1.toInt128());
+        delta = toBalanceDelta(-(amount0.toInt128()), -(amount1.toInt128()));
         unchecked {
             if (amount0 > 0) {
                 state.feeGrowthGlobal0X128 += FullMath.mulDiv(amount0, FixedPoint128.Q128, state.liquidity);
diff --git a/src/libraries/SafeCast.sol b/src/libraries/SafeCast.sol
index 5eb5bd474..82bcac38c 100644
--- a/src/libraries/SafeCast.sol
+++ b/src/libraries/SafeCast.sol
@@ -37,4 +37,12 @@ library SafeCast {
         if (y > uint128(type(int128).max)) revert SafeCastOverflow();
         z = int128(int256(y));
     }
+
+    /// @notice Flip the sign of an int128, revert on overflow
+    /// @param y The int128 to flip the sign of
+    /// @return The flipped integer, still an int128
+    function flipSign(int128 y) internal pure returns (int128) {
+        // this is not unchecked, so it will revert if y==type(int128).min
+        return -y;
+    }
 }
diff --git a/src/test/PoolClaimsTest.sol b/src/test/PoolClaimsTest.sol
index cf42041a6..f934615b4 100644
--- a/src/test/PoolClaimsTest.sol
+++ b/src/test/PoolClaimsTest.sol
@@ -40,7 +40,7 @@ contract PoolClaimsTest is PoolTestBase {
 
         if (data.deposit) {
             manager.mint(data.user, data.currency.toId(), uint128(data.amount));
-            _settle(data.currency, data.user, data.amount.toInt128(), true);
+            _settle(data.currency, data.user, -data.amount.toInt128(), true);
         } else {
             manager.burn(data.user, data.currency.toId(), uint128(data.amount));
             _take(data.currency, data.user, data.amount.toInt128(), true);
diff --git a/src/test/PoolDonateTest.sol b/src/test/PoolDonateTest.sol
index 7ee393db2..eefb2cf8d 100644
--- a/src/test/PoolDonateTest.sol
+++ b/src/test/PoolDonateTest.sol
@@ -6,11 +6,10 @@ import {IPoolManager} from "../interfaces/IPoolManager.sol";
 import {PoolKey} from "../types/PoolKey.sol";
 import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
 import {PoolTestBase} from "./PoolTestBase.sol";
-import {Test} from "forge-std/Test.sol";
 import {IHooks} from "../interfaces/IHooks.sol";
 import {Hooks} from "../libraries/Hooks.sol";
 
-contract PoolDonateTest is PoolTestBase, Test {
+contract PoolDonateTest is PoolTestBase {
     using CurrencyLibrary for Currency;
     using Hooks for IHooks;
 
@@ -61,8 +60,8 @@ contract PoolDonateTest is PoolTestBase, Test {
         assertEq(reserveBefore0, reserveAfter0);
         assertEq(reserveBefore1, reserveAfter1);
         if (!data.key.hooks.hasPermission(Hooks.NO_OP_FLAG)) {
-            assertEq(deltaAfter0, int256(data.amount0));
-            assertEq(deltaAfter1, int256(data.amount1));
+            assertEq(deltaAfter0, -int256(data.amount0));
+            assertEq(deltaAfter1, -int256(data.amount1));
         }
 
         if (delta == BalanceDeltaLibrary.MAXIMUM_DELTA) {
@@ -71,10 +70,10 @@ contract PoolDonateTest is PoolTestBase, Test {
             return abi.encode(delta);
         }
 
-        if (deltaAfter0 > 0) _settle(data.key.currency0, data.sender, int128(deltaAfter0), true);
-        if (deltaAfter1 > 0) _settle(data.key.currency1, data.sender, int128(deltaAfter1), true);
-        if (deltaAfter0 < 0) _take(data.key.currency0, data.sender, int128(deltaAfter0), true);
-        if (deltaAfter1 < 0) _take(data.key.currency1, data.sender, int128(deltaAfter1), true);
+        if (deltaAfter0 < 0) _settle(data.key.currency0, data.sender, int128(deltaAfter0), true);
+        if (deltaAfter1 < 0) _settle(data.key.currency1, data.sender, int128(deltaAfter1), true);
+        if (deltaAfter0 > 0) _take(data.key.currency0, data.sender, int128(deltaAfter0), true);
+        if (deltaAfter1 > 0) _take(data.key.currency1, data.sender, int128(deltaAfter1), true);
 
         return abi.encode(delta);
     }
diff --git a/src/test/PoolModifyLiquidityTest.sol b/src/test/PoolModifyLiquidityTest.sol
index 3cf7a924f..255fd1657 100644
--- a/src/test/PoolModifyLiquidityTest.sol
+++ b/src/test/PoolModifyLiquidityTest.sol
@@ -66,7 +66,7 @@ contract PoolModifyLiquidityTest is Test, PoolTestBase {
         (,,, int256 delta0) = _fetchBalances(data.key.currency0, data.sender, address(this));
         (,,, int256 delta1) = _fetchBalances(data.key.currency1, data.sender, address(this));
 
-        if (data.params.liquidityDelta > 0) {
+        if (data.params.liquidityDelta < 0) {
             assert(delta0 > 0 || delta1 > 0 || data.key.hooks.hasPermission(Hooks.NO_OP_FLAG));
             assert(!(delta0 < 0 || delta1 < 0));
         } else {
@@ -74,10 +74,10 @@ contract PoolModifyLiquidityTest is Test, PoolTestBase {
             assert(!(delta0 > 0 || delta1 > 0));
         }
 
-        if (delta0 > 0) _settle(data.key.currency0, data.sender, int128(delta0), data.settleUsingTransfer);
-        if (delta1 > 0) _settle(data.key.currency1, data.sender, int128(delta1), data.settleUsingTransfer);
-        if (delta0 < 0) _take(data.key.currency0, data.sender, int128(delta0), data.withdrawTokens);
-        if (delta1 < 0) _take(data.key.currency1, data.sender, int128(delta1), data.withdrawTokens);
+        if (delta0 < 0) _settle(data.key.currency0, data.sender, int128(delta0), data.settleUsingTransfer);
+        if (delta1 < 0) _settle(data.key.currency1, data.sender, int128(delta1), data.settleUsingTransfer);
+        if (delta0 > 0) _take(data.key.currency0, data.sender, int128(delta0), data.withdrawTokens);
+        if (delta1 > 0) _take(data.key.currency1, data.sender, int128(delta1), data.withdrawTokens);
 
         return abi.encode(delta);
     }
diff --git a/src/test/PoolNestedActionsTest.sol b/src/test/PoolNestedActionsTest.sol
index e792e3e49..76548e4cb 100644
--- a/src/test/PoolNestedActionsTest.sol
+++ b/src/test/PoolNestedActionsTest.sol
@@ -120,8 +120,8 @@ contract NestedActionExecutor is Test, PoolTestBase {
 
         assertEq(deltaLockerBefore0, deltaLockerAfter0, "Locker delta 0");
         assertEq(deltaLockerBefore1, deltaLockerAfter1, "Locker delta 1");
-        assertEq(deltaThisBefore0 + SWAP_PARAMS.amountSpecified, deltaThisAfter0, "Executor delta 0");
-        assertEq(deltaThisBefore1 - 98, deltaThisAfter1, "Executor delta 1");
+        assertEq(deltaThisBefore0 - SWAP_PARAMS.amountSpecified, deltaThisAfter0, "Executor delta 0");
+        assertEq(deltaThisBefore1 + 98, deltaThisAfter1, "Executor delta 1");
         assertEq(delta.amount0(), deltaThisAfter0, "Swap delta 0");
         assertEq(delta.amount1(), deltaThisAfter1, "Swap delta 1");
 
@@ -198,10 +198,10 @@ contract NestedActionExecutor is Test, PoolTestBase {
 
         assertEq(deltaLockerBefore0, deltaLockerAfter0, "Locker delta 0");
         assertEq(deltaLockerBefore1, deltaLockerAfter1, "Locker delta 1");
-        assertEq(deltaThisBefore0 + int256(DONATE_AMOUNT0), deltaThisAfter0, "Executor delta 0");
-        assertEq(deltaThisBefore1 + int256(DONATE_AMOUNT1), deltaThisAfter1, "Executor delta 1");
-        assertEq(delta.amount0(), int256(DONATE_AMOUNT0), "Donate delta 0");
-        assertEq(delta.amount1(), int256(DONATE_AMOUNT1), "Donate delta 1");
+        assertEq(deltaThisBefore0 - int256(DONATE_AMOUNT0), deltaThisAfter0, "Executor delta 0");
+        assertEq(deltaThisBefore1 - int256(DONATE_AMOUNT1), deltaThisAfter1, "Executor delta 1");
+        assertEq(-delta.amount0(), int256(DONATE_AMOUNT0), "Donate delta 0");
+        assertEq(-delta.amount1(), int256(DONATE_AMOUNT1), "Donate delta 1");
 
         _settle(key.currency0, user, int128(deltaThisAfter0), true);
         _settle(key.currency1, user, int128(deltaThisAfter1), true);
diff --git a/src/test/PoolSwapTest.sol b/src/test/PoolSwapTest.sol
index 5cde518f6..58d7c14b9 100644
--- a/src/test/PoolSwapTest.sol
+++ b/src/test/PoolSwapTest.sol
@@ -9,6 +9,7 @@ import {IHooks} from "../interfaces/IHooks.sol";
 import {Hooks} from "../libraries/Hooks.sol";
 import {PoolTestBase} from "./PoolTestBase.sol";
 import {Test} from "forge-std/Test.sol";
+import {console2} from "forge-std/console2.sol";
 import {Hooks} from "../libraries/Hooks.sol";
 import {IHooks} from "../interfaces/IHooks.sol";
 
@@ -74,22 +75,22 @@ contract PoolSwapTest is Test, PoolTestBase {
             if (data.params.zeroForOne) {
                 if (data.params.amountSpecified > 0) {
                     // exact input, 0 for 1
-                    assertEq(deltaAfter0, data.params.amountSpecified);
-                    assert(deltaAfter1 < 0);
+                    assertEq(-deltaAfter0, data.params.amountSpecified);
+                    assertGt(deltaAfter1, 0);
                 } else {
                     // exact output, 0 for 1
-                    assert(deltaAfter0 > 0);
-                    assertEq(deltaAfter1, data.params.amountSpecified);
+                    assertLt(deltaAfter0, 0);
+                    assertEq(-deltaAfter1, data.params.amountSpecified);
                 }
             } else {
                 if (data.params.amountSpecified > 0) {
                     // exact input, 1 for 0
-                    assertEq(deltaAfter1, data.params.amountSpecified);
-                    assert(deltaAfter0 < 0);
+                    assertEq(-deltaAfter1, data.params.amountSpecified);
+                    assertGt(deltaAfter0, 0);
                 } else {
                     // exact output, 1 for 0
-                    assert(deltaAfter1 > 0);
-                    assertEq(deltaAfter0, data.params.amountSpecified);
+                    assertLt(deltaAfter1, 0);
+                    assertEq(-deltaAfter0, data.params.amountSpecified);
                 }
             }
         }
@@ -100,24 +101,24 @@ contract PoolSwapTest is Test, PoolTestBase {
             return abi.encode(delta);
         }
 
-        if (deltaAfter0 > 0) {
+        if (deltaAfter0 < 0) {
             if (data.testSettings.currencyAlreadySent) {
                 manager.settle(data.key.currency0);
             } else {
                 _settle(data.key.currency0, data.sender, int128(deltaAfter0), data.testSettings.settleUsingTransfer);
             }
         }
-        if (deltaAfter1 > 0) {
+        if (deltaAfter1 < 0) {
             if (data.testSettings.currencyAlreadySent) {
                 manager.settle(data.key.currency1);
             } else {
                 _settle(data.key.currency1, data.sender, int128(deltaAfter1), data.testSettings.settleUsingTransfer);
             }
         }
-        if (deltaAfter0 < 0) {
+        if (deltaAfter0 > 0) {
             _take(data.key.currency0, data.sender, int128(deltaAfter0), data.testSettings.withdrawTokens);
         }
-        if (deltaAfter1 < 0) {
+        if (deltaAfter1 > 0) {
             _take(data.key.currency1, data.sender, int128(deltaAfter1), data.testSettings.withdrawTokens);
         }
 
diff --git a/src/test/PoolTakeTest.sol b/src/test/PoolTakeTest.sol
index 5a1cfdf9b..66f07b653 100644
--- a/src/test/PoolTakeTest.sol
+++ b/src/test/PoolTakeTest.sol
@@ -41,17 +41,17 @@ contract PoolTakeTest is Test, PoolTestBase {
             _fetchBalances(currency, sender, address(this));
         assertEq(deltaBefore, 0);
 
-        _take(currency, sender, -(amount.toInt128()), true);
+        _take(currency, sender, amount.toInt128(), true);
 
         (uint256 userBalAfter, uint256 pmBalAfter, uint256 reserveAfter, int256 deltaAfter) =
             _fetchBalances(currency, sender, address(this));
-        assertEq(deltaAfter, amount.toInt128());
+        assertEq(deltaAfter, -amount.toInt128());
 
         assertEq(userBalAfter - userBalBefore, amount);
         assertEq(pmBalBefore - pmBalAfter, amount);
         assertEq(reserveBefore - reserveAfter, amount);
         assertEq(reserveBefore - reserveAfter, amount);
 
-        _settle(currency, sender, amount.toInt128(), true);
+        _settle(currency, sender, -amount.toInt128(), true);
     }
 }
diff --git a/src/test/PoolTestBase.sol b/src/test/PoolTestBase.sol
index 020934ba6..102fde356 100644
--- a/src/test/PoolTestBase.sol
+++ b/src/test/PoolTestBase.sol
@@ -1,13 +1,14 @@
 // SPDX-License-Identifier: UNLICENSED
 pragma solidity ^0.8.24;
 
+import {Test} from "forge-std/Test.sol";
 import {CurrencyLibrary, Currency} from "../types/Currency.sol";
 import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
 
 import {ILockCallback} from "../interfaces/callback/ILockCallback.sol";
 import {IPoolManager} from "../interfaces/IPoolManager.sol";
 
-abstract contract PoolTestBase is ILockCallback {
+abstract contract PoolTestBase is Test, ILockCallback {
     using CurrencyLibrary for Currency;
 
     IPoolManager public immutable manager;
@@ -17,25 +18,25 @@ abstract contract PoolTestBase is ILockCallback {
     }
 
     function _take(Currency currency, address recipient, int128 amount, bool withdrawTokens) internal {
-        assert(amount < 0);
+        assertGt(amount, 0);
         if (withdrawTokens) {
-            manager.take(currency, recipient, uint128(-amount));
+            manager.take(currency, recipient, uint128(amount));
         } else {
-            manager.mint(recipient, currency.toId(), uint128(-amount));
+            manager.mint(recipient, currency.toId(), uint128(amount));
         }
     }
 
     function _settle(Currency currency, address payer, int128 amount, bool settleUsingTransfer) internal {
-        assert(amount > 0);
+        assertLt(amount, 0);
         if (settleUsingTransfer) {
             if (currency.isNative()) {
-                manager.settle{value: uint128(amount)}(currency);
+                manager.settle{value: uint128(-amount)}(currency);
             } else {
-                IERC20Minimal(Currency.unwrap(currency)).transferFrom(payer, address(manager), uint128(amount));
+                IERC20Minimal(Currency.unwrap(currency)).transferFrom(payer, address(manager), uint128(-amount));
                 manager.settle(currency);
             }
         } else {
-            manager.burn(payer, currency.toId(), uint128(amount));
+            manager.burn(payer, currency.toId(), uint128(-amount));
         }
     }
 
diff --git a/test/utils/SwapHelper.t.sol b/test/utils/SwapHelper.t.sol
index e89950c72..b26886ae3 100644
--- a/test/utils/SwapHelper.t.sol
+++ b/test/utils/SwapHelper.t.sol
@@ -41,31 +41,31 @@ contract SwapHelperTest is Test, Deployers, GasSnapshot {
     function test_swap_helper_zeroForOne_exactInput() public {
         int256 amountSpecified = 100;
         BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES);
-        assertEq(int256(result.amount0()), amountSpecified);
+        assertEq(-int256(result.amount0()), amountSpecified);
     }
 
     function test_swap_helper_zeroForOne_exactOutput() public {
         int256 amountSpecified = -100;
         BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES);
-        assertEq(int256(result.amount1()), amountSpecified);
+        assertEq(-int256(result.amount1()), amountSpecified);
     }
 
     function test_swap_helper_oneForZero_exactInput() public {
         int256 amountSpecified = 100;
         BalanceDelta result = swap(key, false, amountSpecified, ZERO_BYTES);
-        assertEq(int256(result.amount1()), amountSpecified);
+        assertEq(-int256(result.amount1()), amountSpecified);
     }
 
     function test_swap_helper_oneForZero_exactOutput() public {
         int256 amountSpecified = -100;
         BalanceDelta result = swap(key, false, amountSpecified, ZERO_BYTES);
-        assertEq(int256(result.amount0()), amountSpecified);
+        assertEq(-int256(result.amount0()), amountSpecified);
     }
 
     function test_swap_helper_native_zeroForOne_exactInput() public {
         int256 amountSpecified = 100;
         BalanceDelta result = swap(nativeKey, true, amountSpecified, ZERO_BYTES);
-        assertEq(int256(result.amount0()), amountSpecified);
+        assertEq(-int256(result.amount0()), amountSpecified);
     }
 
     function test_swap_helper_native_zeroForOne_exactOutput() public {
@@ -77,38 +77,38 @@ contract SwapHelperTest is Test, Deployers, GasSnapshot {
     function test_swap_helper_native_oneForZero_exactInput() public {
         int256 amountSpecified = 100;
         BalanceDelta result = swap(nativeKey, false, amountSpecified, ZERO_BYTES);
-        assertEq(int256(result.amount1()), amountSpecified);
+        assertEq(-int256(result.amount1()), amountSpecified);
     }
 
     function test_swap_helper_native_oneForZero_exactOutput() public {
         int256 amountSpecified = -100;
         BalanceDelta result = swap(nativeKey, false, amountSpecified, ZERO_BYTES);
-        assertEq(int256(result.amount0()), amountSpecified);
+        assertEq(-int256(result.amount0()), amountSpecified);
     }
 
     // --- Deployers.swapNativeInput() tests --- //
     function test_swapNativeInput_helper_zeroForOne_exactInput() public {
         int256 amountSpecified = 100;
         BalanceDelta result = swapNativeInput(nativeKey, true, amountSpecified, ZERO_BYTES, 100 wei);
-        assertEq(int256(result.amount0()), amountSpecified);
+        assertEq(-int256(result.amount0()), amountSpecified);
     }
 
     function test_swapNativeInput_helper_zeroForOne_exactOutput() public {
         int256 amountSpecified = -100;
         BalanceDelta result = swapNativeInput(nativeKey, true, amountSpecified, ZERO_BYTES, 200 wei); // overpay
-        assertEq(int256(result.amount1()), amountSpecified);
+        assertEq(-int256(result.amount1()), amountSpecified);
     }
 
     function test_swapNativeInput_helper_oneForZero_exactInput() public {
         int256 amountSpecified = 100;
         BalanceDelta result = swapNativeInput(nativeKey, false, amountSpecified, ZERO_BYTES, 0 wei);
-        assertEq(int256(result.amount1()), amountSpecified);
+        assertEq(-int256(result.amount1()), amountSpecified);
     }
 
     function test_swapNativeInput_helper_oneForZero_exactOutput() public {
         int256 amountSpecified = -100;
         BalanceDelta result = swapNativeInput(nativeKey, false, amountSpecified, ZERO_BYTES, 0 wei);
-        assertEq(int256(result.amount0()), amountSpecified);
+        assertEq(-int256(result.amount0()), amountSpecified);
     }
 
     function test_swapNativeInput_helper_nonnative_zeroForOne_exactInput() public {

From ba1494d5e979276029dea6d84dab77cfeb602615 Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Wed, 14 Feb 2024 15:15:42 -0300
Subject: [PATCH 14/19] update comments

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index a6019eea6..8368925db 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@ A more detailed description of Uniswap v4 Core can be found in the draft of the
 - `settle`
 - `mint`
 
-Only the net balances owed to the pool (positive) or to the user (negative) are tracked throughout the duration of a lock. This is the `delta` field held in the lock state. Any number of actions can be run on the pools, as long as the deltas accumulated during the lock reach 0 by the lock’s release. This lock and call style architecture gives callers maximum flexibility in integrating with the core code.
+Only the net balances owed to the user (positive) or to the pool (negative) are tracked throughout the duration of a lock. This is the `delta` field held in the lock state. Any number of actions can be run on the pools, as long as the deltas accumulated during the lock reach 0 by the lock’s release. This lock and call style architecture gives callers maximum flexibility in integrating with the core code.
 
 Additionally, a pool may be initialized with a hook contract, that can implement any of the following callbacks in the lifecycle of pool actions:
 

From d8ebb60ec3cf1677116b88f435c5e5068e57dab4 Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Wed, 6 Mar 2024 12:42:41 -0300
Subject: [PATCH 15/19] remove unnecessary read of result

---
 .../addLiquidity with empty hook.snap         |  2 +-
 .../addLiquidity with native token.snap       |  2 +-
 .forge-snapshots/addLiquidity.snap            |  2 +-
 .../poolManager bytecode size.snap            |  2 +-
 .../removeLiquidity with empty hook.snap      |  2 +-
 .../removeLiquidity with native token.snap    |  2 +-
 .forge-snapshots/removeLiquidity.snap         |  2 +-
 src/libraries/Pool.sol                        | 53 +++++++++----------
 8 files changed, 32 insertions(+), 35 deletions(-)

diff --git a/.forge-snapshots/addLiquidity with empty hook.snap b/.forge-snapshots/addLiquidity with empty hook.snap
index 1c96f61c7..7d693797f 100644
--- a/.forge-snapshots/addLiquidity with empty hook.snap	
+++ b/.forge-snapshots/addLiquidity with empty hook.snap	
@@ -1 +1 @@
-312838
\ No newline at end of file
+312630
\ No newline at end of file
diff --git a/.forge-snapshots/addLiquidity with native token.snap b/.forge-snapshots/addLiquidity with native token.snap
index 511a946be..c54c69058 100644
--- a/.forge-snapshots/addLiquidity with native token.snap	
+++ b/.forge-snapshots/addLiquidity with native token.snap	
@@ -1 +1 @@
-193017
\ No newline at end of file
+192809
\ No newline at end of file
diff --git a/.forge-snapshots/addLiquidity.snap b/.forge-snapshots/addLiquidity.snap
index 30e2b0c4c..020c828a7 100644
--- a/.forge-snapshots/addLiquidity.snap
+++ b/.forge-snapshots/addLiquidity.snap
@@ -1 +1 @@
-192998
\ No newline at end of file
+192790
\ No newline at end of file
diff --git a/.forge-snapshots/poolManager bytecode size.snap b/.forge-snapshots/poolManager bytecode size.snap
index 2d32836cb..dab2b10ac 100644
--- a/.forge-snapshots/poolManager bytecode size.snap	
+++ b/.forge-snapshots/poolManager bytecode size.snap	
@@ -1 +1 @@
-23459
\ No newline at end of file
+23414
\ No newline at end of file
diff --git a/.forge-snapshots/removeLiquidity with empty hook.snap b/.forge-snapshots/removeLiquidity with empty hook.snap
index 45d2eb688..99601b1a8 100644
--- a/.forge-snapshots/removeLiquidity with empty hook.snap	
+++ b/.forge-snapshots/removeLiquidity with empty hook.snap	
@@ -1 +1 @@
-99591
\ No newline at end of file
+99383
\ No newline at end of file
diff --git a/.forge-snapshots/removeLiquidity with native token.snap b/.forge-snapshots/removeLiquidity with native token.snap
index de06d078a..9cb6f5adf 100644
--- a/.forge-snapshots/removeLiquidity with native token.snap	
+++ b/.forge-snapshots/removeLiquidity with native token.snap	
@@ -1 +1 @@
-200964
\ No newline at end of file
+200756
\ No newline at end of file
diff --git a/.forge-snapshots/removeLiquidity.snap b/.forge-snapshots/removeLiquidity.snap
index 4cbde64b2..c09e30a7e 100644
--- a/.forge-snapshots/removeLiquidity.snap
+++ b/.forge-snapshots/removeLiquidity.snap
@@ -1 +1 @@
-197241
\ No newline at end of file
+197033
\ No newline at end of file
diff --git a/src/libraries/Pool.sol b/src/libraries/Pool.sol
index a0869394c..212b79335 100644
--- a/src/libraries/Pool.sol
+++ b/src/libraries/Pool.sol
@@ -209,25 +209,23 @@ library Pool {
             if (self.slot0.tick < params.tickLower) {
                 // current tick is below the passed range; liquidity can only become in range by crossing from left to
                 // right, when we'll need _more_ currency0 (it's becoming more valuable) so user must provide it
-                result = result
-                    - toBalanceDelta(
-                        SqrtPriceMath.getAmount0Delta(
-                            TickMath.getSqrtRatioAtTick(params.tickLower),
-                            TickMath.getSqrtRatioAtTick(params.tickUpper),
-                            params.liquidityDelta
-                        ).toInt128(),
-                        0
-                    );
+                result = toBalanceDelta(
+                    -SqrtPriceMath.getAmount0Delta(
+                        TickMath.getSqrtRatioAtTick(params.tickLower),
+                        TickMath.getSqrtRatioAtTick(params.tickUpper),
+                        params.liquidityDelta
+                    ).toInt128(),
+                    0
+                );
             } else if (self.slot0.tick < params.tickUpper) {
-                result = result
-                    - toBalanceDelta(
-                        SqrtPriceMath.getAmount0Delta(
-                            self.slot0.sqrtPriceX96, TickMath.getSqrtRatioAtTick(params.tickUpper), params.liquidityDelta
-                        ).toInt128(),
-                        SqrtPriceMath.getAmount1Delta(
-                            TickMath.getSqrtRatioAtTick(params.tickLower), self.slot0.sqrtPriceX96, params.liquidityDelta
-                        ).toInt128()
-                    );
+                result = toBalanceDelta(
+                    -SqrtPriceMath.getAmount0Delta(
+                        self.slot0.sqrtPriceX96, TickMath.getSqrtRatioAtTick(params.tickUpper), params.liquidityDelta
+                    ).toInt128(),
+                    -SqrtPriceMath.getAmount1Delta(
+                        TickMath.getSqrtRatioAtTick(params.tickLower), self.slot0.sqrtPriceX96, params.liquidityDelta
+                    ).toInt128()
+                );
 
                 self.liquidity = params.liquidityDelta < 0
                     ? self.liquidity - uint128(-params.liquidityDelta)
@@ -235,19 +233,18 @@ library Pool {
             } else {
                 // current tick is above the passed range; liquidity can only become in range by crossing from right to
                 // left, when we'll need _more_ currency1 (it's becoming more valuable) so user must provide it
-                result = result
-                    - toBalanceDelta(
-                        0,
-                        SqrtPriceMath.getAmount1Delta(
-                            TickMath.getSqrtRatioAtTick(params.tickLower),
-                            TickMath.getSqrtRatioAtTick(params.tickUpper),
-                            params.liquidityDelta
-                        ).toInt128()
-                    );
+                result = toBalanceDelta(
+                    0,
+                    -SqrtPriceMath.getAmount1Delta(
+                        TickMath.getSqrtRatioAtTick(params.tickLower),
+                        TickMath.getSqrtRatioAtTick(params.tickUpper),
+                        params.liquidityDelta
+                    ).toInt128()
+                );
             }
         }
 
-        // Fees earned from LPing are removed from the pool balance.
+        // Fees earned from LPing are added to the user's currency delta.
         result = result + toBalanceDelta(feesOwed0.toInt128(), feesOwed1.toInt128());
     }
 

From f45c75a4384a427ed3d71597f15061e9f53bb936 Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Wed, 6 Mar 2024 14:40:37 -0300
Subject: [PATCH 16/19] move delta flip to sqrtprice lib

---
 .forge-snapshots/addLiquidity with empty hook.snap     |  2 +-
 .forge-snapshots/addLiquidity with native token.snap   |  2 +-
 .forge-snapshots/addLiquidity.snap                     |  2 +-
 .forge-snapshots/poolManager bytecode size.snap        |  2 +-
 .forge-snapshots/removeLiquidity with empty hook.snap  |  2 +-
 .../removeLiquidity with native token.snap             |  2 +-
 .forge-snapshots/removeLiquidity.snap                  |  2 +-
 src/libraries/Pool.sol                                 |  8 ++++----
 src/libraries/SqrtPriceMath.sol                        |  8 ++++----
 test/SqrtPriceMath.t.sol                               | 10 ++++++++--
 10 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/.forge-snapshots/addLiquidity with empty hook.snap b/.forge-snapshots/addLiquidity with empty hook.snap
index 7d693797f..fc770a713 100644
--- a/.forge-snapshots/addLiquidity with empty hook.snap	
+++ b/.forge-snapshots/addLiquidity with empty hook.snap	
@@ -1 +1 @@
-312630
\ No newline at end of file
+312478
\ No newline at end of file
diff --git a/.forge-snapshots/addLiquidity with native token.snap b/.forge-snapshots/addLiquidity with native token.snap
index c54c69058..470796a74 100644
--- a/.forge-snapshots/addLiquidity with native token.snap	
+++ b/.forge-snapshots/addLiquidity with native token.snap	
@@ -1 +1 @@
-192809
\ No newline at end of file
+192657
\ No newline at end of file
diff --git a/.forge-snapshots/addLiquidity.snap b/.forge-snapshots/addLiquidity.snap
index 020c828a7..982717200 100644
--- a/.forge-snapshots/addLiquidity.snap
+++ b/.forge-snapshots/addLiquidity.snap
@@ -1 +1 @@
-192790
\ No newline at end of file
+192638
\ No newline at end of file
diff --git a/.forge-snapshots/poolManager bytecode size.snap b/.forge-snapshots/poolManager bytecode size.snap
index dab2b10ac..552760727 100644
--- a/.forge-snapshots/poolManager bytecode size.snap	
+++ b/.forge-snapshots/poolManager bytecode size.snap	
@@ -1 +1 @@
-23414
\ No newline at end of file
+23388
\ No newline at end of file
diff --git a/.forge-snapshots/removeLiquidity with empty hook.snap b/.forge-snapshots/removeLiquidity with empty hook.snap
index 99601b1a8..bf53e294c 100644
--- a/.forge-snapshots/removeLiquidity with empty hook.snap	
+++ b/.forge-snapshots/removeLiquidity with empty hook.snap	
@@ -1 +1 @@
-99383
\ No newline at end of file
+99211
\ No newline at end of file
diff --git a/.forge-snapshots/removeLiquidity with native token.snap b/.forge-snapshots/removeLiquidity with native token.snap
index 9cb6f5adf..915a91210 100644
--- a/.forge-snapshots/removeLiquidity with native token.snap	
+++ b/.forge-snapshots/removeLiquidity with native token.snap	
@@ -1 +1 @@
-200756
\ No newline at end of file
+200584
\ No newline at end of file
diff --git a/.forge-snapshots/removeLiquidity.snap b/.forge-snapshots/removeLiquidity.snap
index c09e30a7e..bb3614637 100644
--- a/.forge-snapshots/removeLiquidity.snap
+++ b/.forge-snapshots/removeLiquidity.snap
@@ -1 +1 @@
-197033
\ No newline at end of file
+196861
\ No newline at end of file
diff --git a/src/libraries/Pool.sol b/src/libraries/Pool.sol
index 212b79335..c4699630d 100644
--- a/src/libraries/Pool.sol
+++ b/src/libraries/Pool.sol
@@ -210,7 +210,7 @@ library Pool {
                 // current tick is below the passed range; liquidity can only become in range by crossing from left to
                 // right, when we'll need _more_ currency0 (it's becoming more valuable) so user must provide it
                 result = toBalanceDelta(
-                    -SqrtPriceMath.getAmount0Delta(
+                    SqrtPriceMath.getAmount0Delta(
                         TickMath.getSqrtRatioAtTick(params.tickLower),
                         TickMath.getSqrtRatioAtTick(params.tickUpper),
                         params.liquidityDelta
@@ -219,10 +219,10 @@ library Pool {
                 );
             } else if (self.slot0.tick < params.tickUpper) {
                 result = toBalanceDelta(
-                    -SqrtPriceMath.getAmount0Delta(
+                    SqrtPriceMath.getAmount0Delta(
                         self.slot0.sqrtPriceX96, TickMath.getSqrtRatioAtTick(params.tickUpper), params.liquidityDelta
                     ).toInt128(),
-                    -SqrtPriceMath.getAmount1Delta(
+                    SqrtPriceMath.getAmount1Delta(
                         TickMath.getSqrtRatioAtTick(params.tickLower), self.slot0.sqrtPriceX96, params.liquidityDelta
                     ).toInt128()
                 );
@@ -235,7 +235,7 @@ library Pool {
                 // left, when we'll need _more_ currency1 (it's becoming more valuable) so user must provide it
                 result = toBalanceDelta(
                     0,
-                    -SqrtPriceMath.getAmount1Delta(
+                    SqrtPriceMath.getAmount1Delta(
                         TickMath.getSqrtRatioAtTick(params.tickLower),
                         TickMath.getSqrtRatioAtTick(params.tickUpper),
                         params.liquidityDelta
diff --git a/src/libraries/SqrtPriceMath.sol b/src/libraries/SqrtPriceMath.sol
index a391012c7..0839eb73c 100644
--- a/src/libraries/SqrtPriceMath.sol
+++ b/src/libraries/SqrtPriceMath.sol
@@ -200,8 +200,8 @@ library SqrtPriceMath {
     {
         unchecked {
             return liquidity < 0
-                ? -getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()
-                : getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();
+                ? getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()
+                : -getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();
         }
     }
 
@@ -217,8 +217,8 @@ library SqrtPriceMath {
     {
         unchecked {
             return liquidity < 0
-                ? -getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()
-                : getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();
+                ? getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()
+                : -getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();
         }
     }
 }
diff --git a/test/SqrtPriceMath.t.sol b/test/SqrtPriceMath.t.sol
index 68a8edeca..1f47e15fe 100644
--- a/test/SqrtPriceMath.t.sol
+++ b/test/SqrtPriceMath.t.sol
@@ -249,7 +249,7 @@ contract SqrtPriceMathTestTest is Test, GasSnapshot {
         assertEq(amount0, 0);
     }
 
-    function test_getAmount0Delta_returns0_1Amount1ForPriceOf1To1_21() public {
+    function test_getAmount0Delta_1Amount1ForPriceOf1To1_21() public {
         uint256 amount0 = SqrtPriceMath.getAmount0Delta(
             Constants.SQRT_RATIO_1_1, Constants.SQRT_RATIO_121_100, uint128(1 ether), true
         );
@@ -300,7 +300,7 @@ contract SqrtPriceMathTestTest is Test, GasSnapshot {
         assertEq(amount1, 0);
     }
 
-    function test_getAmount1Delta_returns0_1Amount1ForPriceOf1To1_21() public {
+    function test_getAmount1Delta_1Amount1ForPriceOf1To1_21() public {
         uint256 amount1 = SqrtPriceMath.getAmount1Delta(
             Constants.SQRT_RATIO_1_1, Constants.SQRT_RATIO_121_100, uint128(1 ether), true
         );
@@ -320,6 +320,12 @@ contract SqrtPriceMathTestTest is Test, GasSnapshot {
         snapEnd();
     }
 
+    function test_getAmount1Delta_gasCostForAmount1WhereRoundUpIsTrue() public {
+        snapStart("getAmount1Delta_gasCostForAmount1WhereRoundUpIsTrue");
+        SqrtPriceMath.getAmount1Delta(Constants.SQRT_RATIO_121_100, Constants.SQRT_RATIO_1_1, uint128(1 ether), true);
+        snapEnd();
+    }
+
     function test_getAmount1Delta_gasCostForAmount1WhereRoundUpIsFalse() public {
         snapStart("getAmount1Delta_gasCostForAmount1WhereRoundUpIsFalse");
         SqrtPriceMath.getAmount1Delta(Constants.SQRT_RATIO_121_100, Constants.SQRT_RATIO_1_1, uint128(1 ether), false);

From 0043fa4e314a71281be49d61df22b209737e2b91 Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Wed, 6 Mar 2024 14:47:39 -0300
Subject: [PATCH 17/19] remove duplicate test

---
 test/SqrtPriceMath.t.sol | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/test/SqrtPriceMath.t.sol b/test/SqrtPriceMath.t.sol
index 1f47e15fe..cb63d0cbf 100644
--- a/test/SqrtPriceMath.t.sol
+++ b/test/SqrtPriceMath.t.sol
@@ -320,12 +320,6 @@ contract SqrtPriceMathTestTest is Test, GasSnapshot {
         snapEnd();
     }
 
-    function test_getAmount1Delta_gasCostForAmount1WhereRoundUpIsTrue() public {
-        snapStart("getAmount1Delta_gasCostForAmount1WhereRoundUpIsTrue");
-        SqrtPriceMath.getAmount1Delta(Constants.SQRT_RATIO_121_100, Constants.SQRT_RATIO_1_1, uint128(1 ether), true);
-        snapEnd();
-    }
-
     function test_getAmount1Delta_gasCostForAmount1WhereRoundUpIsFalse() public {
         snapStart("getAmount1Delta_gasCostForAmount1WhereRoundUpIsFalse");
         SqrtPriceMath.getAmount1Delta(Constants.SQRT_RATIO_121_100, Constants.SQRT_RATIO_1_1, uint128(1 ether), false);

From 1a76db2d6ca52ab3e097e49c803d629611517cd4 Mon Sep 17 00:00:00 2001
From: Emily Williams <emag3m@gmail.com>
Date: Wed, 6 Mar 2024 14:56:03 -0500
Subject: [PATCH 18/19] amountSpecified matches deltas (#491)

Co-authored-by: hensha256 <henshawalice@gmail.com>
---
 .../SwapMath_oneForZero_exactInCapped.snap    |  2 +-
 .../SwapMath_oneForZero_exactInPartial.snap   |  2 +-
 .../SwapMath_oneForZero_exactOutCapped.snap   |  2 +-
 .../SwapMath_oneForZero_exactOutPartial.snap  |  2 +-
 .../SwapMath_zeroForOne_exactInCapped.snap    |  2 +-
 .../SwapMath_zeroForOne_exactInPartial.snap   |  2 +-
 .../SwapMath_zeroForOne_exactOutCapped.snap   |  2 +-
 .../SwapMath_zeroForOne_exactOutPartial.snap  |  2 +-
 ...swap hook, already cached dynamic fee.snap |  2 +-
 .../cached dynamic fee, no hooks.snap         |  2 +-
 .../poolManager bytecode size.snap            |  2 +-
 .forge-snapshots/simple swap with native.snap |  2 +-
 .forge-snapshots/simple swap.snap             |  2 +-
 .forge-snapshots/simpleSwapEOAInitiated.snap  |  2 +-
 .../simpleSwapNativeEOAInitiated.snap         |  2 +-
 ...p against liquidity with native token.snap |  2 +-
 .forge-snapshots/swap against liquidity.snap  |  2 +-
 .../swap burn 6909 for input.snap             |  2 +-
 .../swap burn native 6909 for input.snap      |  2 +-
 .../swap mint native output as 6909.snap      |  2 +-
 .../swap mint output as 6909.snap             |  2 +-
 .forge-snapshots/swap with dynamic fee.snap   |  2 +-
 .forge-snapshots/swap with hooks.snap         |  2 +-
 .../update dynamic fee in before swap.snap    |  2 +-
 src/PoolManager.sol                           |  2 +-
 src/libraries/Pool.sol                        | 18 +++----
 src/libraries/SafeCast.sol                    |  8 ---
 src/libraries/SwapMath.sol                    | 14 ++---
 src/test/PoolNestedActionsTest.sol            |  4 +-
 src/test/PoolSwapTest.sol                     | 12 ++---
 test/DynamicFees.t.sol                        | 16 +++---
 test/PoolManager.t.sol                        | 54 +++++++++----------
 test/SwapMath.t.sol                           | 30 +++++------
 test/utils/Deployers.sol                      |  4 +-
 test/utils/SwapHelper.t.sol                   | 54 +++++++++----------
 35 files changed, 128 insertions(+), 136 deletions(-)

diff --git a/.forge-snapshots/SwapMath_oneForZero_exactInCapped.snap b/.forge-snapshots/SwapMath_oneForZero_exactInCapped.snap
index 9fbf3f867..27d48e9a4 100644
--- a/.forge-snapshots/SwapMath_oneForZero_exactInCapped.snap
+++ b/.forge-snapshots/SwapMath_oneForZero_exactInCapped.snap
@@ -1 +1 @@
-2203
\ No newline at end of file
+1947
\ No newline at end of file
diff --git a/.forge-snapshots/SwapMath_oneForZero_exactInPartial.snap b/.forge-snapshots/SwapMath_oneForZero_exactInPartial.snap
index b19e196ad..9560ba822 100644
--- a/.forge-snapshots/SwapMath_oneForZero_exactInPartial.snap
+++ b/.forge-snapshots/SwapMath_oneForZero_exactInPartial.snap
@@ -1 +1 @@
-3028
\ No newline at end of file
+3238
\ No newline at end of file
diff --git a/.forge-snapshots/SwapMath_oneForZero_exactOutCapped.snap b/.forge-snapshots/SwapMath_oneForZero_exactOutCapped.snap
index 05949f123..758e03adc 100644
--- a/.forge-snapshots/SwapMath_oneForZero_exactOutCapped.snap
+++ b/.forge-snapshots/SwapMath_oneForZero_exactOutCapped.snap
@@ -1 +1 @@
-1963
\ No newline at end of file
+2208
\ No newline at end of file
diff --git a/.forge-snapshots/SwapMath_oneForZero_exactOutPartial.snap b/.forge-snapshots/SwapMath_oneForZero_exactOutPartial.snap
index b19e196ad..9560ba822 100644
--- a/.forge-snapshots/SwapMath_oneForZero_exactOutPartial.snap
+++ b/.forge-snapshots/SwapMath_oneForZero_exactOutPartial.snap
@@ -1 +1 @@
-3028
\ No newline at end of file
+3238
\ No newline at end of file
diff --git a/.forge-snapshots/SwapMath_zeroForOne_exactInCapped.snap b/.forge-snapshots/SwapMath_zeroForOne_exactInCapped.snap
index 61b5691d1..12057ad70 100644
--- a/.forge-snapshots/SwapMath_zeroForOne_exactInCapped.snap
+++ b/.forge-snapshots/SwapMath_zeroForOne_exactInCapped.snap
@@ -1 +1 @@
-2193
\ No newline at end of file
+1937
\ No newline at end of file
diff --git a/.forge-snapshots/SwapMath_zeroForOne_exactInPartial.snap b/.forge-snapshots/SwapMath_zeroForOne_exactInPartial.snap
index 1a81226e6..c173e591f 100644
--- a/.forge-snapshots/SwapMath_zeroForOne_exactInPartial.snap
+++ b/.forge-snapshots/SwapMath_zeroForOne_exactInPartial.snap
@@ -1 +1 @@
-3181
\ No newline at end of file
+2826
\ No newline at end of file
diff --git a/.forge-snapshots/SwapMath_zeroForOne_exactOutCapped.snap b/.forge-snapshots/SwapMath_zeroForOne_exactOutCapped.snap
index 6d92a178f..c802063a0 100644
--- a/.forge-snapshots/SwapMath_zeroForOne_exactOutCapped.snap
+++ b/.forge-snapshots/SwapMath_zeroForOne_exactOutCapped.snap
@@ -1 +1 @@
-1953
\ No newline at end of file
+2198
\ No newline at end of file
diff --git a/.forge-snapshots/SwapMath_zeroForOne_exactOutPartial.snap b/.forge-snapshots/SwapMath_zeroForOne_exactOutPartial.snap
index 1a81226e6..c173e591f 100644
--- a/.forge-snapshots/SwapMath_zeroForOne_exactOutPartial.snap
+++ b/.forge-snapshots/SwapMath_zeroForOne_exactOutPartial.snap
@@ -1 +1 @@
-3181
\ No newline at end of file
+2826
\ No newline at end of file
diff --git a/.forge-snapshots/before swap hook, already cached dynamic fee.snap b/.forge-snapshots/before swap hook, already cached dynamic fee.snap
index e9aec1167..981929aca 100644
--- a/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
+++ b/.forge-snapshots/before swap hook, already cached dynamic fee.snap	
@@ -1 +1 @@
-185335
\ No newline at end of file
+184850
\ No newline at end of file
diff --git a/.forge-snapshots/cached dynamic fee, no hooks.snap b/.forge-snapshots/cached dynamic fee, no hooks.snap
index 61d8c9782..af2004dd5 100644
--- a/.forge-snapshots/cached dynamic fee, no hooks.snap	
+++ b/.forge-snapshots/cached dynamic fee, no hooks.snap	
@@ -1 +1 @@
-139362
\ No newline at end of file
+138877
\ No newline at end of file
diff --git a/.forge-snapshots/poolManager bytecode size.snap b/.forge-snapshots/poolManager bytecode size.snap
index 552760727..bc5e03d4b 100644
--- a/.forge-snapshots/poolManager bytecode size.snap	
+++ b/.forge-snapshots/poolManager bytecode size.snap	
@@ -1 +1 @@
-23388
\ No newline at end of file
+23323
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap with native.snap b/.forge-snapshots/simple swap with native.snap
index 0a345d1f6..3209f2c45 100644
--- a/.forge-snapshots/simple swap with native.snap	
+++ b/.forge-snapshots/simple swap with native.snap	
@@ -1 +1 @@
-187932
\ No newline at end of file
+187447
\ No newline at end of file
diff --git a/.forge-snapshots/simple swap.snap b/.forge-snapshots/simple swap.snap
index 0a7e23711..2e5f87b51 100644
--- a/.forge-snapshots/simple swap.snap	
+++ b/.forge-snapshots/simple swap.snap	
@@ -1 +1 @@
-196472
\ No newline at end of file
+195987
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapEOAInitiated.snap b/.forge-snapshots/simpleSwapEOAInitiated.snap
index a856fb2a7..07992eea9 100644
--- a/.forge-snapshots/simpleSwapEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapEOAInitiated.snap
@@ -1 +1 @@
-167083
\ No newline at end of file
+166598
\ No newline at end of file
diff --git a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
index a7dbfb203..16f69621a 100644
--- a/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
+++ b/.forge-snapshots/simpleSwapNativeEOAInitiated.snap
@@ -1 +1 @@
-165611
\ No newline at end of file
+165126
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity with native token.snap b/.forge-snapshots/swap against liquidity with native token.snap
index 39f69af23..e86de2e5d 100644
--- a/.forge-snapshots/swap against liquidity with native token.snap	
+++ b/.forge-snapshots/swap against liquidity with native token.snap	
@@ -1 +1 @@
-118595
\ No newline at end of file
+118106
\ No newline at end of file
diff --git a/.forge-snapshots/swap against liquidity.snap b/.forge-snapshots/swap against liquidity.snap
index ed0bccfac..7ef41f543 100644
--- a/.forge-snapshots/swap against liquidity.snap	
+++ b/.forge-snapshots/swap against liquidity.snap	
@@ -1 +1 @@
-106062
\ No newline at end of file
+105573
\ No newline at end of file
diff --git a/.forge-snapshots/swap burn 6909 for input.snap b/.forge-snapshots/swap burn 6909 for input.snap
index 22728cc3a..0eda177e1 100644
--- a/.forge-snapshots/swap burn 6909 for input.snap	
+++ b/.forge-snapshots/swap burn 6909 for input.snap	
@@ -1 +1 @@
-126218
\ No newline at end of file
+125700
\ No newline at end of file
diff --git a/.forge-snapshots/swap burn native 6909 for input.snap b/.forge-snapshots/swap burn native 6909 for input.snap
index 056426fae..e188f56da 100644
--- a/.forge-snapshots/swap burn native 6909 for input.snap	
+++ b/.forge-snapshots/swap burn native 6909 for input.snap	
@@ -1 +1 @@
-122171
\ No newline at end of file
+121653
\ No newline at end of file
diff --git a/.forge-snapshots/swap mint native output as 6909.snap b/.forge-snapshots/swap mint native output as 6909.snap
index 5b925b581..8da1a1e6a 100644
--- a/.forge-snapshots/swap mint native output as 6909.snap	
+++ b/.forge-snapshots/swap mint native output as 6909.snap	
@@ -1 +1 @@
-190494
\ No newline at end of file
+190005
\ No newline at end of file
diff --git a/.forge-snapshots/swap mint output as 6909.snap b/.forge-snapshots/swap mint output as 6909.snap
index 8346aab23..57cb7b38e 100644
--- a/.forge-snapshots/swap mint output as 6909.snap	
+++ b/.forge-snapshots/swap mint output as 6909.snap	
@@ -1 +1 @@
-207299
\ No newline at end of file
+206814
\ No newline at end of file
diff --git a/.forge-snapshots/swap with dynamic fee.snap b/.forge-snapshots/swap with dynamic fee.snap
index 9c4a53763..0c7ae4c05 100644
--- a/.forge-snapshots/swap with dynamic fee.snap	
+++ b/.forge-snapshots/swap with dynamic fee.snap	
@@ -1 +1 @@
-184436
\ No newline at end of file
+183951
\ No newline at end of file
diff --git a/.forge-snapshots/swap with hooks.snap b/.forge-snapshots/swap with hooks.snap
index fa9619017..aff2d029f 100644
--- a/.forge-snapshots/swap with hooks.snap	
+++ b/.forge-snapshots/swap with hooks.snap	
@@ -1 +1 @@
-106040
\ No newline at end of file
+105551
\ No newline at end of file
diff --git a/.forge-snapshots/update dynamic fee in before swap.snap b/.forge-snapshots/update dynamic fee in before swap.snap
index d554a0afa..c17d44032 100644
--- a/.forge-snapshots/update dynamic fee in before swap.snap	
+++ b/.forge-snapshots/update dynamic fee in before swap.snap	
@@ -1 +1 @@
-191140
\ No newline at end of file
+190655
\ No newline at end of file
diff --git a/src/PoolManager.sol b/src/PoolManager.sol
index e530decc1..4b0c705eb 100644
--- a/src/PoolManager.sol
+++ b/src/PoolManager.sol
@@ -231,7 +231,7 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC6909Claims {
         }
 
         emit Swap(
-            id, msg.sender, -delta.amount0(), -delta.amount1(), state.sqrtPriceX96, state.liquidity, state.tick, swapFee
+            id, msg.sender, delta.amount0(), delta.amount1(), state.sqrtPriceX96, state.liquidity, state.tick, swapFee
         );
 
         key.hooks.afterSwap(key, params, delta, hookData);
diff --git a/src/libraries/Pool.sol b/src/libraries/Pool.sol
index c4699630d..72549922e 100644
--- a/src/libraries/Pool.sol
+++ b/src/libraries/Pool.sol
@@ -326,7 +326,7 @@ library Pool {
             protocolFee: params.zeroForOne ? uint8(slot0Start.protocolFee % 256) : uint8(slot0Start.protocolFee >> 8)
         });
 
-        bool exactInput = params.amountSpecified > 0;
+        bool exactInput = params.amountSpecified < 0;
 
         state = SwapState({
             amountSpecifiedRemaining: params.amountSpecified,
@@ -371,14 +371,14 @@ library Pool {
             if (exactInput) {
                 // safe because we test that amountSpecified > amountIn + feeAmount in SwapMath
                 unchecked {
-                    state.amountSpecifiedRemaining -= (step.amountIn + step.feeAmount).toInt256();
+                    state.amountSpecifiedRemaining += (step.amountIn + step.feeAmount).toInt256();
                 }
-                state.amountCalculated = state.amountCalculated - step.amountOut.toInt256();
+                state.amountCalculated = state.amountCalculated + step.amountOut.toInt256();
             } else {
                 unchecked {
-                    state.amountSpecifiedRemaining += step.amountOut.toInt256();
+                    state.amountSpecifiedRemaining -= step.amountOut.toInt256();
                 }
-                state.amountCalculated = state.amountCalculated + (step.amountIn + step.feeAmount).toInt256();
+                state.amountCalculated = state.amountCalculated - (step.amountIn + step.feeAmount).toInt256();
             }
 
             // if the protocol fee is on, calculate how much is owed, decrement feeAmount, and increment protocolFee
@@ -445,13 +445,13 @@ library Pool {
         unchecked {
             if (params.zeroForOne == exactInput) {
                 result = toBalanceDelta(
-                    (params.amountSpecified - state.amountSpecifiedRemaining).toInt128().flipSign(),
-                    state.amountCalculated.toInt128().flipSign()
+                    (params.amountSpecified - state.amountSpecifiedRemaining).toInt128(),
+                    state.amountCalculated.toInt128()
                 );
             } else {
                 result = toBalanceDelta(
-                    state.amountCalculated.toInt128().flipSign(),
-                    (params.amountSpecified - state.amountSpecifiedRemaining).toInt128().flipSign()
+                    state.amountCalculated.toInt128(),
+                    (params.amountSpecified - state.amountSpecifiedRemaining).toInt128()
                 );
             }
         }
diff --git a/src/libraries/SafeCast.sol b/src/libraries/SafeCast.sol
index 82bcac38c..5eb5bd474 100644
--- a/src/libraries/SafeCast.sol
+++ b/src/libraries/SafeCast.sol
@@ -37,12 +37,4 @@ library SafeCast {
         if (y > uint128(type(int128).max)) revert SafeCastOverflow();
         z = int128(int256(y));
     }
-
-    /// @notice Flip the sign of an int128, revert on overflow
-    /// @param y The int128 to flip the sign of
-    /// @return The flipped integer, still an int128
-    function flipSign(int128 y) internal pure returns (int128) {
-        // this is not unchecked, so it will revert if y==type(int128).min
-        return -y;
-    }
 }
diff --git a/src/libraries/SwapMath.sol b/src/libraries/SwapMath.sol
index 6c011dd3b..d7ba4405d 100644
--- a/src/libraries/SwapMath.sol
+++ b/src/libraries/SwapMath.sol
@@ -27,10 +27,10 @@ library SwapMath {
     ) internal pure returns (uint160 sqrtRatioNextX96, uint256 amountIn, uint256 amountOut, uint256 feeAmount) {
         unchecked {
             bool zeroForOne = sqrtRatioCurrentX96 >= sqrtRatioTargetX96;
-            bool exactIn = amountRemaining >= 0;
+            bool exactIn = amountRemaining < 0;
 
             if (exactIn) {
-                uint256 amountRemainingLessFee = FullMath.mulDiv(uint256(amountRemaining), 1e6 - feePips, 1e6);
+                uint256 amountRemainingLessFee = FullMath.mulDiv(uint256(-amountRemaining), 1e6 - feePips, 1e6);
                 amountIn = zeroForOne
                     ? SqrtPriceMath.getAmount0Delta(sqrtRatioTargetX96, sqrtRatioCurrentX96, liquidity, true)
                     : SqrtPriceMath.getAmount1Delta(sqrtRatioCurrentX96, sqrtRatioTargetX96, liquidity, true);
@@ -45,11 +45,11 @@ library SwapMath {
                 amountOut = zeroForOne
                     ? SqrtPriceMath.getAmount1Delta(sqrtRatioTargetX96, sqrtRatioCurrentX96, liquidity, false)
                     : SqrtPriceMath.getAmount0Delta(sqrtRatioCurrentX96, sqrtRatioTargetX96, liquidity, false);
-                if (uint256(-amountRemaining) >= amountOut) {
+                if (uint256(amountRemaining) >= amountOut) {
                     sqrtRatioNextX96 = sqrtRatioTargetX96;
                 } else {
                     sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromOutput(
-                        sqrtRatioCurrentX96, liquidity, uint256(-amountRemaining), zeroForOne
+                        sqrtRatioCurrentX96, liquidity, uint256(amountRemaining), zeroForOne
                     );
                 }
             }
@@ -74,13 +74,13 @@ library SwapMath {
             }
 
             // cap the output amount to not exceed the remaining output amount
-            if (!exactIn && amountOut > uint256(-amountRemaining)) {
-                amountOut = uint256(-amountRemaining);
+            if (!exactIn && amountOut > uint256(amountRemaining)) {
+                amountOut = uint256(amountRemaining);
             }
 
             if (exactIn && sqrtRatioNextX96 != sqrtRatioTargetX96) {
                 // we didn't reach the target, so take the remainder of the maximum input as fee
-                feeAmount = uint256(amountRemaining) - amountIn;
+                feeAmount = uint256(-amountRemaining) - amountIn;
             } else {
                 feeAmount = FullMath.mulDivRoundingUp(amountIn, feePips, 1e6 - feePips);
             }
diff --git a/src/test/PoolNestedActionsTest.sol b/src/test/PoolNestedActionsTest.sol
index 9cdc8f8e9..5ad95f9ab 100644
--- a/src/test/PoolNestedActionsTest.sol
+++ b/src/test/PoolNestedActionsTest.sol
@@ -70,7 +70,7 @@ contract NestedActionExecutor is Test, PoolTestBase {
         IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: -1e18});
 
     IPoolManager.SwapParams internal SWAP_PARAMS =
-        IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: Constants.SQRT_RATIO_1_2});
+        IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: Constants.SQRT_RATIO_1_2});
 
     uint256 internal DONATE_AMOUNT0 = 12345e6;
     uint256 internal DONATE_AMOUNT1 = 98765e4;
@@ -124,7 +124,7 @@ contract NestedActionExecutor is Test, PoolTestBase {
 
         assertEq(deltaLockerBefore0, deltaLockerAfter0, "Locker delta 0");
         assertEq(deltaLockerBefore1, deltaLockerAfter1, "Locker delta 1");
-        assertEq(deltaThisBefore0 - SWAP_PARAMS.amountSpecified, deltaThisAfter0, "Executor delta 0");
+        assertEq(deltaThisBefore0 + SWAP_PARAMS.amountSpecified, deltaThisAfter0, "Executor delta 0");
         assertEq(deltaThisBefore1 + 98, deltaThisAfter1, "Executor delta 1");
         assertEq(delta.amount0(), deltaThisAfter0, "Swap delta 0");
         assertEq(delta.amount1(), deltaThisAfter1, "Swap delta 1");
diff --git a/src/test/PoolSwapTest.sol b/src/test/PoolSwapTest.sol
index 822425fc0..dde0e3119 100644
--- a/src/test/PoolSwapTest.sol
+++ b/src/test/PoolSwapTest.sol
@@ -71,24 +71,24 @@ contract PoolSwapTest is Test, PoolTestBase {
         assertEq(reserveBefore1, reserveAfter1);
 
         if (data.params.zeroForOne) {
-            if (data.params.amountSpecified > 0) {
+            if (data.params.amountSpecified < 0) {
                 // exact input, 0 for 1
-                assertEq(-deltaAfter0, data.params.amountSpecified);
+                assertEq(deltaAfter0, data.params.amountSpecified);
                 assertGt(deltaAfter1, 0);
             } else {
                 // exact output, 0 for 1
                 assertLt(deltaAfter0, 0);
-                assertEq(-deltaAfter1, data.params.amountSpecified);
+                assertEq(deltaAfter1, data.params.amountSpecified);
             }
         } else {
-            if (data.params.amountSpecified > 0) {
+            if (data.params.amountSpecified < 0) {
                 // exact input, 1 for 0
-                assertEq(-deltaAfter1, data.params.amountSpecified);
+                assertEq(deltaAfter1, data.params.amountSpecified);
                 assertGt(deltaAfter0, 0);
             } else {
                 // exact output, 1 for 0
                 assertLt(deltaAfter1, 0);
-                assertEq(-deltaAfter0, data.params.amountSpecified);
+                assertEq(deltaAfter0, data.params.amountSpecified);
             }
         }
 
diff --git a/test/DynamicFees.t.sol b/test/DynamicFees.t.sol
index 9ad0df3e3..47a90eba5 100644
--- a/test/DynamicFees.t.sol
+++ b/test/DynamicFees.t.sol
@@ -103,12 +103,12 @@ contract TestDynamicFees is Test, Deployers, GasSnapshot {
         manager.updateDynamicSwapFee(key);
 
         IPoolManager.SwapParams memory params =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});
 
         vm.expectEmit(true, true, true, true, address(manager));
-        emit Swap(key.toId(), address(swapRouter), 100, -98, 79228162514264329749955861424, 1e18, -1, 123);
+        emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 123);
 
         snapStart("swap with dynamic fee");
         swapRouter.swap(key, params, testSettings, ZERO_BYTES);
@@ -120,12 +120,12 @@ contract TestDynamicFees is Test, Deployers, GasSnapshot {
         manager.updateDynamicSwapFee(key);
 
         IPoolManager.SwapParams memory params =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});
 
         vm.expectEmit(true, true, true, true, address(manager));
-        emit Swap(key.toId(), address(swapRouter), 100, -98, 79228162514264329749955861424, 1e18, -1, 456);
+        emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 456);
         bytes memory data = abi.encode(true, uint24(456));
 
         snapStart("update dynamic fee in before swap");
@@ -138,12 +138,12 @@ contract TestDynamicFees is Test, Deployers, GasSnapshot {
         manager.updateDynamicSwapFee(key);
 
         IPoolManager.SwapParams memory params =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});
 
         vm.expectEmit(true, true, true, true, address(manager));
-        emit Swap(key.toId(), address(swapRouter), 100, -98, 79228162514264329749955861424, 1e18, -1, 123);
+        emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 123);
         bytes memory data = abi.encode(false, uint24(0));
 
         snapStart("before swap hook, already cached dynamic fee");
@@ -166,12 +166,12 @@ contract TestDynamicFees is Test, Deployers, GasSnapshot {
         manager.updateDynamicSwapFee(key);
 
         IPoolManager.SwapParams memory params =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});
 
         vm.expectEmit(true, true, true, true, address(manager));
-        emit Swap(key.toId(), address(swapRouter), 100, -98, 79228162514264329749955861424, 1e18, -1, 123);
+        emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 123);
 
         snapStart("cached dynamic fee, no hooks");
         swapRouter.swap(key, params, testSettings, ZERO_BYTES);
diff --git a/test/PoolManager.t.sol b/test/PoolManager.t.sol
index 93932f912..e4b1b34e2 100644
--- a/test/PoolManager.t.sol
+++ b/test/PoolManager.t.sol
@@ -411,7 +411,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
         key.fee = 100;
         IPoolManager.SwapParams memory params =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: sqrtPriceX96});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: sqrtPriceX96});
 
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});
@@ -422,14 +422,14 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
     function test_swap_succeedsIfInitialized() public {
         IPoolManager.SwapParams memory swapParams =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
 
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: false, settleUsingTransfer: true, currencyAlreadySent: false});
 
         vm.expectEmit(true, true, true, true);
         emit Swap(
-            key.toId(), address(swapRouter), int128(100), int128(-98), 79228162514264329749955861424, 1e18, -1, 3000
+            key.toId(), address(swapRouter), int128(-100), int128(98), 79228162514264329749955861424, 1e18, -1, 3000
         );
 
         swapRouter.swap(key, swapParams, testSettings, ZERO_BYTES);
@@ -437,7 +437,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
     function test_swap_succeedsWithNativeTokensIfInitialized() public {
         IPoolManager.SwapParams memory swapParams =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
 
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: false, settleUsingTransfer: true, currencyAlreadySent: false});
@@ -446,8 +446,8 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
         emit Swap(
             nativeKey.toId(),
             address(swapRouter),
-            int128(100),
-            int128(-98),
+            int128(-100),
+            int128(98),
             79228162514264329749955861424,
             1e18,
             -1,
@@ -470,7 +470,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
         (key,) = initPoolAndAddLiquidity(currency0, currency1, IHooks(mockAddr), 3000, SQRT_RATIO_1_1, ZERO_BYTES);
 
         IPoolManager.SwapParams memory swapParams =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
 
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: false, settleUsingTransfer: true, currencyAlreadySent: false});
@@ -527,7 +527,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
         (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_RATIO_1_1, ZERO_BYTES);
 
         IPoolManager.SwapParams memory swapParams =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 10, sqrtPriceLimitX96: SQRT_RATIO_1_2});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -10, sqrtPriceLimitX96: SQRT_RATIO_1_2});
 
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: false, settleUsingTransfer: true, currencyAlreadySent: false});
@@ -536,14 +536,14 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
         mockHooks.setReturnValue(mockHooks.afterSwap.selector, mockHooks.afterSwap.selector);
 
         vm.expectEmit(true, true, true, true);
-        emit Swap(key.toId(), address(swapRouter), 10, -8, 79228162514264336880490487708, 1e18, -1, 100);
+        emit Swap(key.toId(), address(swapRouter), -10, 8, 79228162514264336880490487708, 1e18, -1, 100);
 
         swapRouter.swap(key, swapParams, testSettings, ZERO_BYTES);
     }
 
     function test_swap_gas() public {
         IPoolManager.SwapParams memory swapParams =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
 
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});
@@ -555,7 +555,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
     function test_swap_withNative_gas() public {
         IPoolManager.SwapParams memory swapParams =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
 
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});
@@ -575,7 +575,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
         (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 3000, SQRT_RATIO_1_1, ZERO_BYTES);
 
         IPoolManager.SwapParams memory swapParams =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
 
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});
@@ -583,7 +583,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
         swapRouter.swap(key, swapParams, testSettings, ZERO_BYTES);
 
         swapParams =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_4});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_4});
         testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});
 
@@ -594,7 +594,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
     function test_swap_mint6909IfOutputNotTaken_gas() public {
         IPoolManager.SwapParams memory params =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
 
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: false, settleUsingTransfer: true, currencyAlreadySent: false});
@@ -611,7 +611,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
     function test_swap_mint6909IfNativeOutputNotTaken_gas() public {
         IPoolManager.SwapParams memory params =
-            IPoolManager.SwapParams({zeroForOne: false, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_2_1});
+            IPoolManager.SwapParams({zeroForOne: false, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_2_1});
 
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: false, settleUsingTransfer: true, currencyAlreadySent: false});
@@ -628,7 +628,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
     function test_swap_burn6909AsInput_gas() public {
         IPoolManager.SwapParams memory params =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
 
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: false, settleUsingTransfer: true, currencyAlreadySent: false});
@@ -644,7 +644,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
         manager.setOperator(address(swapRouter), true);
 
         // swap from currency1 to currency0 again, using 6909s as input tokens
-        params = IPoolManager.SwapParams({zeroForOne: false, amountSpecified: -25, sqrtPriceLimitX96: SQRT_RATIO_4_1});
+        params = IPoolManager.SwapParams({zeroForOne: false, amountSpecified: 25, sqrtPriceLimitX96: SQRT_RATIO_4_1});
         testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: false, currencyAlreadySent: false});
 
@@ -660,7 +660,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
     function test_swap_burnNative6909AsInput_gas() public {
         IPoolManager.SwapParams memory params =
-            IPoolManager.SwapParams({zeroForOne: false, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_2_1});
+            IPoolManager.SwapParams({zeroForOne: false, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_2_1});
 
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: false, settleUsingTransfer: true, currencyAlreadySent: false});
@@ -676,7 +676,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
         manager.setOperator(address(swapRouter), true);
 
         // swap from currency0 to currency1, using 6909s as input tokens
-        params = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -25, sqrtPriceLimitX96: SQRT_RATIO_1_4});
+        params = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 25, sqrtPriceLimitX96: SQRT_RATIO_1_4});
         testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: false, currencyAlreadySent: false});
 
@@ -693,14 +693,14 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
     function test_swap_againstLiq_gas() public {
         IPoolManager.SwapParams memory params =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
 
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});
 
         swapRouter.swap(key, params, testSettings, ZERO_BYTES);
 
-        params = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_4});
+        params = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_4});
 
         snapStart("swap against liquidity");
         swapRouter.swap(key, params, testSettings, ZERO_BYTES);
@@ -709,14 +709,14 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
     function test_swap_againstLiqWithNative_gas() public {
         IPoolManager.SwapParams memory params =
-            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
+            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
 
         PoolSwapTest.TestSettings memory testSettings =
             PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});
 
         swapRouter.swap{value: 1 ether}(nativeKey, params, testSettings, ZERO_BYTES);
 
-        params = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_4});
+        params = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_4});
 
         snapStart("swap against liquidity with native token");
         swapRouter.swap{value: 1 ether}(nativeKey, params, testSettings, ZERO_BYTES);
@@ -753,10 +753,10 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
         params.liquidityDelta = LIQ_PARAMS.liquidityDelta;
         modifyLiquidityRouter.modifyLiquidity(key, params, ZERO_BYTES);
 
-        IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams(false, 10000, TickMath.MAX_SQRT_RATIO - 1);
+        IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams(false, -10000, TickMath.MAX_SQRT_RATIO - 1);
         swapRouter.swap(key, swapParams, PoolSwapTest.TestSettings(true, true, false), ZERO_BYTES);
 
-        uint256 expectedTotalSwapFee = uint256(swapParams.amountSpecified) * key.fee / 1e6;
+        uint256 expectedTotalSwapFee = uint256(-swapParams.amountSpecified) * key.fee / 1e6;
         uint256 expectedProtocolFee = expectedTotalSwapFee / protocolFee1;
         assertEq(manager.protocolFeesAccrued(currency0), 0);
         assertEq(manager.protocolFeesAccrued(currency1), expectedProtocolFee);
@@ -1013,7 +1013,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
         swapRouter.swap{value: 10000}(
             nativeKey,
-            IPoolManager.SwapParams(true, 10000, SQRT_RATIO_1_2),
+            IPoolManager.SwapParams(true, -10000, SQRT_RATIO_1_2),
             PoolSwapTest.TestSettings(true, true, false),
             ZERO_BYTES
         );
@@ -1042,7 +1042,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
 
         swapRouter.swap{value: 10000}(
             nativeKey,
-            IPoolManager.SwapParams(true, 10000, SQRT_RATIO_1_2),
+            IPoolManager.SwapParams(true, -10000, SQRT_RATIO_1_2),
             PoolSwapTest.TestSettings(true, true, false),
             ZERO_BYTES
         );
diff --git a/test/SwapMath.t.sol b/test/SwapMath.t.sol
index ad63dc41d..ebabd5da6 100644
--- a/test/SwapMath.t.sol
+++ b/test/SwapMath.t.sol
@@ -66,7 +66,7 @@ contract SwapMathTest is Test, GasSnapshot {
         uint160 priceTarget = SQRT_RATIO_1000_100;
         uint160 price = SQRT_RATIO_1_1;
         uint128 liquidity = 2 ether;
-        int256 amount = 1 ether;
+        int256 amount = 1 ether * -1;
         uint24 fee = 600;
         bool zeroForOne = false;
 
@@ -76,10 +76,10 @@ contract SwapMathTest is Test, GasSnapshot {
         assertEq(amountIn, 999400000000000000);
         assertEq(amountOut, 666399946655997866);
         assertEq(feeAmount, 600000000000000);
-        assertEq(amountIn + feeAmount, uint256(amount));
+        assertEq(amountIn + feeAmount, uint256(-amount));
 
         uint256 priceAfterWholeInputAmountLessFee =
-            SqrtPriceMath.getNextSqrtPriceFromInput(price, liquidity, uint256(uint256(amount) - feeAmount), zeroForOne);
+            SqrtPriceMath.getNextSqrtPriceFromInput(price, liquidity, uint256(uint256(-amount) - feeAmount), zeroForOne);
 
         assert(sqrtQ < priceTarget);
         assertEq(sqrtQ, priceAfterWholeInputAmountLessFee);
@@ -89,7 +89,7 @@ contract SwapMathTest is Test, GasSnapshot {
         uint160 priceTarget = SQRT_RATIO_10000_100;
         uint160 price = SQRT_RATIO_1_1;
         uint128 liquidity = 2 ether;
-        int256 amount = (1 ether) * -1;
+        int256 amount = (1 ether);
         uint24 fee = 600;
         bool zeroForOne = false;
 
@@ -98,10 +98,10 @@ contract SwapMathTest is Test, GasSnapshot {
 
         assertEq(amountIn, 2000000000000000000);
         assertEq(feeAmount, 1200720432259356);
-        assertEq(amountOut, uint256(amount * -1));
+        assertEq(amountOut, uint256(amount));
 
         uint256 priceAfterWholeOutputAmount =
-            SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, uint256(amount * -1), zeroForOne);
+            SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, uint256(amount), zeroForOne);
 
         assert(sqrtQ < priceTarget);
         assertEq(sqrtQ, priceAfterWholeOutputAmount);
@@ -109,7 +109,7 @@ contract SwapMathTest is Test, GasSnapshot {
 
     function test_amountOut_isCappedAtTheDesiredAmountOut() public {
         (uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) = SwapMath.computeSwapStep(
-            417332158212080721273783715441582, 1452870262520218020823638996, 159344665391607089467575320103, -1, 1
+            417332158212080721273783715441582, 1452870262520218020823638996, 159344665391607089467575320103, 1, 1
         );
 
         assertEq(amountIn, 1);
@@ -130,7 +130,7 @@ contract SwapMathTest is Test, GasSnapshot {
 
     function test_entireInputAmountTakenAsFee() public {
         (uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) =
-            SwapMath.computeSwapStep(2413, 79887613182836312, 1985041575832132834610021537970, 10, 1872);
+            SwapMath.computeSwapStep(2413, 79887613182836312, 1985041575832132834610021537970, -10, 1872);
 
         assertEq(amountIn, 0);
         assertEq(feeAmount, 10);
@@ -144,7 +144,7 @@ contract SwapMathTest is Test, GasSnapshot {
         uint128 liquidity = 1024;
         // virtual reserves of one are only 4
         // https://www.wolframalpha.com/input/?i=1024+%2F+%2820282409603651670423947251286016+%2F+2**96%29
-        int256 amountRemaining = -4;
+        int256 amountRemaining = 4;
         uint24 feePips = 3000;
 
         (uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) =
@@ -162,7 +162,7 @@ contract SwapMathTest is Test, GasSnapshot {
         uint128 liquidity = 1024;
         // virtual reserves of zero are only 262144
         // https://www.wolframalpha.com/input/?i=1024+*+%2820282409603651670423947251286016+%2F+2**96%29
-        int256 amountRemaining = -263000;
+        int256 amountRemaining = 263000;
         uint24 feePips = 3000;
 
         (uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) =
@@ -192,10 +192,10 @@ contract SwapMathTest is Test, GasSnapshot {
         assertLe(amountIn, type(uint256).max - feeAmount);
 
         unchecked {
-            if (amountRemaining < 0) {
-                assertLe(amountOut, uint256(-amountRemaining));
+            if (amountRemaining >= 0) {
+                assertLe(amountOut, uint256(amountRemaining));
             } else {
-                assertLe(amountIn + feeAmount, uint256(amountRemaining));
+                assertLe(amountIn + feeAmount, uint256(-amountRemaining));
             }
         }
 
@@ -208,8 +208,8 @@ contract SwapMathTest is Test, GasSnapshot {
 
         // didn't reach price target, entire amount must be consumed
         if (sqrtQ != sqrtPriceTargetRaw) {
-            if (amountRemaining < 0) assertEq(amountOut, uint256(-amountRemaining));
-            else assertEq(amountIn + feeAmount, uint256(amountRemaining));
+            if (amountRemaining > 0) assertEq(amountOut, uint256(amountRemaining));
+            else assertEq(amountIn + feeAmount, uint256(-amountRemaining));
         }
 
         // next price is between price and price target
diff --git a/test/utils/Deployers.sol b/test/utils/Deployers.sol
index d3fbc1658..e19425015 100644
--- a/test/utils/Deployers.sol
+++ b/test/utils/Deployers.sol
@@ -192,9 +192,9 @@ contract Deployers {
     {
         // allow native input for exact-input, guide users to the `swapNativeInput` function
         bool isNativeInput = zeroForOne && _key.currency0.isNative();
-        if (isNativeInput) require(0 < amountSpecified, "Use swapNativeInput() for native-token exact-output swaps");
+        if (isNativeInput) require(0 > amountSpecified, "Use swapNativeInput() for native-token exact-output swaps");
 
-        uint256 value = isNativeInput ? uint256(amountSpecified) : 0;
+        uint256 value = isNativeInput ? uint256(-amountSpecified) : 0;
 
         return swapRouter.swap{value: value}(
             _key,
diff --git a/test/utils/SwapHelper.t.sol b/test/utils/SwapHelper.t.sol
index b26886ae3..1d83d663b 100644
--- a/test/utils/SwapHelper.t.sol
+++ b/test/utils/SwapHelper.t.sol
@@ -39,98 +39,98 @@ contract SwapHelperTest is Test, Deployers, GasSnapshot {
 
     // --- Deployers.swap() tests --- //
     function test_swap_helper_zeroForOne_exactInput() public {
-        int256 amountSpecified = 100;
+        int256 amountSpecified = -100;
         BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES);
-        assertEq(-int256(result.amount0()), amountSpecified);
+        assertEq(result.amount0(), amountSpecified);
     }
 
     function test_swap_helper_zeroForOne_exactOutput() public {
-        int256 amountSpecified = -100;
+        int256 amountSpecified = 100;
         BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES);
-        assertEq(-int256(result.amount1()), amountSpecified);
+        assertEq(result.amount1(), amountSpecified);
     }
 
     function test_swap_helper_oneForZero_exactInput() public {
-        int256 amountSpecified = 100;
+        int256 amountSpecified = -100;
         BalanceDelta result = swap(key, false, amountSpecified, ZERO_BYTES);
-        assertEq(-int256(result.amount1()), amountSpecified);
+        assertEq(result.amount1(), amountSpecified);
     }
 
     function test_swap_helper_oneForZero_exactOutput() public {
-        int256 amountSpecified = -100;
+        int256 amountSpecified = 100;
         BalanceDelta result = swap(key, false, amountSpecified, ZERO_BYTES);
-        assertEq(-int256(result.amount0()), amountSpecified);
+        assertEq(result.amount0(), amountSpecified);
     }
 
     function test_swap_helper_native_zeroForOne_exactInput() public {
-        int256 amountSpecified = 100;
+        int256 amountSpecified = -100;
         BalanceDelta result = swap(nativeKey, true, amountSpecified, ZERO_BYTES);
-        assertEq(-int256(result.amount0()), amountSpecified);
+        assertEq(result.amount0(), amountSpecified);
     }
 
     function test_swap_helper_native_zeroForOne_exactOutput() public {
-        int256 amountSpecified = -100;
+        int256 amountSpecified = 100;
         vm.expectRevert();
         swap(nativeKey, true, amountSpecified, ZERO_BYTES);
     }
 
     function test_swap_helper_native_oneForZero_exactInput() public {
-        int256 amountSpecified = 100;
+        int256 amountSpecified = -100;
         BalanceDelta result = swap(nativeKey, false, amountSpecified, ZERO_BYTES);
-        assertEq(-int256(result.amount1()), amountSpecified);
+        assertEq(result.amount1(), amountSpecified);
     }
 
     function test_swap_helper_native_oneForZero_exactOutput() public {
-        int256 amountSpecified = -100;
+        int256 amountSpecified = 100;
         BalanceDelta result = swap(nativeKey, false, amountSpecified, ZERO_BYTES);
-        assertEq(-int256(result.amount0()), amountSpecified);
+        assertEq(result.amount0(), amountSpecified);
     }
 
     // --- Deployers.swapNativeInput() tests --- //
     function test_swapNativeInput_helper_zeroForOne_exactInput() public {
-        int256 amountSpecified = 100;
+        int256 amountSpecified = -100;
         BalanceDelta result = swapNativeInput(nativeKey, true, amountSpecified, ZERO_BYTES, 100 wei);
-        assertEq(-int256(result.amount0()), amountSpecified);
+        assertEq(result.amount0(), amountSpecified);
     }
 
     function test_swapNativeInput_helper_zeroForOne_exactOutput() public {
-        int256 amountSpecified = -100;
+        int256 amountSpecified = 100;
         BalanceDelta result = swapNativeInput(nativeKey, true, amountSpecified, ZERO_BYTES, 200 wei); // overpay
-        assertEq(-int256(result.amount1()), amountSpecified);
+        assertEq(result.amount1(), amountSpecified);
     }
 
     function test_swapNativeInput_helper_oneForZero_exactInput() public {
-        int256 amountSpecified = 100;
+        int256 amountSpecified = -100;
         BalanceDelta result = swapNativeInput(nativeKey, false, amountSpecified, ZERO_BYTES, 0 wei);
-        assertEq(-int256(result.amount1()), amountSpecified);
+        assertEq(result.amount1(), amountSpecified);
     }
 
     function test_swapNativeInput_helper_oneForZero_exactOutput() public {
-        int256 amountSpecified = -100;
+        int256 amountSpecified = 100;
         BalanceDelta result = swapNativeInput(nativeKey, false, amountSpecified, ZERO_BYTES, 0 wei);
-        assertEq(-int256(result.amount0()), amountSpecified);
+        assertEq(result.amount0(), amountSpecified);
     }
 
     function test_swapNativeInput_helper_nonnative_zeroForOne_exactInput() public {
-        int256 amountSpecified = 100;
+        int256 amountSpecified = -100;
         vm.expectRevert();
         swapNativeInput(key, true, amountSpecified, ZERO_BYTES, 0 wei);
     }
 
     function test_swapNativeInput_helper_nonnative_zeroForOne_exactOutput() public {
-        int256 amountSpecified = -100;
+        int256 amountSpecified = 100;
         vm.expectRevert();
         swapNativeInput(key, true, amountSpecified, ZERO_BYTES, 0 wei);
     }
 
     function test_swapNativeInput_helper_nonnative_oneForZero_exactInput() public {
-        int256 amountSpecified = 100;
+        int256 amountSpecified = -100;
         vm.expectRevert();
         swapNativeInput(key, false, amountSpecified, ZERO_BYTES, 0 wei);
     }
 
     function test_swapNativeInput_helper_nonnative_oneForZero_exactOutput() public {
-        int256 amountSpecified = -100;
+        int256 amountSpecified = 100;
         vm.expectRevert();
         swapNativeInput(key, false, amountSpecified, ZERO_BYTES, 0 wei);
     }

From 4a1ccfa5ca5ca4b979fed2b5b95eb849aeb5ee42 Mon Sep 17 00:00:00 2001
From: hensha256 <henshawalice@gmail.com>
Date: Fri, 8 Mar 2024 11:49:11 -0300
Subject: [PATCH 19/19] PR nits

---
 src/PoolManager.sol       | 4 ++--
 src/libraries/Pool.sol    | 1 -
 src/test/PoolSwapTest.sol | 1 -
 3 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/PoolManager.sol b/src/PoolManager.sol
index 4b0c705eb..ff2e4e4af 100644
--- a/src/PoolManager.sol
+++ b/src/PoolManager.sol
@@ -259,7 +259,7 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC6909Claims {
 
     /// @inheritdoc IPoolManager
     function take(Currency currency, address to, uint256 amount) external override noDelegateCall isLocked {
-        // flipping a postive number in an int is always safe
+        // subtraction must be safe
         _accountDelta(currency, -(amount.toInt128()));
         reservesOf[currency] -= amount;
         currency.transfer(to, amount);
@@ -275,7 +275,7 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC6909Claims {
 
     /// @inheritdoc IPoolManager
     function mint(address to, uint256 id, uint256 amount) external override noDelegateCall isLocked {
-        // flipping a postive number in an int is always safe
+        // subtraction must be safe
         _accountDelta(CurrencyLibrary.fromId(id), -(amount.toInt128()));
         _mint(to, id, amount);
     }
diff --git a/src/libraries/Pool.sol b/src/libraries/Pool.sol
index 72549922e..5deb01e2b 100644
--- a/src/libraries/Pool.sol
+++ b/src/libraries/Pool.sol
@@ -441,7 +441,6 @@ library Pool {
             self.feeGrowthGlobal1X128 = state.feeGrowthGlobalX128;
         }
 
-        // in an unchecked block so sign flipping is not safe without a helper function
         unchecked {
             if (params.zeroForOne == exactInput) {
                 result = toBalanceDelta(
diff --git a/src/test/PoolSwapTest.sol b/src/test/PoolSwapTest.sol
index dde0e3119..757b8379d 100644
--- a/src/test/PoolSwapTest.sol
+++ b/src/test/PoolSwapTest.sol
@@ -9,7 +9,6 @@ import {IHooks} from "../interfaces/IHooks.sol";
 import {Hooks} from "../libraries/Hooks.sol";
 import {PoolTestBase} from "./PoolTestBase.sol";
 import {Test} from "forge-std/Test.sol";
-import {console2} from "forge-std/console2.sol";
 import {Hooks} from "../libraries/Hooks.sol";
 import {IHooks} from "../interfaces/IHooks.sol";