diff --git a/.forge-snapshots/add liquidity to already existing position with salt.snap b/.forge-snapshots/add liquidity to already existing position with salt.snap index 229a6f36b..567cfb72b 100644 --- a/.forge-snapshots/add liquidity to already existing position with salt.snap +++ b/.forge-snapshots/add liquidity to already existing position with salt.snap @@ -1 +1 @@ -144615 \ No newline at end of file +144639 \ No newline at end of file diff --git a/.forge-snapshots/addLiquidity CA fee.snap b/.forge-snapshots/addLiquidity CA fee.snap index 2dbb0582b..8342ac755 100644 --- a/.forge-snapshots/addLiquidity CA fee.snap +++ b/.forge-snapshots/addLiquidity CA fee.snap @@ -1 +1 @@ -170904 \ No newline at end of file +170928 \ No newline at end of file diff --git a/.forge-snapshots/addLiquidity with empty hook.snap b/.forge-snapshots/addLiquidity with empty hook.snap index c402ac3f7..b04e884a5 100644 --- a/.forge-snapshots/addLiquidity with empty hook.snap +++ b/.forge-snapshots/addLiquidity with empty hook.snap @@ -1 +1 @@ -274182 \ No newline at end of file +274240 \ 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 007796950..cd7fd0616 100644 --- a/.forge-snapshots/addLiquidity with native token.snap +++ b/.forge-snapshots/addLiquidity with native token.snap @@ -1 +1 @@ -135108 \ No newline at end of file +135120 \ No newline at end of file diff --git a/.forge-snapshots/create new liquidity to a position with salt.snap b/.forge-snapshots/create new liquidity to a position with salt.snap index 35994a0d0..521237ab9 100644 --- a/.forge-snapshots/create new liquidity to a position with salt.snap +++ b/.forge-snapshots/create new liquidity to a position with salt.snap @@ -1 +1 @@ -292807 \ No newline at end of file +292831 \ 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 2b407e08d..f2a99d3bb 100644 --- a/.forge-snapshots/donate gas with 1 token.snap +++ b/.forge-snapshots/donate gas with 1 token.snap @@ -1 +1 @@ -106309 \ No newline at end of file +106333 \ 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 c6de840fc..a491bae33 100644 --- a/.forge-snapshots/donate gas with 2 tokens.snap +++ b/.forge-snapshots/donate gas with 2 tokens.snap @@ -1 +1 @@ -145724 \ No newline at end of file +145748 \ No newline at end of file diff --git a/.forge-snapshots/erc20 collect protocol fees.snap b/.forge-snapshots/erc20 collect protocol fees.snap index 2a8ab2b2d..91a7b5c6f 100644 --- a/.forge-snapshots/erc20 collect protocol fees.snap +++ b/.forge-snapshots/erc20 collect protocol fees.snap @@ -1 +1 @@ -57439 \ No newline at end of file +57451 \ No newline at end of file diff --git a/.forge-snapshots/initialize.snap b/.forge-snapshots/initialize.snap index 9599bb1c0..bf8722821 100644 --- a/.forge-snapshots/initialize.snap +++ b/.forge-snapshots/initialize.snap @@ -1 +1 @@ -60009 \ No newline at end of file +51533 \ No newline at end of file diff --git a/.forge-snapshots/poolManager bytecode size.snap b/.forge-snapshots/poolManager bytecode size.snap index e0083410f..27c79889b 100644 --- a/.forge-snapshots/poolManager bytecode size.snap +++ b/.forge-snapshots/poolManager bytecode size.snap @@ -1 +1 @@ -24140 \ No newline at end of file +23688 \ No newline at end of file diff --git a/.forge-snapshots/removeLiquidity CA fee.snap b/.forge-snapshots/removeLiquidity CA fee.snap index c93d8da18..f58102b65 100644 --- a/.forge-snapshots/removeLiquidity CA fee.snap +++ b/.forge-snapshots/removeLiquidity CA fee.snap @@ -1 +1 @@ -141192 \ No newline at end of file +141194 \ 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 5fed9375b..bac1084ca 100644 --- a/.forge-snapshots/removeLiquidity with empty hook.snap +++ b/.forge-snapshots/removeLiquidity with empty hook.snap @@ -1 +1 @@ -130567 \ No newline at end of file +130603 \ 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 4f897d062..19f882d70 100644 --- a/.forge-snapshots/removeLiquidity with native token.snap +++ b/.forge-snapshots/removeLiquidity with native token.snap @@ -1 +1 @@ -112513 \ No newline at end of file +112523 \ No newline at end of file diff --git a/.forge-snapshots/simple addLiquidity second addition same range.snap b/.forge-snapshots/simple addLiquidity second addition same range.snap index 098d9352b..d3a590e01 100644 --- a/.forge-snapshots/simple addLiquidity second addition same range.snap +++ b/.forge-snapshots/simple addLiquidity second addition same range.snap @@ -1 +1 @@ -98826 \ No newline at end of file +98850 \ No newline at end of file diff --git a/.forge-snapshots/simple addLiquidity.snap b/.forge-snapshots/simple addLiquidity.snap index 3f91cc8f1..216625993 100644 --- a/.forge-snapshots/simple addLiquidity.snap +++ b/.forge-snapshots/simple addLiquidity.snap @@ -1 +1 @@ -161371 \ No newline at end of file +161395 \ No newline at end of file diff --git a/.forge-snapshots/simple removeLiquidity some liquidity remains.snap b/.forge-snapshots/simple removeLiquidity some liquidity remains.snap index e68338618..c8020f5a6 100644 --- a/.forge-snapshots/simple removeLiquidity some liquidity remains.snap +++ b/.forge-snapshots/simple removeLiquidity some liquidity remains.snap @@ -1 +1 @@ -92962 \ No newline at end of file +92986 \ No newline at end of file diff --git a/.forge-snapshots/simple removeLiquidity.snap b/.forge-snapshots/simple removeLiquidity.snap index 38214f3d2..85b1f5818 100644 --- a/.forge-snapshots/simple removeLiquidity.snap +++ b/.forge-snapshots/simple removeLiquidity.snap @@ -1 +1 @@ -85075 \ No newline at end of file +85099 \ 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 dd35d28f8..3a563cd16 100644 --- a/.forge-snapshots/simple swap with native.snap +++ b/.forge-snapshots/simple swap with native.snap @@ -1 +1 @@ -108422 \ No newline at end of file +108434 \ No newline at end of file diff --git a/.forge-snapshots/simple swap.snap b/.forge-snapshots/simple swap.snap index 1e8829cfc..fcab2fe6a 100644 --- a/.forge-snapshots/simple swap.snap +++ b/.forge-snapshots/simple swap.snap @@ -1 +1 @@ -123239 \ No newline at end of file +123263 \ No newline at end of file diff --git a/.forge-snapshots/swap CA custom curve + swap noop.snap b/.forge-snapshots/swap CA custom curve + swap noop.snap index 4ee133a95..401a560a7 100644 --- a/.forge-snapshots/swap CA custom curve + swap noop.snap +++ b/.forge-snapshots/swap CA custom curve + swap noop.snap @@ -1 +1 @@ -124633 \ No newline at end of file +124635 \ No newline at end of file diff --git a/.forge-snapshots/swap CA fee on unspecified.snap b/.forge-snapshots/swap CA fee on unspecified.snap index 5a90659c9..13dcef08d 100644 --- a/.forge-snapshots/swap CA fee on unspecified.snap +++ b/.forge-snapshots/swap CA fee on unspecified.snap @@ -1 +1 @@ -154684 \ No newline at end of file +154686 \ 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 c8ce4751f..bb452f916 100644 --- a/.forge-snapshots/swap against liquidity with native token.snap +++ b/.forge-snapshots/swap against liquidity with native token.snap @@ -1 +1 @@ -105557 \ No newline at end of file +105569 \ No newline at end of file diff --git a/.forge-snapshots/swap against liquidity.snap b/.forge-snapshots/swap against liquidity.snap index afeb30892..70783815d 100644 --- a/.forge-snapshots/swap against liquidity.snap +++ b/.forge-snapshots/swap against liquidity.snap @@ -1 +1 @@ -116622 \ No newline at end of file +116646 \ 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 e42f2a6db..0be5b3104 100644 --- a/.forge-snapshots/swap burn 6909 for input.snap +++ b/.forge-snapshots/swap burn 6909 for input.snap @@ -1 +1 @@ -129261 \ No newline at end of file +129285 \ 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 4e4ef13df..6b81ca8c9 100644 --- a/.forge-snapshots/swap burn native 6909 for input.snap +++ b/.forge-snapshots/swap burn native 6909 for input.snap @@ -1 +1 @@ -118660 \ No newline at end of file +118672 \ 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 a3d026bae..d1c41e163 100644 --- a/.forge-snapshots/swap mint native output as 6909.snap +++ b/.forge-snapshots/swap mint native output as 6909.snap @@ -1 +1 @@ -139727 \ No newline at end of file +139739 \ 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 7b0c1ad3d..b5ec0883d 100644 --- a/.forge-snapshots/swap mint output as 6909.snap +++ b/.forge-snapshots/swap mint output as 6909.snap @@ -1 +1 @@ -155080 \ No newline at end of file +155104 \ No newline at end of file diff --git a/.forge-snapshots/swap skips hook call if hook is caller.snap b/.forge-snapshots/swap skips hook call if hook is caller.snap index ef1abd51b..403b7eb63 100644 --- a/.forge-snapshots/swap skips hook call if hook is caller.snap +++ b/.forge-snapshots/swap skips hook call if hook is caller.snap @@ -1 +1 @@ -206285 \ No newline at end of file +206251 \ No newline at end of file diff --git a/.forge-snapshots/swap with hooks.snap b/.forge-snapshots/swap with hooks.snap index 9fb8d971d..e215016a8 100644 --- a/.forge-snapshots/swap with hooks.snap +++ b/.forge-snapshots/swap with hooks.snap @@ -1 +1 @@ -132260 \ No newline at end of file +132274 \ No newline at end of file diff --git a/.forge-snapshots/swap with lp fee and protocol fee.snap b/.forge-snapshots/swap with lp fee and protocol fee.snap deleted file mode 100644 index 8bf4f1a5f..000000000 --- a/.forge-snapshots/swap with lp fee and protocol fee.snap +++ /dev/null @@ -1 +0,0 @@ -169603 \ No newline at end of file diff --git a/.forge-snapshots/swap with return dynamic fee.snap b/.forge-snapshots/swap with return dynamic fee.snap index 59f45046e..fd902a4a0 100644 --- a/.forge-snapshots/swap with return dynamic fee.snap +++ b/.forge-snapshots/swap with return dynamic fee.snap @@ -1 +1 @@ -145611 \ No newline at end of file +145577 \ 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 bb377db1b..2bf5b6d0e 100644 --- a/.forge-snapshots/update dynamic fee in before swap.snap +++ b/.forge-snapshots/update dynamic fee in before swap.snap @@ -1 +1 @@ -147891 \ No newline at end of file +147869 \ No newline at end of file diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..f03633465 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @uniswap/protocols diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml deleted file mode 100644 index 01113933e..000000000 --- a/.github/workflows/coverage.yml +++ /dev/null @@ -1,89 +0,0 @@ -name: code coverage - -on: - pull_request: - branches: - - main - -jobs: - comment-forge-coverage: - runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: write - - steps: - - name: Checkout code - uses: actions/checkout@v3 - with: - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install foundry - uses: foundry-rs/foundry-toolchain@v1 - with: - version: nightly - - name: Run Forge build - run: | - forge --version - forge build --sizes --via-ir - id: build - - name: Run forge coverage - id: coverage - run: | - { - echo 'COVERAGE<> "$GITHUB_OUTPUT" - env: - FOUNDRY_RPC_URL: "${{ secrets.RPC_URL }}" - - - name: Check coverage is updated - uses: actions/github-script@v5 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const fs = require('fs'); - const file = "coverage.txt" - if(!fs.existsSync(file)) { - console.log("Nothing to check"); - return - } - const currentCoverage = fs.readFileSync(file, "utf8").trim(); - const newCoverage = (`${{ steps.coverage.outputs.COVERAGE }}`).trim(); - if (newCoverage != currentCoverage) { - core.setFailed(`Code coverage not updated. Run : forge coverage | grep '^|' | grep -v 'test/' > coverage.txt`); - } - - - name: Comment on PR - id: comment - uses: actions/github-script@v5 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const {data: comments} = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - }) - - const botComment = comments.find(comment => comment.user.id === 41898282) - - const output = `${{ steps.coverage.outputs.COVERAGE }}`; - const commentBody = `Forge code coverage:\n${output}\n`; - - if (botComment) { - github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: botComment.id, - body: commentBody - }) - } else { - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: commentBody - }); - } diff --git a/README.md b/README.md index 78788f033..53abf7601 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ If you’re interested in contributing please see our [contribution guidelines]( ## Whitepaper -A more detailed description of Uniswap v4 Core can be found in the draft of the [Uniswap v4 Core Whitepaper](./docs/whitepaper-v4.pdf). +A more detailed description of Uniswap v4 Core can be found in the draft of the [Uniswap v4 Core Whitepaper](./docs/whitepaper/whitepaper-v4.pdf). ## Architecture diff --git a/src/PoolManager.sol b/src/PoolManager.sol index f366d33aa..92b8148ad 100644 --- a/src/PoolManager.sol +++ b/src/PoolManager.sol @@ -112,11 +112,7 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim } /// @inheritdoc IPoolManager - function initialize(PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData) - external - noDelegateCall - returns (int24 tick) - { + function initialize(PoolKey memory key, uint160 sqrtPriceX96) external noDelegateCall returns (int24 tick) { // see TickBitmap.sol for overflow conditions that can arise from tick spacing being too large if (key.tickSpacing > MAX_TICK_SPACING) TickSpacingTooLarge.selector.revertWith(key.tickSpacing); if (key.tickSpacing < MIN_TICK_SPACING) TickSpacingTooSmall.selector.revertWith(key.tickSpacing); @@ -129,14 +125,13 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim uint24 lpFee = key.fee.getInitialLPFee(); - key.hooks.beforeInitialize(key, sqrtPriceX96, hookData); + key.hooks.beforeInitialize(key, sqrtPriceX96); PoolId id = key.toId(); - uint24 protocolFee = _fetchProtocolFee(key); - tick = _pools[id].initialize(sqrtPriceX96, protocolFee, lpFee); + tick = _pools[id].initialize(sqrtPriceX96, lpFee); - key.hooks.afterInitialize(key, sqrtPriceX96, tick, hookData); + key.hooks.afterInitialize(key, sqrtPriceX96, tick); // emit all details of a pool key. poolkeys are not saved in storage and must always be provided by the caller // the key's fee may be a static fee or a sentinel to denote a dynamic fee. @@ -178,7 +173,7 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim BalanceDelta hookDelta; (callerDelta, hookDelta) = key.hooks.afterModifyLiquidity(key, params, callerDelta, feesAccrued, hookData); - // if the hook doesnt have the flag to be able to return deltas, hookDelta will always be 0 + // if the hook doesn't have the flag to be able to return deltas, hookDelta will always be 0 if (hookDelta != BalanceDeltaLibrary.ZERO_DELTA) _accountPoolBalanceDelta(key, hookDelta, address(key.hooks)); _accountPoolBalanceDelta(key, callerDelta, msg.sender); @@ -221,7 +216,7 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim BalanceDelta hookDelta; (swapDelta, hookDelta) = key.hooks.afterSwap(key, params, swapDelta, hookData, beforeSwapDelta); - // if the hook doesnt have the flag to be able to return deltas, hookDelta will always be 0 + // if the hook doesn't have the flag to be able to return deltas, hookDelta will always be 0 if (hookDelta != BalanceDeltaLibrary.ZERO_DELTA) _accountPoolBalanceDelta(key, hookDelta, address(key.hooks)); _accountPoolBalanceDelta(key, swapDelta, msg.sender); diff --git a/src/ProtocolFees.sol b/src/ProtocolFees.sol index f89566872..ecea47484 100644 --- a/src/ProtocolFees.sol +++ b/src/ProtocolFees.sol @@ -6,7 +6,6 @@ import {IProtocolFeeController} from "./interfaces/IProtocolFeeController.sol"; import {IProtocolFees} from "./interfaces/IProtocolFees.sol"; import {PoolKey} from "./types/PoolKey.sol"; import {ProtocolFeeLibrary} from "./libraries/ProtocolFeeLibrary.sol"; -import {BipsLibrary} from "./libraries/BipsLibrary.sol"; import {Owned} from "solmate/src/auth/Owned.sol"; import {PoolId} from "./types/PoolId.sol"; import {Pool} from "./libraries/Pool.sol"; @@ -17,7 +16,6 @@ abstract contract ProtocolFees is IProtocolFees, Owned { using ProtocolFeeLibrary for uint24; using Pool for Pool.State; using CustomRevert for bytes4; - using BipsLibrary for uint256; /// @inheritdoc IProtocolFees mapping(Currency currency => uint256 amount) public protocolFeesAccrued; @@ -25,10 +23,6 @@ abstract contract ProtocolFees is IProtocolFees, Owned { /// @inheritdoc IProtocolFees IProtocolFeeController public protocolFeeController; - // a percentage of the block.gaslimit denoted in basis points, used as the gas limit for fee controller calls - // 100 bps is 1%, at 30M gas, the limit is 300K - uint256 private constant BLOCK_LIMIT_BPS = 100; - constructor() Owned(msg.sender) {} /// @inheritdoc IProtocolFees @@ -66,42 +60,6 @@ abstract contract ProtocolFees is IProtocolFees, Owned { /// @dev this is overridden in PoolManager.sol to give access to the _pools mapping function _getPool(PoolId id) internal virtual returns (Pool.State storage); - /// @notice Fetch the protocol fees for a given pool - /// @dev the success of this function is false if the call fails or the returned fees are invalid - /// @dev to prevent an invalid protocol fee controller from blocking pools from being initialized - /// the success of this function is NOT checked on initialize and if the call fails, the protocol fees are set to 0. - function _fetchProtocolFee(PoolKey memory key) internal returns (uint24 protocolFee) { - if (address(protocolFeeController) != address(0)) { - uint256 controllerGasLimit = block.gaslimit.calculatePortion(BLOCK_LIMIT_BPS); - - // note that EIP-150 mandates that calls requesting more than 63/64ths of remaining gas - // will be allotted no more than this amount, so controllerGasLimit must be set with this - // in mind. - if (gasleft() < controllerGasLimit) ProtocolFeeCannotBeFetched.selector.revertWith(); - - address toAddress = address(protocolFeeController); - - bytes memory data = abi.encodeCall(IProtocolFeeController.protocolFeeForPool, (key)); - - bool success; - uint256 returnData; - assembly ("memory-safe") { - // only load the first 32 bytes of the return data to prevent gas griefing - success := call(controllerGasLimit, toAddress, 0, add(data, 0x20), mload(data), 0, 32) - // if success is false this wont actually be returned, instead 0 will be returned - returnData := mload(0) - - // success if return data size is 32 bytes - success := and(success, eq(returndatasize(), 32)) - } - - // Ensure return data does not overflow a uint24 and that the underlying fees are within bounds. - protocolFee = success && (returnData == uint24(returnData)) && uint24(returnData).isValidProtocolFee() - ? uint24(returnData) - : 0; - } - } - function _updateProtocolFees(Currency currency, uint256 amount) internal { unchecked { protocolFeesAccrued[currency] += amount; diff --git a/src/interfaces/IHooks.sol b/src/interfaces/IHooks.sol index e0d4a1f4e..a541e2681 100644 --- a/src/interfaces/IHooks.sol +++ b/src/interfaces/IHooks.sol @@ -17,26 +17,18 @@ interface IHooks { /// @param sender The initial msg.sender for the initialize call /// @param key The key for the pool being initialized /// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96 - /// @param hookData Arbitrary data handed into the PoolManager by the initializer to be be passed on to the hook /// @return bytes4 The function selector for the hook - function beforeInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96, bytes calldata hookData) - external - returns (bytes4); + function beforeInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96) external returns (bytes4); /// @notice The hook called after the state of a pool is initialized /// @param sender The initial msg.sender for the initialize call /// @param key The key for the pool being initialized /// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96 /// @param tick The current tick after the state of a pool is initialized - /// @param hookData Arbitrary data handed into the PoolManager by the initializer to be be passed on to the hook /// @return bytes4 The function selector for the hook - function afterInitialize( - address sender, - PoolKey calldata key, - uint160 sqrtPriceX96, - int24 tick, - bytes calldata hookData - ) external returns (bytes4); + function afterInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96, int24 tick) + external + returns (bytes4); /// @notice The hook called before liquidity is added /// @param sender The initial msg.sender for the add liquidity call diff --git a/src/interfaces/IPoolManager.sol b/src/interfaces/IPoolManager.sol index dc5b60b49..3269851d0 100644 --- a/src/interfaces/IPoolManager.sol +++ b/src/interfaces/IPoolManager.sol @@ -116,11 +116,8 @@ interface IPoolManager is IProtocolFees, IERC6909Claims, IExtsload, IExttload { /// @dev A swap fee totaling MAX_SWAP_FEE (100%) makes exact output swaps impossible since the input is entirely consumed by the fee /// @param key The pool key for the pool to initialize /// @param sqrtPriceX96 The initial square root price - /// @param hookData The data to pass through to the initialize hooks /// @return tick The initial tick of the pool - function initialize(PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData) - external - returns (int24 tick); + function initialize(PoolKey memory key, uint160 sqrtPriceX96) external returns (int24 tick); struct ModifyLiquidityParams { // the lower and upper tick of the position diff --git a/src/interfaces/IProtocolFees.sol b/src/interfaces/IProtocolFees.sol index cfbf82154..0717bfc88 100644 --- a/src/interfaces/IProtocolFees.sol +++ b/src/interfaces/IProtocolFees.sol @@ -8,10 +8,9 @@ import {PoolKey} from "../types/PoolKey.sol"; /// @notice Interface for all protocol-fee related functions in the pool manager interface IProtocolFees { - /// @notice Thrown when not enough gas is provided to look up the protocol fee - error ProtocolFeeCannotBeFetched(); /// @notice Thrown when protocol fee is set too high error ProtocolFeeTooLarge(uint24 fee); + /// @notice Thrown when the contract is unlocked error ContractUnlocked(); diff --git a/src/libraries/BipsLibrary.sol b/src/libraries/BipsLibrary.sol deleted file mode 100644 index 219232e25..000000000 --- a/src/libraries/BipsLibrary.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -/// @title For calculating a percentage of an amount, using bips -library BipsLibrary { - uint256 internal constant BPS_DENOMINATOR = 10_000; - - /// @notice emitted when an invalid percentage is provided - error InvalidBips(); - - /// @param amount The total amount to calculate a percentage of - /// @param bips The percentage to calculate, in bips - function calculatePortion(uint256 amount, uint256 bips) internal pure returns (uint256) { - if (bips > BPS_DENOMINATOR) revert InvalidBips(); - return (amount * bips) / BPS_DENOMINATOR; - } -} diff --git a/src/libraries/Hooks.sol b/src/libraries/Hooks.sol index 28036e4f0..2f02548f5 100644 --- a/src/libraries/Hooks.sol +++ b/src/libraries/Hooks.sol @@ -126,7 +126,7 @@ library Hooks { : (uint160(address(self)) & ALL_HOOK_MASK > 0 || fee.isDynamicFee()); } - /// @notice performs a hook call using the given calldata on the given hook that doesnt return a delta + /// @notice performs a hook call using the given calldata on the given hook that doesn't return a delta /// @return result The complete data returned by the hook function callHook(IHooks self, bytes memory data) internal returns (bytes memory result) { bool success; @@ -175,22 +175,19 @@ library Hooks { } /// @notice calls beforeInitialize hook if permissioned and validates return value - function beforeInitialize(IHooks self, PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData) - internal - noSelfCall(self) - { + function beforeInitialize(IHooks self, PoolKey memory key, uint160 sqrtPriceX96) internal noSelfCall(self) { if (self.hasPermission(BEFORE_INITIALIZE_FLAG)) { - self.callHook(abi.encodeCall(IHooks.beforeInitialize, (msg.sender, key, sqrtPriceX96, hookData))); + self.callHook(abi.encodeCall(IHooks.beforeInitialize, (msg.sender, key, sqrtPriceX96))); } } /// @notice calls afterInitialize hook if permissioned and validates return value - function afterInitialize(IHooks self, PoolKey memory key, uint160 sqrtPriceX96, int24 tick, bytes calldata hookData) + function afterInitialize(IHooks self, PoolKey memory key, uint160 sqrtPriceX96, int24 tick) internal noSelfCall(self) { if (self.hasPermission(AFTER_INITIALIZE_FLAG)) { - self.callHook(abi.encodeCall(IHooks.afterInitialize, (msg.sender, key, sqrtPriceX96, tick, hookData))); + self.callHook(abi.encodeCall(IHooks.afterInitialize, (msg.sender, key, sqrtPriceX96, tick))); } } @@ -271,7 +268,7 @@ library Hooks { // any return in unspecified is passed to the afterSwap hook for handling int128 hookDeltaSpecified = hookReturn.getSpecifiedDelta(); - // Update the swap amount according to the hook's return, and check that the swap type doesnt change (exact input/output) + // Update the swap amount according to the hook's return, and check that the swap type doesn't change (exact input/output) if (hookDeltaSpecified != 0) { bool exactInput = amountToSwap < 0; amountToSwap += hookDeltaSpecified; diff --git a/src/libraries/Pool.sol b/src/libraries/Pool.sol index e843e2115..fa871d2aa 100644 --- a/src/libraries/Pool.sol +++ b/src/libraries/Pool.sol @@ -94,16 +94,13 @@ library Pool { if (tickUpper > TickMath.MAX_TICK) TickUpperOutOfBounds.selector.revertWith(tickUpper); } - function initialize(State storage self, uint160 sqrtPriceX96, uint24 protocolFee, uint24 lpFee) - internal - returns (int24 tick) - { + function initialize(State storage self, uint160 sqrtPriceX96, uint24 lpFee) internal returns (int24 tick) { if (self.slot0.sqrtPriceX96() != 0) PoolAlreadyInitialized.selector.revertWith(); tick = TickMath.getTickAtSqrtPrice(sqrtPriceX96); - self.slot0 = Slot0.wrap(bytes32(0)).setSqrtPriceX96(sqrtPriceX96).setTick(tick).setProtocolFee(protocolFee) - .setLpFee(lpFee); + // the initial protocolFee is 0 so doesn't need to be set + self.slot0 = Slot0.wrap(bytes32(0)).setSqrtPriceX96(sqrtPriceX96).setTick(tick).setLpFee(lpFee); } function setProtocolFee(State storage self, uint24 protocolFee) internal { @@ -411,7 +408,7 @@ library Pool { } // Shift tick if we reached the next price, and preemptively decrement for zeroForOne swaps to tickNext - 1. - // If the swap doesnt continue (if amountRemaining == 0 or sqrtPriceLimit is met), slot0.tick will be 1 less + // If the swap doesn't continue (if amountRemaining == 0 or sqrtPriceLimit is met), slot0.tick will be 1 less // than getTickAtSqrtPrice(slot0.sqrtPrice). This doesn't affect swaps, but donation calls should verify both // price and tick to reward the correct LPs. if (result.sqrtPriceX96 == step.sqrtPriceNextX96) { diff --git a/src/test/BaseTestHooks.sol b/src/test/BaseTestHooks.sol index f4d673f06..83c9f9af9 100644 --- a/src/test/BaseTestHooks.sol +++ b/src/test/BaseTestHooks.sol @@ -10,12 +10,11 @@ import {IPoolManager} from "../interfaces/IPoolManager.sol"; contract BaseTestHooks is IHooks { error HookNotImplemented(); - function beforeInitialize( - address, /* sender **/ - PoolKey calldata, /* key **/ - uint160, /* sqrtPriceX96 **/ - bytes calldata /* hookData **/ - ) external virtual returns (bytes4) { + function beforeInitialize(address, /* sender **/ PoolKey calldata, /* key **/ uint160 /* sqrtPriceX96 **/ ) + external + virtual + returns (bytes4) + { revert HookNotImplemented(); } @@ -23,8 +22,7 @@ contract BaseTestHooks is IHooks { address, /* sender **/ PoolKey calldata, /* key **/ uint160, /* sqrtPriceX96 **/ - int24, /* tick **/ - bytes calldata /* hookData **/ + int24 /* tick **/ ) external virtual returns (bytes4) { revert HookNotImplemented(); } diff --git a/src/test/DynamicFeesTestHook.sol b/src/test/DynamicFeesTestHook.sol index 7d6aa0e5a..8b546d09a 100644 --- a/src/test/DynamicFeesTestHook.sol +++ b/src/test/DynamicFeesTestHook.sol @@ -19,11 +19,7 @@ contract DynamicFeesTestHook is BaseTestHooks { fee = _fee; } - function afterInitialize(address, PoolKey calldata key, uint160, int24, bytes calldata) - external - override - returns (bytes4) - { + function afterInitialize(address, PoolKey calldata key, uint160, int24) external override returns (bytes4) { manager.updateDynamicLPFee(key, fee); return IHooks.afterInitialize.selector; } diff --git a/src/test/EmptyTestHooks.sol b/src/test/EmptyTestHooks.sol index 51f28c12c..43544cf90 100644 --- a/src/test/EmptyTestHooks.sol +++ b/src/test/EmptyTestHooks.sol @@ -32,21 +32,11 @@ contract EmptyTestHooks is IHooks { ); } - function beforeInitialize(address, PoolKey calldata, uint160, bytes calldata) - external - pure - override - returns (bytes4) - { + function beforeInitialize(address, PoolKey calldata, uint160) external pure override returns (bytes4) { return IHooks.beforeInitialize.selector; } - function afterInitialize(address, PoolKey calldata, uint160, int24, bytes calldata) - external - pure - override - returns (bytes4) - { + function afterInitialize(address, PoolKey calldata, uint160, int24) external pure override returns (bytes4) { return IHooks.afterInitialize.selector; } diff --git a/src/test/MockHooks.sol b/src/test/MockHooks.sol index 08ef4e79e..8299ddfc8 100644 --- a/src/test/MockHooks.sol +++ b/src/test/MockHooks.sol @@ -27,22 +27,14 @@ contract MockHooks is IHooks { mapping(PoolId => uint16) public lpFees; - function beforeInitialize(address, PoolKey calldata, uint160, bytes calldata hookData) - external - override - returns (bytes4) - { - beforeInitializeData = hookData; + function beforeInitialize(address, PoolKey calldata, uint160) external override returns (bytes4) { + beforeInitializeData = new bytes(123); bytes4 selector = MockHooks.beforeInitialize.selector; return returnValues[selector] == bytes4(0) ? selector : returnValues[selector]; } - function afterInitialize(address, PoolKey calldata, uint160, int24, bytes calldata hookData) - external - override - returns (bytes4) - { - afterInitializeData = hookData; + function afterInitialize(address, PoolKey calldata, uint160, int24) external override returns (bytes4) { + afterInitializeData = new bytes(123); bytes4 selector = MockHooks.afterInitialize.selector; return returnValues[selector] == bytes4(0) ? selector : returnValues[selector]; } diff --git a/src/test/PoolNestedActionsTest.sol b/src/test/PoolNestedActionsTest.sol index 11f8996bf..044ca0b71 100644 --- a/src/test/PoolNestedActionsTest.sol +++ b/src/test/PoolNestedActionsTest.sol @@ -223,7 +223,7 @@ contract NestedActionExecutor is Test, PoolTestBase { PoolId id = key.toId(); (uint256 price,,,) = manager.getSlot0(id); assertEq(price, 0); - manager.initialize(key, Constants.SQRT_PRICE_1_2, Constants.ZERO_BYTES); + manager.initialize(key, Constants.SQRT_PRICE_1_2); (price,,,) = manager.getSlot0(id); assertEq(price, Constants.SQRT_PRICE_1_2); } diff --git a/src/test/ProtocolFeeControllerTest.sol b/src/test/ProtocolFeeControllerTest.sol index dba8dd9cb..25fc0795d 100644 --- a/src/test/ProtocolFeeControllerTest.sol +++ b/src/test/ProtocolFeeControllerTest.sol @@ -17,42 +17,3 @@ contract ProtocolFeeControllerTest is IProtocolFeeController { protocolFee[id] = fee; } } - -/// @notice Reverts on call -contract RevertingProtocolFeeControllerTest is IProtocolFeeController { - function protocolFeeForPool(PoolKey memory /* key */ ) external pure returns (uint24) { - revert(); - } -} - -/// @notice Returns an out of bounds protocol fee -contract OutOfBoundsProtocolFeeControllerTest is IProtocolFeeController { - function protocolFeeForPool(PoolKey memory /* key */ ) external pure returns (uint24) { - // set both protocol fees to 1001, which is greater than MAX_PROTOCOL_FEE - return (1001 << 12) | 1001; - } -} - -/// @notice Return a value that overflows a uint24 -contract OverflowProtocolFeeControllerTest is IProtocolFeeController { - function protocolFeeForPool(PoolKey memory /* key */ ) external pure returns (uint24) { - assembly { - let ptr := mload(0x40) - mstore(ptr, 0xFFFFAAA001) - return(ptr, 0x20) - } - } -} - -/// @notice Returns data that is larger than a word -contract InvalidReturnSizeProtocolFeeControllerTest is IProtocolFeeController { - function protocolFeeForPool(PoolKey memory /* key */ ) external pure returns (uint24) { - address a = address(1); - assembly { - let ptr := mload(0x40) - mstore(ptr, a) - mstore(add(ptr, 0x20), a) - return(ptr, 0x40) - } - } -} diff --git a/src/test/ProtocolFeesImplementation.sol b/src/test/ProtocolFeesImplementation.sol index 30008e7dc..f485e26e1 100644 --- a/src/test/ProtocolFeesImplementation.sol +++ b/src/test/ProtocolFeesImplementation.sol @@ -30,10 +30,6 @@ contract ProtocolFeesImplementation is ProtocolFees { return isUnlocked; } - function fetchProtocolFee(PoolKey memory key) public returns (uint24) { - return ProtocolFees._fetchProtocolFee(key); - } - function updateProtocolFees(Currency currency, uint256 amount) public { ProtocolFees._updateProtocolFees(currency, amount); } diff --git a/src/test/ProxyPoolManager.sol b/src/test/ProxyPoolManager.sol index b82bf8428..a8a4415df 100644 --- a/src/test/ProxyPoolManager.sol +++ b/src/test/ProxyPoolManager.sol @@ -68,11 +68,7 @@ contract ProxyPoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909 } /// @inheritdoc IPoolManager - function initialize(PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData) - external - noDelegateCall - returns (int24 tick) - { + function initialize(PoolKey memory key, uint160 sqrtPriceX96) external noDelegateCall returns (int24 tick) { // see TickBitmap.sol for overflow conditions that can arise from tick spacing being too large if (key.tickSpacing > MAX_TICK_SPACING) TickSpacingTooLarge.selector.revertWith(key.tickSpacing); if (key.tickSpacing < MIN_TICK_SPACING) TickSpacingTooSmall.selector.revertWith(key.tickSpacing); @@ -85,14 +81,13 @@ contract ProxyPoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909 uint24 lpFee = key.fee.getInitialLPFee(); - key.hooks.beforeInitialize(key, sqrtPriceX96, hookData); + key.hooks.beforeInitialize(key, sqrtPriceX96); PoolId id = key.toId(); - uint24 protocolFee = _fetchProtocolFee(key); - tick = _pools[id].initialize(sqrtPriceX96, protocolFee, lpFee); + tick = _pools[id].initialize(sqrtPriceX96, lpFee); - key.hooks.afterInitialize(key, sqrtPriceX96, tick, hookData); + key.hooks.afterInitialize(key, sqrtPriceX96, tick); // emit all details of a pool key. poolkeys are not saved in storage and must always be provided by the caller // the key's fee may be a static fee or a sentinel to denote a dynamic fee. diff --git a/src/test/SkipCallsTestHook.sol b/src/test/SkipCallsTestHook.sol index 341709fc4..d6021bdf9 100644 --- a/src/test/SkipCallsTestHook.sol +++ b/src/test/SkipCallsTestHook.sol @@ -27,23 +27,19 @@ contract SkipCallsTestHook is BaseTestHooks, Test { manager = _manager; } - function beforeInitialize(address, PoolKey calldata key, uint160 sqrtPriceX96, bytes calldata hookData) - external - override - returns (bytes4) - { + function beforeInitialize(address, PoolKey calldata key, uint160 sqrtPriceX96) external override returns (bytes4) { counter++; - _initialize(key, sqrtPriceX96, hookData); + _initialize(key, sqrtPriceX96); return IHooks.beforeInitialize.selector; } - function afterInitialize(address, PoolKey calldata key, uint160 sqrtPriceX96, int24, bytes calldata hookData) + function afterInitialize(address, PoolKey calldata key, uint160 sqrtPriceX96, int24) external override returns (bytes4) { counter++; - _initialize(key, sqrtPriceX96, hookData); + _initialize(key, sqrtPriceX96); return IHooks.afterInitialize.selector; } @@ -137,10 +133,10 @@ contract SkipCallsTestHook is BaseTestHooks, Test { return IHooks.afterDonate.selector; } - function _initialize(PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData) public { + function _initialize(PoolKey memory key, uint160 sqrtPriceX96) public { // initialize a new pool with different fee key.fee = 2000; - IPoolManager(manager).initialize(key, sqrtPriceX96, hookData); + IPoolManager(manager).initialize(key, sqrtPriceX96); } function _swap(PoolKey calldata key, IPoolManager.SwapParams memory params, bytes calldata hookData) public { diff --git a/test/CustomAccounting.t.sol b/test/CustomAccounting.t.sol index 6cb3d0bb9..e4942dce3 100644 --- a/test/CustomAccounting.t.sol +++ b/test/CustomAccounting.t.sol @@ -65,7 +65,7 @@ contract CustomAccountingTest is Test, Deployers, GasSnapshot { vm.etch(hookAddr, implAddr.code); hook = hookAddr; - (key,) = initPoolAndAddLiquidity(currency0, currency1, IHooks(hookAddr), 100, SQRT_PRICE_1_1, ZERO_BYTES); + (key,) = initPoolAndAddLiquidity(currency0, currency1, IHooks(hookAddr), 100, SQRT_PRICE_1_1); } // ------------------------ SWAP ------------------------ diff --git a/test/DynamicFees.t.sol b/test/DynamicFees.t.sol index 1753769dd..d16a3ec0e 100644 --- a/test/DynamicFees.t.sol +++ b/test/DynamicFees.t.sol @@ -62,12 +62,7 @@ contract TestDynamicFees is Test, Deployers, GasSnapshot { deployMintAndApprove2Currencies(); (key,) = initPoolAndAddLiquidity( - currency0, - currency1, - IHooks(address(dynamicFeesHooks)), - LPFeeLibrary.DYNAMIC_FEE_FLAG, - SQRT_PRICE_1_1, - ZERO_BYTES + currency0, currency1, IHooks(address(dynamicFeesHooks)), LPFeeLibrary.DYNAMIC_FEE_FLAG, SQRT_PRICE_1_1 ); } @@ -83,7 +78,7 @@ contract TestDynamicFees is Test, Deployers, GasSnapshot { abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, fee) ) ); - manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); + manager.initialize(key, SQRT_PRICE_1_1); } function test_initialize_initializesFeeTo0() public { @@ -92,7 +87,7 @@ contract TestDynamicFees is Test, Deployers, GasSnapshot { // this fee is not fetched as theres no afterInitialize hook dynamicFeesNoHooks.setFee(1000000); - manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); + manager.initialize(key, SQRT_PRICE_1_1); assertEq(_fetchPoolLPFee(key), 0); } @@ -100,7 +95,7 @@ contract TestDynamicFees is Test, Deployers, GasSnapshot { key.tickSpacing = 30; dynamicFeesHooks.setFee(123); - manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); + manager.initialize(key, SQRT_PRICE_1_1); assertEq(_fetchPoolLPFee(key), 123); } @@ -121,7 +116,7 @@ contract TestDynamicFees is Test, Deployers, GasSnapshot { abi.encodeWithSelector(IPoolManager.UnauthorizedDynamicLPFeeUpdate.selector) ) ); - manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); + manager.initialize(key, SQRT_PRICE_1_1); } function test_updateDynamicLPFee_beforeSwap_failsWithTooLargeFee() public { @@ -329,7 +324,7 @@ contract TestDynamicFees is Test, Deployers, GasSnapshot { function test_swap_withDynamicFee_gas() public { (key,) = initPoolAndAddLiquidity( - currency0, currency1, dynamicFeesNoHooks, LPFeeLibrary.DYNAMIC_FEE_FLAG, SQRT_PRICE_1_1, ZERO_BYTES + currency0, currency1, dynamicFeesNoHooks, LPFeeLibrary.DYNAMIC_FEE_FLAG, SQRT_PRICE_1_1 ); assertEq(_fetchPoolLPFee(key), 0); diff --git a/test/DynamicReturnFees.t.sol b/test/DynamicReturnFees.t.sol index 768d53c8b..4975e804d 100644 --- a/test/DynamicReturnFees.t.sol +++ b/test/DynamicReturnFees.t.sol @@ -49,12 +49,7 @@ contract TestDynamicReturnFees is Test, Deployers, GasSnapshot { deployMintAndApprove2Currencies(); (key,) = initPoolAndAddLiquidity( - currency0, - currency1, - IHooks(address(dynamicReturnFeesHook)), - LPFeeLibrary.DYNAMIC_FEE_FLAG, - SQRT_PRICE_1_1, - ZERO_BYTES + currency0, currency1, IHooks(address(dynamicReturnFeesHook)), LPFeeLibrary.DYNAMIC_FEE_FLAG, SQRT_PRICE_1_1 ); } @@ -107,7 +102,7 @@ contract TestDynamicReturnFees is Test, Deployers, GasSnapshot { function test_dynamicReturnSwapFee_initializeZeroSwapFee() public { key.tickSpacing = 30; - manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); + manager.initialize(key, SQRT_PRICE_1_1); assertEq(_fetchPoolSwapFee(key), 0); } @@ -115,9 +110,7 @@ contract TestDynamicReturnFees is Test, Deployers, GasSnapshot { key.fee = 3000; // static fee dynamicReturnFeesHook.setFee(1000); // 0.10% fee is NOT used because the pool has a static fee - initPoolAndAddLiquidity( - currency0, currency1, IHooks(address(dynamicReturnFeesHook)), 3000, SQRT_PRICE_1_1, ZERO_BYTES - ); + initPoolAndAddLiquidity(currency0, currency1, IHooks(address(dynamicReturnFeesHook)), 3000, SQRT_PRICE_1_1); assertEq(_fetchPoolSwapFee(key), 3000); // despite returning a valid swap fee (1000), the static fee is used @@ -136,7 +129,7 @@ contract TestDynamicReturnFees is Test, Deployers, GasSnapshot { // create a new pool with an initial fee of 123 key.tickSpacing = 30; - manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); + manager.initialize(key, SQRT_PRICE_1_1); modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); uint24 initialFee = 123; dynamicReturnFeesHook.forcePoolFeeUpdate(key, initialFee); diff --git a/test/ModifyLiquidity.t.sol b/test/ModifyLiquidity.t.sol index dc8094091..f4ebe74aa 100644 --- a/test/ModifyLiquidity.t.sol +++ b/test/ModifyLiquidity.t.sol @@ -40,7 +40,7 @@ contract ModifyLiquidityTest is Test, Logger, Deployers, JavascriptFfi, Fuzzers, function setUp() public { deployFreshManagerAndRouters(); deployMintAndApprove2Currencies(); - (simpleKey, simplePoolId) = initPool(currency0, currency1, IHooks(address(0)), 3000, SQRT_PRICE_1_1, ZERO_BYTES); + (simpleKey, simplePoolId) = initPool(currency0, currency1, IHooks(address(0)), 3000, SQRT_PRICE_1_1); } /*////////////////////////////////////////////////////////////// @@ -72,9 +72,8 @@ contract ModifyLiquidityTest is Test, Logger, Deployers, JavascriptFfi, Fuzzers, // Static edge case, no fuzz test, to make sure we test max tickspacing. function test_ffi_addLiqudity_weirdPool_0_returnsCorrectLiquidityDelta() public { // Use a pool with TickSpacing of MAX_TICK_SPACING - (PoolKey memory wp0, PoolId wpId0) = initPool( - currency0, currency1, IHooks(address(0)), 500, TickMath.MAX_TICK_SPACING, SQRT_PRICE_1_1, ZERO_BYTES - ); + (PoolKey memory wp0, PoolId wpId0) = + initPool(currency0, currency1, IHooks(address(0)), 500, TickMath.MAX_TICK_SPACING, SQRT_PRICE_1_1); // Set the params to add random amount of liquidity to random tick boundary. int24 tickUpper = TickMath.MAX_TICK_SPACING * 4; @@ -97,9 +96,8 @@ contract ModifyLiquidityTest is Test, Logger, Deployers, JavascriptFfi, Fuzzers, // Static edge case, no fuzz test, to make sure we test min tick spacing. function test_ffi_addLiqudity_weirdPool_1_returnsCorrectLiquidityDelta() public { // Use a pool with TickSpacing of MIN_TICK_SPACING - (PoolKey memory wp0, PoolId wpId0) = initPool( - currency0, currency1, IHooks(address(0)), 551, TickMath.MIN_TICK_SPACING, SQRT_PRICE_1_1, ZERO_BYTES - ); + (PoolKey memory wp0, PoolId wpId0) = + initPool(currency0, currency1, IHooks(address(0)), 551, TickMath.MIN_TICK_SPACING, SQRT_PRICE_1_1); // Set the params to add random amount of liquidity to random tick boundary. int24 tickUpper = TickMath.MIN_TICK_SPACING * 17; diff --git a/test/PoolManager.swap.t.sol b/test/PoolManager.swap.t.sol index 30c9bc66a..1a7e1ebd3 100644 --- a/test/PoolManager.swap.t.sol +++ b/test/PoolManager.swap.t.sol @@ -41,7 +41,7 @@ abstract contract V3Fuzzer is V3Helper, Deployers, Fuzzers, IUniswapV3MintCallba v3Pool.initialize(sqrtPriceX96); key_ = PoolKey(currency0, currency1, fee, tickSpacing, IHooks(address(0))); - manager.initialize(key_, sqrtPriceX96, ""); + manager.initialize(key_, sqrtPriceX96); } function addLiquidity( diff --git a/test/PoolManager.t.sol b/test/PoolManager.t.sol index cb8c8fa73..be71725a1 100644 --- a/test/PoolManager.t.sol +++ b/test/PoolManager.t.sol @@ -179,7 +179,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { MockContract(mockAddr).setImplementation(hookAddr); - (key,) = initPool(currency0, currency1, IHooks(mockAddr), 3000, sqrtPriceX96, ZERO_BYTES); + (key,) = initPool(currency0, currency1, IHooks(mockAddr), 3000, sqrtPriceX96); BalanceDelta balanceDelta = modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); @@ -214,7 +214,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { MockContract(mockAddr).setImplementation(hookAddr); - (key,) = initPool(currency0, currency1, IHooks(mockAddr), 3000, sqrtPriceX96, ZERO_BYTES); + (key,) = initPool(currency0, currency1, IHooks(mockAddr), 3000, sqrtPriceX96); modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); BalanceDelta balanceDelta = modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); @@ -243,7 +243,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { vm.etch(hookAddr, address(impl).code); MockHooks mockHooks = MockHooks(hookAddr); - (key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); + (key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1); mockHooks.setReturnValue(mockHooks.beforeAddLiquidity.selector, bytes4(0xdeadbeef)); mockHooks.setReturnValue(mockHooks.afterAddLiquidity.selector, bytes4(0xdeadbeef)); @@ -265,7 +265,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { vm.etch(hookAddr, address(impl).code); MockHooks mockHooks = MockHooks(hookAddr); - (key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); + (key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1); modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); mockHooks.setReturnValue(mockHooks.beforeRemoveLiquidity.selector, bytes4(0xdeadbeef)); @@ -288,7 +288,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { vm.etch(hookAddr, address(impl).code); MockHooks mockHooks = MockHooks(hookAddr); - (key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); + (key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1); mockHooks.setReturnValue(mockHooks.beforeAddLiquidity.selector, mockHooks.beforeAddLiquidity.selector); mockHooks.setReturnValue(mockHooks.afterAddLiquidity.selector, mockHooks.afterAddLiquidity.selector); @@ -313,7 +313,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { vm.etch(hookAddr, address(impl).code); MockHooks mockHooks = MockHooks(hookAddr); - (key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); + (key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1); modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); mockHooks.setReturnValue(mockHooks.beforeRemoveLiquidity.selector, mockHooks.beforeRemoveLiquidity.selector); @@ -449,7 +449,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { vm.etch(allHooksAddr, address(impl).code); MockHooks mockHooks = MockHooks(allHooksAddr); - (key,) = initPool(currency0, currency1, mockHooks, 3000, SQRT_PRICE_1_1, ZERO_BYTES); + (key,) = initPool(currency0, currency1, mockHooks, 3000, SQRT_PRICE_1_1); modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); snapLastCall("addLiquidity with empty hook"); @@ -461,7 +461,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { vm.etch(allHooksAddr, address(impl).code); MockHooks mockHooks = MockHooks(allHooksAddr); - (key,) = initPool(currency0, currency1, mockHooks, 3000, SQRT_PRICE_1_1, ZERO_BYTES); + (key,) = initPool(currency0, currency1, mockHooks, 3000, SQRT_PRICE_1_1); modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); @@ -528,7 +528,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { MockContract(mockAddr).setImplementation(hookAddr); - (key,) = initPoolAndAddLiquidity(currency0, currency1, IHooks(mockAddr), 3000, SQRT_PRICE_1_1, ZERO_BYTES); + (key,) = initPoolAndAddLiquidity(currency0, currency1, IHooks(mockAddr), 3000, SQRT_PRICE_1_1); PoolSwapTest.TestSettings memory testSettings = PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false}); @@ -554,7 +554,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { vm.etch(hookAddr, address(impl).code); MockHooks mockHooks = MockHooks(hookAddr); - (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); + (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1); IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 10, sqrtPriceLimitX96: SQRT_PRICE_1_2}); @@ -582,7 +582,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { vm.etch(hookAddr, address(impl).code); MockHooks mockHooks = MockHooks(hookAddr); - (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); + (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1); IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -10, sqrtPriceLimitX96: SQRT_PRICE_1_2}); @@ -630,7 +630,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { vm.etch(allHooksAddr, address(impl).code); MockHooks mockHooks = MockHooks(allHooksAddr); - (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 3000, SQRT_PRICE_1_1, ZERO_BYTES); + (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 3000, SQRT_PRICE_1_1); PoolSwapTest.TestSettings memory testSettings = PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false}); @@ -821,7 +821,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { function test_donate_failsIfNoLiquidity(uint160 sqrtPriceX96) public { sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); - (key,) = initPool(currency0, currency1, IHooks(address(0)), 100, sqrtPriceX96, ZERO_BYTES); + (key,) = initPool(currency0, currency1, IHooks(address(0)), 100, sqrtPriceX96); vm.expectRevert(Pool.NoLiquidityToReceiveFees.selector); donateRouter.donate(key, 100, 100, ZERO_BYTES); @@ -860,7 +860,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { vm.etch(hookAddr, address(impl).code); MockHooks mockHooks = MockHooks(hookAddr); - (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); + (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1); mockHooks.setReturnValue(mockHooks.beforeDonate.selector, bytes4(0xdeadbeef)); mockHooks.setReturnValue(mockHooks.afterDonate.selector, bytes4(0xdeadbeef)); @@ -882,7 +882,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { vm.etch(hookAddr, address(impl).code); MockHooks mockHooks = MockHooks(hookAddr); - (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); + (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1); mockHooks.setReturnValue(mockHooks.beforeDonate.selector, mockHooks.beforeDonate.selector); mockHooks.setReturnValue(mockHooks.afterDonate.selector, mockHooks.afterDonate.selector); @@ -924,8 +924,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { (currency0Invalid ? currency0 : invalidCurrency), IHooks(address(0)), 3000, - SQRT_PRICE_1_1, - ZERO_BYTES + SQRT_PRICE_1_1 ); (uint256 amount0, uint256 amount1) = currency0Invalid ? (1, 0) : (0, 1); @@ -1155,7 +1154,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { // hooks: IHooks(address(0)), // tickSpacing: 10 // }); - // manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); + // manager.initialize(key, SQRT_PRICE_1_1); // PoolId poolId = key.toId(); // bytes32 slot0Bytes = manager.extsload(keccak256(abi.encode(poolId, POOL_SLOT))); @@ -1179,7 +1178,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot { // hooks: IHooks(address(0)), // tickSpacing: 10 // }); - // manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); + // manager.initialize(key, SQRT_PRICE_1_1); // // populate feeGrowthGlobalX128 struct w/ modify + swap // modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(-120, 120, 5 ether, 0)); diff --git a/test/PoolManagerInitialize.t.sol b/test/PoolManagerInitialize.t.sol index 22478c516..b4c9b43d0 100644 --- a/test/PoolManagerInitialize.t.sol +++ b/test/PoolManagerInitialize.t.sol @@ -63,30 +63,30 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot { if (key0.tickSpacing > TickMath.MAX_TICK_SPACING) { vm.expectRevert(abi.encodeWithSelector(IPoolManager.TickSpacingTooLarge.selector, key0.tickSpacing)); - manager.initialize(key0, sqrtPriceX96, ZERO_BYTES); + manager.initialize(key0, sqrtPriceX96); } else if (key0.tickSpacing < TickMath.MIN_TICK_SPACING) { vm.expectRevert(abi.encodeWithSelector(IPoolManager.TickSpacingTooSmall.selector, key0.tickSpacing)); - manager.initialize(key0, sqrtPriceX96, ZERO_BYTES); + manager.initialize(key0, sqrtPriceX96); } else if (key0.currency0 >= key0.currency1) { vm.expectRevert( abi.encodeWithSelector( IPoolManager.CurrenciesOutOfOrderOrEqual.selector, key0.currency0, key0.currency1 ) ); - manager.initialize(key0, sqrtPriceX96, ZERO_BYTES); + manager.initialize(key0, sqrtPriceX96); } else if (!key0.hooks.isValidHookAddress(key0.fee)) { vm.expectRevert(abi.encodeWithSelector(Hooks.HookAddressNotValid.selector, address(key0.hooks))); - manager.initialize(key0, sqrtPriceX96, ZERO_BYTES); + manager.initialize(key0, sqrtPriceX96); } else if ((key0.fee != LPFeeLibrary.DYNAMIC_FEE_FLAG) && (key0.fee > 1000000)) { vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, key0.fee)); - manager.initialize(key0, sqrtPriceX96, ZERO_BYTES); + manager.initialize(key0, sqrtPriceX96); } else { int24 tick = TickMath.getTickAtSqrtPrice(sqrtPriceX96); vm.expectEmit(true, true, true, true); emit Initialize( key0.toId(), key0.currency0, key0.currency1, key0.fee, key0.tickSpacing, key0.hooks, sqrtPriceX96, tick ); - manager.initialize(key0, sqrtPriceX96, ZERO_BYTES); + manager.initialize(key0, sqrtPriceX96); (uint160 slot0SqrtPriceX96,, uint24 slot0ProtocolFee,) = manager.getSlot0(key0.toId()); assertEq(slot0SqrtPriceX96, sqrtPriceX96); @@ -112,7 +112,7 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot { sqrtPriceX96, tick ); - manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); + manager.initialize(uninitializedKey, sqrtPriceX96); (uint160 slot0SqrtPriceX96, int24 slot0Tick, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId()); @@ -136,15 +136,15 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot { uninitializedKey.hooks = IHooks(mockAddr); - int24 tick = manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); + int24 tick = manager.initialize(uninitializedKey, sqrtPriceX96); (uint160 slot0SqrtPriceX96,,,) = manager.getSlot0(uninitializedKey.toId()); assertEq(slot0SqrtPriceX96, sqrtPriceX96, "sqrtPrice"); bytes32 beforeSelector = MockHooks.beforeInitialize.selector; - bytes memory beforeParams = abi.encode(address(this), uninitializedKey, sqrtPriceX96, ZERO_BYTES); + bytes memory beforeParams = abi.encode(address(this), uninitializedKey, sqrtPriceX96); bytes32 afterSelector = MockHooks.afterInitialize.selector; - bytes memory afterParams = abi.encode(address(this), uninitializedKey, sqrtPriceX96, tick, ZERO_BYTES); + bytes memory afterParams = abi.encode(address(this), uninitializedKey, sqrtPriceX96, tick); assertEq(MockContract(mockAddr).timesCalledSelector(beforeSelector), 1, "beforeSelector count"); assertTrue(MockContract(mockAddr).calledWithSelector(beforeSelector, beforeParams), "beforeSelector params"); @@ -172,7 +172,7 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot { tick ); - manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); + manager.initialize(uninitializedKey, sqrtPriceX96); } function test_initialize_succeedsWithEmptyHooks(uint160 sqrtPriceX96) public { @@ -187,7 +187,7 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot { uninitializedKey.hooks = mockHooks; - manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); + manager.initialize(uninitializedKey, sqrtPriceX96); (uint160 slot0SqrtPriceX96,,,) = manager.getSlot0(uninitializedKey.toId()); assertEq(slot0SqrtPriceX96, sqrtPriceX96); } @@ -206,7 +206,7 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot { Currency.unwrap(currency0) ) ); - manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); + manager.initialize(uninitializedKey, sqrtPriceX96); } function test_initialize_revertsWithSameTokenCombo(uint160 sqrtPriceX96) public { @@ -223,34 +223,16 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot { Currency.unwrap(currency0) ) ); - manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); - } - - function test_initialize_fetchFeeWhenController(uint24 protocolFee) public { - manager.setProtocolFeeController(feeController); - feeController.setProtocolFeeForPool(uninitializedKey.toId(), protocolFee); - - uint16 fee0 = protocolFee.getZeroForOneFee(); - uint16 fee1 = protocolFee.getOneForZeroFee(); - - manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES); - - (uint160 slot0SqrtPriceX96,, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId()); - assertEq(slot0SqrtPriceX96, SQRT_PRICE_1_1); - if ((fee0 > 1000) || (fee1 > 1000)) { - assertEq(slot0ProtocolFee, 0); - } else { - assertEq(slot0ProtocolFee, protocolFee); - } + manager.initialize(uninitializedKey, sqrtPriceX96); } function test_initialize_revertsWhenPoolAlreadyInitialized(uint160 sqrtPriceX96) public { // Assumptions tested in Pool.t.sol sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); - manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); + manager.initialize(uninitializedKey, sqrtPriceX96); vm.expectRevert(Pool.PoolAlreadyInitialized.selector); - manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); + manager.initialize(uninitializedKey, sqrtPriceX96); } function test_initialize_failsWithIncorrectSelectors() public { @@ -267,12 +249,12 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot { // Fails at beforeInitialize hook. vm.expectRevert(Hooks.InvalidHookResponse.selector); - manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES); + manager.initialize(uninitializedKey, SQRT_PRICE_1_1); // Fail at afterInitialize hook. mockHooks.setReturnValue(mockHooks.beforeInitialize.selector, mockHooks.beforeInitialize.selector); vm.expectRevert(Hooks.InvalidHookResponse.selector); - manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES); + manager.initialize(uninitializedKey, SQRT_PRICE_1_1); } function test_initialize_succeedsWithCorrectSelectors() public { @@ -301,7 +283,7 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot { tick ); - manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES); + manager.initialize(uninitializedKey, SQRT_PRICE_1_1); } function test_initialize_failsIfTickSpaceTooLarge(uint160 sqrtPriceX96) public { @@ -311,7 +293,7 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot { uninitializedKey.tickSpacing = TickMath.MAX_TICK_SPACING + 1; vm.expectRevert(abi.encodeWithSelector(IPoolManager.TickSpacingTooLarge.selector, uninitializedKey.tickSpacing)); - manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); + manager.initialize(uninitializedKey, sqrtPriceX96); } function test_initialize_failsIfTickSpaceZero(uint160 sqrtPriceX96) public { @@ -321,7 +303,7 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot { uninitializedKey.tickSpacing = 0; vm.expectRevert(abi.encodeWithSelector(IPoolManager.TickSpacingTooSmall.selector, uninitializedKey.tickSpacing)); - manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); + manager.initialize(uninitializedKey, sqrtPriceX96); } function test_initialize_failsIfTickSpaceNeg(uint160 sqrtPriceX96) public { @@ -331,114 +313,11 @@ contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot { uninitializedKey.tickSpacing = -1; vm.expectRevert(abi.encodeWithSelector(IPoolManager.TickSpacingTooSmall.selector, uninitializedKey.tickSpacing)); - manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); - } - - function test_initialize_succeedsWithOutOfBoundsFeeController(uint160 sqrtPriceX96) public { - // Assumptions tested in Pool.t.sol - sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); - - manager.setProtocolFeeController(outOfBoundsFeeController); - - int24 tick = TickMath.getTickAtSqrtPrice(sqrtPriceX96); - // expect initialize to succeed even though the controller reverts - vm.expectEmit(true, true, true, true); - emit Initialize( - uninitializedKey.toId(), - uninitializedKey.currency0, - uninitializedKey.currency1, - uninitializedKey.fee, - uninitializedKey.tickSpacing, - uninitializedKey.hooks, - sqrtPriceX96, - tick - ); - manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); - // protocol fees should default to 0 - (,, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId()); - assertEq(slot0ProtocolFee, 0); - } - - function test_initialize_succeedsWithRevertingFeeController(uint160 sqrtPriceX96) public { - // Assumptions tested in Pool.t.sol - sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); - - manager.setProtocolFeeController(revertingFeeController); - - int24 tick = TickMath.getTickAtSqrtPrice(sqrtPriceX96); - - // expect initialize to succeed even though the controller reverts - vm.expectEmit(true, true, true, true); - emit Initialize( - uninitializedKey.toId(), - uninitializedKey.currency0, - uninitializedKey.currency1, - uninitializedKey.fee, - uninitializedKey.tickSpacing, - uninitializedKey.hooks, - sqrtPriceX96, - tick - ); - manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); - // protocol fees should default to 0 - (,, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId()); - assertEq(slot0ProtocolFee, 0); - } - - function test_initialize_succeedsWithOverflowFeeController(uint160 sqrtPriceX96) public { - // Assumptions tested in Pool.t.sol - sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); - - manager.setProtocolFeeController(overflowFeeController); - - int24 tick = TickMath.getTickAtSqrtPrice(sqrtPriceX96); - - // expect initialize to succeed - vm.expectEmit(true, true, true, true); - emit Initialize( - uninitializedKey.toId(), - uninitializedKey.currency0, - uninitializedKey.currency1, - uninitializedKey.fee, - uninitializedKey.tickSpacing, - uninitializedKey.hooks, - sqrtPriceX96, - tick - ); - manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); - // protocol fees should default to 0 - (,, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId()); - assertEq(slot0ProtocolFee, 0); - } - - function test_initialize_succeedsWithWrongReturnSizeFeeController(uint160 sqrtPriceX96) public { - // Assumptions tested in Pool.t.sol - sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); - - manager.setProtocolFeeController(invalidReturnSizeFeeController); - - int24 tick = TickMath.getTickAtSqrtPrice(sqrtPriceX96); - - // expect initialize to succeed - vm.expectEmit(true, true, true, true); - emit Initialize( - uninitializedKey.toId(), - uninitializedKey.currency0, - uninitializedKey.currency1, - uninitializedKey.fee, - uninitializedKey.tickSpacing, - uninitializedKey.hooks, - sqrtPriceX96, - tick - ); - manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); - // protocol fees should default to 0 - (,, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId()); - assertEq(slot0ProtocolFee, 0); + manager.initialize(uninitializedKey, sqrtPriceX96); } function test_initialize_gas() public { - manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES); + manager.initialize(uninitializedKey, SQRT_PRICE_1_1); snapLastCall("initialize"); } } diff --git a/test/ProtocolFeesImplementation.t.sol b/test/ProtocolFeesImplementation.t.sol index 716d8b1bf..f5f7007ea 100644 --- a/test/ProtocolFeesImplementation.t.sol +++ b/test/ProtocolFeesImplementation.t.sol @@ -14,13 +14,7 @@ import {Deployers} from "../test/utils/Deployers.sol"; import {PoolId} from "../src/types/PoolId.sol"; import {IHooks} from "../src/interfaces/IHooks.sol"; import {Constants} from "../test/utils/Constants.sol"; -import { - ProtocolFeeControllerTest, - OutOfBoundsProtocolFeeControllerTest, - RevertingProtocolFeeControllerTest, - OverflowProtocolFeeControllerTest, - InvalidReturnSizeProtocolFeeControllerTest -} from "../src/test/ProtocolFeeControllerTest.sol"; +import {ProtocolFeeControllerTest} from "../src/test/ProtocolFeeControllerTest.sol"; contract ProtocolFeesTest is Test, GasSnapshot, Deployers { using ProtocolFeeLibrary for uint24; @@ -186,43 +180,4 @@ contract ProtocolFeesTest is Test, GasSnapshot, Deployers { protocolFees.updateProtocolFees(currency0, amount); assertEq(protocolFees.protocolFeesAccrued(currency0), newAmount); } - - function test_fetchProtocolFee_succeeds() public { - protocolFees.setProtocolFeeController(feeController); - vm.prank(address(feeController)); - uint24 protocolFee = protocolFees.fetchProtocolFee(key); - assertEq(protocolFee, 0); - } - - function test_fetchProtocolFee_outOfBounds() public { - outOfBoundsFeeController = new OutOfBoundsProtocolFeeControllerTest(); - protocolFees.setProtocolFeeController(outOfBoundsFeeController); - vm.prank(address(outOfBoundsFeeController)); - uint24 protocolFee = protocolFees.fetchProtocolFee(key); - assertEq(protocolFee, 0); - } - - function test_fetchProtocolFee_overflowFee() public { - overflowFeeController = new OverflowProtocolFeeControllerTest(); - protocolFees.setProtocolFeeController(overflowFeeController); - vm.prank(address(overflowFeeController)); - uint24 protocolFee = protocolFees.fetchProtocolFee(key); - assertEq(protocolFee, 0); - } - - function test_fetchProtocolFee_invalidReturnSize() public { - invalidReturnSizeFeeController = new InvalidReturnSizeProtocolFeeControllerTest(); - protocolFees.setProtocolFeeController(invalidReturnSizeFeeController); - vm.prank(address(invalidReturnSizeFeeController)); - uint24 protocolFee = protocolFees.fetchProtocolFee(key); - assertEq(protocolFee, 0); - } - - function test_fetchProtocolFee_revert() public { - revertingFeeController = new RevertingProtocolFeeControllerTest(); - protocolFees.setProtocolFeeController(revertingFeeController); - vm.prank(address(revertingFeeController)); - uint24 protocolFee = protocolFees.fetchProtocolFee(key); - assertEq(protocolFee, 0); - } } diff --git a/test/SkipCallsTestHook.t.sol b/test/SkipCallsTestHook.t.sol index fb07221aa..1e6bc584e 100644 --- a/test/SkipCallsTestHook.t.sol +++ b/test/SkipCallsTestHook.t.sol @@ -30,7 +30,7 @@ contract SkipCallsTest is Test, Deployers, GasSnapshot { assertEq(skipCallsTestHook.counter(), 0); - (key,) = initPool(currency0, currency1, IHooks(address(skipCallsTestHook)), 3000, SQRT_PRICE_1_1, ZERO_BYTES); + (key,) = initPool(currency0, currency1, IHooks(address(skipCallsTestHook)), 3000, SQRT_PRICE_1_1); } function approveAndAddLiquidity(SkipCallsTestHook skipCallsTestHook) private { diff --git a/test/Sync.t.sol b/test/Sync.t.sol index bc70386fb..74bf8e800 100644 --- a/test/Sync.t.sol +++ b/test/Sync.t.sol @@ -108,7 +108,7 @@ contract SyncTest is Test, Deployers, GasSnapshot { PoolKey memory key2 = PoolKey({currency0: cur0, currency1: cur1, fee: 3000, tickSpacing: 60, hooks: IHooks(address(0))}); - manager.initialize(key2, SQRT_PRICE_1_1, new bytes(0)); + manager.initialize(key2, SQRT_PRICE_1_1); modifyLiquidityRouter.modifyLiquidity(key2, IPoolManager.ModifyLiquidityParams(-60, 60, 100, 0), new bytes(0)); (uint256 balanceCurrency2) = currency2.balanceOf(address(manager)); diff --git a/test/libraries/BipsLibrary.t.sol b/test/libraries/BipsLibrary.t.sol deleted file mode 100644 index 02cc67d71..000000000 --- a/test/libraries/BipsLibrary.t.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import "forge-std/Test.sol"; -import {BipsLibrary} from "../../src/libraries/BipsLibrary.sol"; - -contract BipsLibraryTest is Test { - using BipsLibrary for uint256; - - // The block gas limit set in foundry config is 300_000_000 (300M) for testing purposes - uint256 BLOCK_GAS_LIMIT; - - function setUp() public { - BLOCK_GAS_LIMIT = block.gaslimit; - } - - function test_fuzz_calculatePortion(uint256 amount, uint256 bips) public { - amount = bound(amount, 0, uint256(type(uint128).max)); - if (bips > BipsLibrary.BPS_DENOMINATOR) { - vm.expectRevert(BipsLibrary.InvalidBips.selector); - amount.calculatePortion(bips); - } else { - assertEq(amount.calculatePortion(bips), amount * bips / BipsLibrary.BPS_DENOMINATOR); - } - } - - function test_fuzz_gasLimit(uint256 bips) public { - if (bips > BipsLibrary.BPS_DENOMINATOR) { - vm.expectRevert(BipsLibrary.InvalidBips.selector); - block.gaslimit.calculatePortion(bips); - } else { - assertEq(block.gaslimit.calculatePortion(bips), BLOCK_GAS_LIMIT * bips / BipsLibrary.BPS_DENOMINATOR); - } - } - - function test_gasLimit_100_percent() public view { - assertEq(block.gaslimit, block.gaslimit.calculatePortion(10_000)); - } - - function test_gasLimit_1_percent() public view { - // 100 bps = 1% - // 1% of 30M is 300K - assertEq(BLOCK_GAS_LIMIT / 100, block.gaslimit.calculatePortion(100)); - } - - function test_gasLimit_1BP() public view { - // 1bp is 0.01% - // 0.01% of 30M is 300 - assertEq(BLOCK_GAS_LIMIT / 10000, block.gaslimit.calculatePortion(1)); - } -} diff --git a/test/libraries/Hooks.t.sol b/test/libraries/Hooks.t.sol index 610250ccb..eacc1ea6c 100644 --- a/test/libraries/Hooks.t.sol +++ b/test/libraries/Hooks.t.sol @@ -43,7 +43,7 @@ contract HooksTest is Test, Deployers, GasSnapshot { } function test_initialize_succeedsWithHook() public { - manager.initialize(uninitializedKey, SQRT_PRICE_1_1, new bytes(123)); + manager.initialize(uninitializedKey, SQRT_PRICE_1_1); (uint160 sqrtPriceX96,,,) = manager.getSlot0(uninitializedKey.toId()); assertEq(sqrtPriceX96, SQRT_PRICE_1_1); @@ -54,13 +54,13 @@ contract HooksTest is Test, Deployers, GasSnapshot { function test_beforeInitialize_invalidReturn() public { mockHooks.setReturnValue(mockHooks.beforeInitialize.selector, bytes4(0xdeadbeef)); vm.expectRevert(Hooks.InvalidHookResponse.selector); - manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES); + manager.initialize(uninitializedKey, SQRT_PRICE_1_1); } function test_afterInitialize_invalidReturn() public { mockHooks.setReturnValue(mockHooks.afterInitialize.selector, bytes4(0xdeadbeef)); vm.expectRevert(Hooks.InvalidHookResponse.selector); - manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES); + manager.initialize(uninitializedKey, SQRT_PRICE_1_1); } function test_beforeAfterAddLiquidity_beforeAfterRemoveLiquidity_succeedsWithHook() public { @@ -1001,7 +1001,7 @@ contract HooksTest is Test, Deployers, GasSnapshot { BaseTestHooks revertingHook = BaseTestHooks(beforeSwapFlag); PoolKey memory key = PoolKey(currency0, currency1, 0, 60, IHooks(revertingHook)); - manager.initialize(key, SQRT_PRICE_1_1, new bytes(0)); + manager.initialize(key, SQRT_PRICE_1_1); IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_PRICE_1_2}); @@ -1027,7 +1027,7 @@ contract HooksTest is Test, Deployers, GasSnapshot { EmptyRevertContract revertingHook = EmptyRevertContract(beforeSwapFlag); PoolKey memory key = PoolKey(currency0, currency1, 0, 60, IHooks(address(revertingHook))); - manager.initialize(key, SQRT_PRICE_1_1, new bytes(0)); + manager.initialize(key, SQRT_PRICE_1_1); IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_PRICE_1_2}); diff --git a/test/libraries/Pool.t.sol b/test/libraries/Pool.t.sol index 4b8ec1e56..0ffa73f09 100644 --- a/test/libraries/Pool.t.sol +++ b/test/libraries/Pool.t.sol @@ -27,30 +27,27 @@ contract PoolTest is Test, GasSnapshot { uint24 constant MAX_PROTOCOL_FEE = ProtocolFeeLibrary.MAX_PROTOCOL_FEE; // 0.1% uint24 constant MAX_LP_FEE = LPFeeLibrary.MAX_LP_FEE; // 100% - function testPoolInitialize(uint160 sqrtPriceX96, uint24 protocolFee, uint24 swapFee) public { + function test_pool_initialize(uint160 sqrtPriceX96, uint24 swapFee) public { if (sqrtPriceX96 < TickMath.MIN_SQRT_PRICE || sqrtPriceX96 >= TickMath.MAX_SQRT_PRICE) { vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidSqrtPrice.selector, sqrtPriceX96)); - state.initialize(sqrtPriceX96, protocolFee, swapFee); + state.initialize(sqrtPriceX96, swapFee); } else { - state.initialize(sqrtPriceX96, protocolFee, swapFee); + state.initialize(sqrtPriceX96, swapFee); assertEq(state.slot0.sqrtPriceX96(), sqrtPriceX96); - assertEq(state.slot0.protocolFee(), protocolFee); + assertEq(state.slot0.protocolFee(), 0); assertEq(state.slot0.tick(), TickMath.getTickAtSqrtPrice(sqrtPriceX96)); assertLt(state.slot0.tick(), TickMath.MAX_TICK); assertGt(state.slot0.tick(), TickMath.MIN_TICK - 1); } } - function testModifyLiquidity( - uint160 sqrtPriceX96, - uint24 protocolFee, - uint24 lpFee, - Pool.ModifyLiquidityParams memory params - ) public { + function test_modifyLiquidity(uint160 sqrtPriceX96, uint24 lpFee, Pool.ModifyLiquidityParams memory params) + public + { // Assumptions tested in PoolManager.t.sol params.tickSpacing = int24(bound(params.tickSpacing, TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING)); - testPoolInitialize(sqrtPriceX96, protocolFee, lpFee); + test_pool_initialize(sqrtPriceX96, lpFee); if (params.tickLower >= params.tickUpper) { vm.expectRevert(abi.encodeWithSelector(Pool.TicksMisordered.selector, params.tickLower, params.tickUpper)); @@ -106,9 +103,8 @@ contract PoolTest is Test, GasSnapshot { uint24 protocolFee = protocolFee1 << 12 | protocolFee0; // initialize and add liquidity - testModifyLiquidity( + test_modifyLiquidity( sqrtPriceX96, - protocolFee, lpFee, Pool.ModifyLiquidityParams({ owner: address(this), @@ -121,6 +117,10 @@ contract PoolTest is Test, GasSnapshot { ); Slot0 slot0 = state.slot0; + assertEq(slot0.protocolFee(), 0); + slot0 = slot0.setProtocolFee(protocolFee); + assertEq(slot0.protocolFee(), protocolFee); + uint24 _lpFee = params.lpFeeOverride.isOverride() ? params.lpFeeOverride.removeOverrideFlag() : lpFee; uint24 swapFee = protocolFee == 0 ? _lpFee : uint16(protocolFee).calculateSwapFee(_lpFee); diff --git a/test/libraries/StateLibrary.t.sol b/test/libraries/StateLibrary.t.sol index 8327b40f5..4f6294465 100644 --- a/test/libraries/StateLibrary.t.sol +++ b/test/libraries/StateLibrary.t.sol @@ -33,7 +33,7 @@ contract StateLibraryTest is Test, Deployers, Fuzzers, GasSnapshot { // Create the pool key = PoolKey(currency0, currency1, 3000, 60, IHooks(address(0x0))); poolId = key.toId(); - manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); + manager.initialize(key, SQRT_PRICE_1_1); } function test_getSlot0() public { diff --git a/test/utils/Deployers.sol b/test/utils/Deployers.sol index 2d7b6f410..f15b42461 100644 --- a/test/utils/Deployers.sol +++ b/test/utils/Deployers.sol @@ -25,13 +25,7 @@ import {PoolClaimsTest} from "../../src/test/PoolClaimsTest.sol"; import {ActionsRouter} from "../../src/test/ActionsRouter.sol"; import {LiquidityAmounts} from "../../test/utils/LiquidityAmounts.sol"; import {StateLibrary} from "../../src/libraries/StateLibrary.sol"; -import { - ProtocolFeeControllerTest, - OutOfBoundsProtocolFeeControllerTest, - RevertingProtocolFeeControllerTest, - OverflowProtocolFeeControllerTest, - InvalidReturnSizeProtocolFeeControllerTest -} from "../../src/test/ProtocolFeeControllerTest.sol"; +import {ProtocolFeeControllerTest} from "../../src/test/ProtocolFeeControllerTest.sol"; contract Deployers { using LPFeeLibrary for uint24; @@ -70,10 +64,6 @@ contract Deployers { PoolClaimsTest claimsRouter; PoolNestedActionsTest nestedActionRouter; ProtocolFeeControllerTest feeController; - RevertingProtocolFeeControllerTest revertingFeeController; - OutOfBoundsProtocolFeeControllerTest outOfBoundsFeeController; - OverflowProtocolFeeControllerTest overflowFeeController; - InvalidReturnSizeProtocolFeeControllerTest invalidReturnSizeFeeController; PoolKey key; PoolKey nativeKey; @@ -99,10 +89,6 @@ contract Deployers { claimsRouter = new PoolClaimsTest(manager); nestedActionRouter = new PoolNestedActionsTest(manager); feeController = new ProtocolFeeControllerTest(); - revertingFeeController = new RevertingProtocolFeeControllerTest(); - outOfBoundsFeeController = new OutOfBoundsProtocolFeeControllerTest(); - overflowFeeController = new OverflowProtocolFeeControllerTest(); - invalidReturnSizeFeeController = new InvalidReturnSizeProtocolFeeControllerTest(); actionsRouter = new ActionsRouter(manager); manager.setProtocolFeeController(feeController); @@ -154,17 +140,13 @@ contract Deployers { } } - function initPool( - Currency _currency0, - Currency _currency1, - IHooks hooks, - uint24 fee, - uint160 sqrtPriceX96, - bytes memory initData - ) internal returns (PoolKey memory _key, PoolId id) { + function initPool(Currency _currency0, Currency _currency1, IHooks hooks, uint24 fee, uint160 sqrtPriceX96) + internal + returns (PoolKey memory _key, PoolId id) + { _key = PoolKey(_currency0, _currency1, fee, fee.isDynamicFee() ? int24(60) : int24(fee / 100 * 2), hooks); id = _key.toId(); - manager.initialize(_key, sqrtPriceX96, initData); + manager.initialize(_key, sqrtPriceX96); } function initPool( @@ -173,12 +155,11 @@ contract Deployers { IHooks hooks, uint24 fee, int24 tickSpacing, - uint160 sqrtPriceX96, - bytes memory initData + uint160 sqrtPriceX96 ) internal returns (PoolKey memory _key, PoolId id) { _key = PoolKey(_currency0, _currency1, fee, tickSpacing, hooks); id = _key.toId(); - manager.initialize(_key, sqrtPriceX96, initData); + manager.initialize(_key, sqrtPriceX96); } function initPoolAndAddLiquidity( @@ -186,10 +167,9 @@ contract Deployers { Currency _currency1, IHooks hooks, uint24 fee, - uint160 sqrtPriceX96, - bytes memory initData + uint160 sqrtPriceX96 ) internal returns (PoolKey memory _key, PoolId id) { - (_key, id) = initPool(_currency0, _currency1, hooks, fee, sqrtPriceX96, initData); + (_key, id) = initPool(_currency0, _currency1, hooks, fee, sqrtPriceX96); modifyLiquidityRouter.modifyLiquidity{value: msg.value}(_key, LIQUIDITY_PARAMS, ZERO_BYTES); } @@ -199,10 +179,9 @@ contract Deployers { IHooks hooks, uint24 fee, uint160 sqrtPriceX96, - bytes memory initData, uint256 msgValue ) internal returns (PoolKey memory _key, PoolId id) { - (_key, id) = initPool(_currency0, _currency1, hooks, fee, sqrtPriceX96, initData); + (_key, id) = initPool(_currency0, _currency1, hooks, fee, sqrtPriceX96); modifyLiquidityRouter.modifyLiquidity{value: msgValue}(_key, LIQUIDITY_PARAMS, ZERO_BYTES); } @@ -211,11 +190,10 @@ contract Deployers { deployFreshManagerAndRouters(); // sets the global currencies and key deployMintAndApprove2Currencies(); - (key,) = initPoolAndAddLiquidity(currency0, currency1, hooks, 3000, SQRT_PRICE_1_1, ZERO_BYTES); + (key,) = initPoolAndAddLiquidity(currency0, currency1, hooks, 3000, SQRT_PRICE_1_1); nestedActionRouter.executor().setKey(key); - (nativeKey,) = initPoolAndAddLiquidityETH( - CurrencyLibrary.ADDRESS_ZERO, currency1, hooks, 3000, SQRT_PRICE_1_1, ZERO_BYTES, 1 ether - ); + (nativeKey,) = + initPoolAndAddLiquidityETH(CurrencyLibrary.ADDRESS_ZERO, currency1, hooks, 3000, SQRT_PRICE_1_1, 1 ether); uninitializedKey = key; uninitializedNativeKey = nativeKey; uninitializedKey.fee = 100;