From 2a65fdf48247f80f6e572270563daf13640e64f1 Mon Sep 17 00:00:00 2001 From: debych Date: Tue, 3 Sep 2024 20:17:19 +0300 Subject: [PATCH 01/11] [Core] fix pending fee transfer --- src/core/contracts/AlgebraFactory.sol | 2 +- src/core/contracts/base/ReservesManager.sol | 86 ++++++++++++------- .../contracts/libraries/PoolAddress.sol | 2 +- 3 files changed, 57 insertions(+), 33 deletions(-) diff --git a/src/core/contracts/AlgebraFactory.sol b/src/core/contracts/AlgebraFactory.sol index 6236ce8f..6ddd3590 100644 --- a/src/core/contracts/AlgebraFactory.sol +++ b/src/core/contracts/AlgebraFactory.sol @@ -57,7 +57,7 @@ contract AlgebraFactory is IAlgebraFactory, Ownable2Step, AccessControlEnumerabl /// @inheritdoc IAlgebraFactory /// @dev keccak256 of AlgebraPool init bytecode. Used to compute pool address deterministically - bytes32 public constant POOL_INIT_CODE_HASH = 0x53a254b73c7f4f4a23175de0908ad4b30f3bc60806bd69bba905db6f24b991a5; + bytes32 public constant POOL_INIT_CODE_HASH = 0xe5353bc2362696b562faf4b8c41096ecbc2795f6f42dd5b78d8750e17b84ad8d; constructor(address _poolDeployer) { require(_poolDeployer != address(0)); diff --git a/src/core/contracts/base/ReservesManager.sol b/src/core/contracts/base/ReservesManager.sol index 488e24ef..d1aa3dc1 100644 --- a/src/core/contracts/base/ReservesManager.sol +++ b/src/core/contracts/base/ReservesManager.sol @@ -67,15 +67,13 @@ abstract contract ReservesManager is AlgebraPoolBase { } } - function updateFeeAmounts( - int256 deltaR0, - int256 deltaR1, + function _accrueAndTransferFees( uint256 fee0, uint256 fee1, - address feesRecipient, - bytes32 slot, - uint32 lastTimestamp - ) internal returns (int256, int256, uint256, uint256) { + uint256 lastTimestamp, + address recipient, + bytes32 slot + ) internal returns (uint256, uint256, uint256, uint256) { uint256 feePending0; uint256 feePending1; @@ -93,29 +91,35 @@ abstract contract ReservesManager is AlgebraPoolBase { feePending0 += fee0; feePending1 += fee1; - uint256 feeSent0; - uint256 feeSent1; - if (_blockTimestamp() - lastTimestamp >= Constants.FEE_TRANSFER_FREQUENCY || feePending0 > type(uint104).max || feePending1 > type(uint104).max) { - if (feePending0 > 0) { - _transfer(token0, feesRecipient, feePending0); - deltaR0 = deltaR0 - feePending0.toInt256(); - feeSent0 = feePending0; - feePending0 = 0; - } - if (feePending1 > 0) { - _transfer(token1, feesRecipient, feePending1); - deltaR1 = deltaR1 - feePending1.toInt256(); - feeSent1 = feePending1; - feePending1 = 0; + (uint256 feeSent0, uint256 feeSent1) = _transferFees(feePending0, feePending1, recipient); + assembly { + sstore(slot, 0) } + return (0, 0, feeSent0, feeSent1); + } else { + return (feePending0, feePending1, 0, 0); } + } - assembly { - sstore(slot, or(or(feePending0, shl(104, feePending1)), shl(208, lastTimestamp))) + function _transferFees( + uint256 feePending0, + uint256 feePending1, + address feesRecipient + ) private returns (uint256, uint256) { + uint256 feeSent0; + uint256 feeSent1; + + if (feePending0 > 0) { + _transfer(token0, feesRecipient, feePending0); + feeSent0 = feePending0; + } + if (feePending1 > 0) { + _transfer(token1, feesRecipient, feePending1); + feeSent1 = feePending1; } - return (deltaR0, deltaR1, feeSent0, feeSent1); + return (feeSent0, feeSent1); } /// @notice Applies deltas to reserves and pays communityFees @@ -136,26 +140,46 @@ abstract contract ReservesManager is AlgebraPoolBase { bytes32 slot; uint32 lastTimestamp = lastFeeTransferTimestamp; uint32 currentTimestamp = _blockTimestamp(); + bool feeSent; if (communityFee0 | communityFee1 != 0) { assembly { slot := communityFeePending0.slot } - (deltaR0, deltaR1, , ) = updateFeeAmounts(deltaR0, deltaR1, communityFee0, communityFee1, communityVault, slot, lastTimestamp); + + (uint256 feePending0, uint256 feePending1, uint256 feeSent0, uint256 feeSent1) = _accrueAndTransferFees(communityFee0, communityFee1, lastTimestamp, communityVault, slot); + if (feeSent0 | feeSent1 != 0) { + (deltaR0, deltaR1) = (deltaR0 - feeSent0.toInt256(), deltaR1 - feeSent1.toInt256()); + feeSent = true; + } else { + (communityFeePending0, communityFeePending1) = (uint104(feePending0), uint104(feePending1)); + } } if (pluginFee0 | pluginFee1 != 0) { assembly { slot := pluginFeePending0.slot } - uint256 pluginFeeSent0; - uint256 pluginFeeSent1; - (deltaR0, deltaR1, pluginFeeSent0, pluginFeeSent1) = updateFeeAmounts(deltaR0, deltaR1, pluginFee0, pluginFee1, plugin, slot, lastTimestamp); - if (pluginFeeSent0 > 0 || pluginFeeSent1 > 0) { - if (IAlgebraPlugin(plugin).handlePluginFee(pluginFeeSent0, pluginFeeSent1) != IAlgebraPlugin.handlePluginFee.selector) revert IAlgebraPoolErrors.invalidPluginResponce(); + + (uint256 feePending0, uint256 feePending1, uint256 feeSent0, uint256 feeSent1) = _accrueAndTransferFees(pluginFee0, pluginFee1, lastTimestamp, plugin, slot); + if (feeSent0 | feeSent1 != 0) { + (deltaR0, deltaR1) = (deltaR0 - feeSent0.toInt256(), deltaR1 - feeSent1.toInt256()); + feeSent = true; + + if (IAlgebraPlugin(plugin).handlePluginFee(feeSent0, feeSent1) != IAlgebraPlugin.handlePluginFee.selector) revert IAlgebraPoolErrors.invalidPluginResponce(); + } else { + (pluginFeePending0, pluginFeePending1) = (uint104(feePending0), uint104(feePending1)); + } + } else if (feeSent) { + (uint256 feeSent0, uint256 feeSent1) = _transferFees(pluginFeePending0, pluginFeePending1, plugin); + if (feeSent0 | feeSent1 != 0) { + (pluginFeePending0, pluginFeePending1) = (0, 0); + (deltaR0, deltaR1) = (deltaR0 - feeSent0.toInt256(), deltaR1 - feeSent1.toInt256()); + + if (IAlgebraPlugin(plugin).handlePluginFee(feeSent0, feeSent1) != IAlgebraPlugin.handlePluginFee.selector) revert IAlgebraPoolErrors.invalidPluginResponce(); } } - if (currentTimestamp - lastTimestamp >= Constants.FEE_TRANSFER_FREQUENCY) lastFeeTransferTimestamp = currentTimestamp; + if (feeSent) lastFeeTransferTimestamp = currentTimestamp; } if (deltaR0 | deltaR1 == 0) return; diff --git a/src/periphery/contracts/libraries/PoolAddress.sol b/src/periphery/contracts/libraries/PoolAddress.sol index 770ef4d4..b0f4804f 100644 --- a/src/periphery/contracts/libraries/PoolAddress.sol +++ b/src/periphery/contracts/libraries/PoolAddress.sol @@ -5,7 +5,7 @@ pragma solidity >=0.5.0; /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery library PoolAddress { - bytes32 internal constant POOL_INIT_CODE_HASH = 0x53a254b73c7f4f4a23175de0908ad4b30f3bc60806bd69bba905db6f24b991a5; + bytes32 internal constant POOL_INIT_CODE_HASH = 0xe5353bc2362696b562faf4b8c41096ecbc2795f6f42dd5b78d8750e17b84ad8d; /// @notice The identifying key of the pool struct PoolKey { From 2f5387f8cb7296e6833ab76ecce1a563a8f0c03f Mon Sep 17 00:00:00 2001 From: debych Date: Tue, 3 Sep 2024 20:17:52 +0300 Subject: [PATCH 02/11] [Core] set 0 runs --- src/core/hardhat.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hardhat.config.ts b/src/core/hardhat.config.ts index b130f221..ea05d892 100644 --- a/src/core/hardhat.config.ts +++ b/src/core/hardhat.config.ts @@ -39,7 +39,7 @@ const HIGH_COMPILER_SETTINGS: SolcUserConfig = { evmVersion: 'paris', optimizer: { enabled: true, - runs: 500, + runs: 0, }, metadata: { bytecodeHash: 'none', From d6b2c7734a75fcf8f2e98b8d5f7d6abb2cfccd9a Mon Sep 17 00:00:00 2001 From: IliaAzhel Date: Wed, 4 Sep 2024 17:44:53 +0300 Subject: [PATCH 03/11] [Core] add changeReserves to burn --- src/core/contracts/AlgebraFactory.sol | 2 +- src/core/contracts/AlgebraPool.sol | 11 +++++++---- src/periphery/contracts/libraries/PoolAddress.sol | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/core/contracts/AlgebraFactory.sol b/src/core/contracts/AlgebraFactory.sol index 6ddd3590..be7536a2 100644 --- a/src/core/contracts/AlgebraFactory.sol +++ b/src/core/contracts/AlgebraFactory.sol @@ -57,7 +57,7 @@ contract AlgebraFactory is IAlgebraFactory, Ownable2Step, AccessControlEnumerabl /// @inheritdoc IAlgebraFactory /// @dev keccak256 of AlgebraPool init bytecode. Used to compute pool address deterministically - bytes32 public constant POOL_INIT_CODE_HASH = 0xe5353bc2362696b562faf4b8c41096ecbc2795f6f42dd5b78d8750e17b84ad8d; + bytes32 public constant POOL_INIT_CODE_HASH = 0x6385c295f92db035f35dfbf362b0b49aa3525ab9a8f623f2c137edbe2b3d3574; constructor(address _poolDeployer) { require(_poolDeployer != address(0)); diff --git a/src/core/contracts/AlgebraPool.sol b/src/core/contracts/AlgebraPool.sol index 1663dea2..dcfe0c5b 100644 --- a/src/core/contracts/AlgebraPool.sol +++ b/src/core/contracts/AlgebraPool.sol @@ -143,16 +143,19 @@ contract AlgebraPool is AlgebraPoolBase, TickStructure, ReentrancyGuard, Positio (amount0, amount1) = _updatePositionTicksAndFees(position, bottomTick, topTick, liquidityDelta); if (pluginFee > 0) { + uint256 deltaPluginFeePending0; + uint256 deltaPluginFeePending1; + if (amount0 > 0) { - uint256 deltaPluginFeePending0 = FullMath.mulDiv(amount0, pluginFee, Constants.FEE_DENOMINATOR); + deltaPluginFeePending0 = FullMath.mulDiv(amount0, pluginFee, Constants.FEE_DENOMINATOR); amount0 -= deltaPluginFeePending0; - pluginFeePending0 += uint104(deltaPluginFeePending0); } if (amount1 > 0) { - uint256 deltaPluginFeePending1 = FullMath.mulDiv(amount1, pluginFee, Constants.FEE_DENOMINATOR); + deltaPluginFeePending1 = FullMath.mulDiv(amount1, pluginFee, Constants.FEE_DENOMINATOR); amount1 -= deltaPluginFeePending1; - pluginFeePending1 += uint104(deltaPluginFeePending1); } + + _changeReserves(0, 0, 0, 0, deltaPluginFeePending0, deltaPluginFeePending1); } if (amount0 | amount1 != 0) { diff --git a/src/periphery/contracts/libraries/PoolAddress.sol b/src/periphery/contracts/libraries/PoolAddress.sol index b0f4804f..afdeb260 100644 --- a/src/periphery/contracts/libraries/PoolAddress.sol +++ b/src/periphery/contracts/libraries/PoolAddress.sol @@ -5,7 +5,7 @@ pragma solidity >=0.5.0; /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery library PoolAddress { - bytes32 internal constant POOL_INIT_CODE_HASH = 0xe5353bc2362696b562faf4b8c41096ecbc2795f6f42dd5b78d8750e17b84ad8d; + bytes32 internal constant POOL_INIT_CODE_HASH = 0x6385c295f92db035f35dfbf362b0b49aa3525ab9a8f623f2c137edbe2b3d3574; /// @notice The identifying key of the pool struct PoolKey { From 3111145092b52a2efb745baa11cc3a670f2f1f7e Mon Sep 17 00:00:00 2001 From: IliaAzhel Date: Wed, 4 Sep 2024 22:04:41 +0300 Subject: [PATCH 04/11] [Core] update fees calculation --- src/core/contracts/AlgebraFactory.sol | 2 +- src/core/contracts/AlgebraPool.sol | 2 +- src/core/contracts/base/SwapCalculation.sol | 7 ++++++- src/periphery/contracts/libraries/PoolAddress.sol | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/core/contracts/AlgebraFactory.sol b/src/core/contracts/AlgebraFactory.sol index be7536a2..7c99afbe 100644 --- a/src/core/contracts/AlgebraFactory.sol +++ b/src/core/contracts/AlgebraFactory.sol @@ -57,7 +57,7 @@ contract AlgebraFactory is IAlgebraFactory, Ownable2Step, AccessControlEnumerabl /// @inheritdoc IAlgebraFactory /// @dev keccak256 of AlgebraPool init bytecode. Used to compute pool address deterministically - bytes32 public constant POOL_INIT_CODE_HASH = 0x6385c295f92db035f35dfbf362b0b49aa3525ab9a8f623f2c137edbe2b3d3574; + bytes32 public constant POOL_INIT_CODE_HASH = 0x95cae1693e5a3bc78f48679682e43b3ce024da4362d51eccdac32de2ccaba0ba; constructor(address _poolDeployer) { require(_poolDeployer != address(0)); diff --git a/src/core/contracts/AlgebraPool.sol b/src/core/contracts/AlgebraPool.sol index dcfe0c5b..18cdfa1e 100644 --- a/src/core/contracts/AlgebraPool.sol +++ b/src/core/contracts/AlgebraPool.sol @@ -373,7 +373,7 @@ contract AlgebraPool is AlgebraPoolBase, TickStructure, ReentrancyGuard, Positio if (_isPlugin()) return (0, 0); bytes4 selector; (selector, overrideFee, pluginFee) = IAlgebraPlugin(plugin).beforeSwap(msg.sender, recipient, zto, amount, limitPrice, payInAdvance, data); - if (overrideFee >= 1e6 || pluginFee > overrideFee) revert incorrectPluginFee(); + if ((overrideFee + pluginFee) >= 1e6) revert incorrectPluginFee(); selector.shouldReturn(IAlgebraPlugin.beforeSwap.selector); } } diff --git a/src/core/contracts/base/SwapCalculation.sol b/src/core/contracts/base/SwapCalculation.sol index 75fb28a6..f00fb196 100644 --- a/src/core/contracts/base/SwapCalculation.sol +++ b/src/core/contracts/base/SwapCalculation.sol @@ -60,7 +60,12 @@ abstract contract SwapCalculation is AlgebraPoolBase { // load from one storage slot too (currentPrice, currentTick, cache.fee, cache.communityFee) = (globalState.price, globalState.tick, globalState.lastFee, globalState.communityFee); if (currentPrice == 0) revert notInitialized(); - if (overrideFee != 0) cache.fee = overrideFee; + if (overrideFee != 0) { + cache.fee = overrideFee + pluginFee; + } else { + cache.fee += pluginFee; + } + if (cache.fee >= 1e6) revert incorrectPluginFee(); if (zeroToOne) { if (limitSqrtPrice >= currentPrice || limitSqrtPrice <= TickMath.MIN_SQRT_RATIO) revert invalidLimitSqrtPrice(); diff --git a/src/periphery/contracts/libraries/PoolAddress.sol b/src/periphery/contracts/libraries/PoolAddress.sol index afdeb260..f991d857 100644 --- a/src/periphery/contracts/libraries/PoolAddress.sol +++ b/src/periphery/contracts/libraries/PoolAddress.sol @@ -5,7 +5,7 @@ pragma solidity >=0.5.0; /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery library PoolAddress { - bytes32 internal constant POOL_INIT_CODE_HASH = 0x6385c295f92db035f35dfbf362b0b49aa3525ab9a8f623f2c137edbe2b3d3574; + bytes32 internal constant POOL_INIT_CODE_HASH = 0x95cae1693e5a3bc78f48679682e43b3ce024da4362d51eccdac32de2ccaba0ba; /// @notice The identifying key of the pool struct PoolKey { From 0245da0a75dfab2a430a40fce51e91fcc76b5f0c Mon Sep 17 00:00:00 2001 From: IliaAzhel Date: Thu, 5 Sep 2024 12:59:21 +0300 Subject: [PATCH 05/11] [Core] fix tests --- src/core/contracts/test/MockPoolPlugin.sol | 4 +-- src/core/test/AlgebraPool.spec.ts | 36 +++++++++++++--------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/core/contracts/test/MockPoolPlugin.sol b/src/core/contracts/test/MockPoolPlugin.sol index 27ebf15d..b3675f9a 100644 --- a/src/core/contracts/test/MockPoolPlugin.sol +++ b/src/core/contracts/test/MockPoolPlugin.sol @@ -110,8 +110,8 @@ contract MockPoolPlugin is IAlgebraPlugin, IAlgebraDynamicFeePlugin { ) external override returns (bytes4, uint24) { emit BeforeModifyPosition(sender, recipient, bottomTick, topTick, desiredLiquidityDelta, data); if (!Plugins.hasFlag(selectorsDisableConfig, Plugins.BEFORE_POSITION_MODIFY_FLAG)) - return (IAlgebraPlugin.beforeModifyPosition.selector, overrideFee); - return (IAlgebraPlugin.defaultPluginConfig.selector, overrideFee); + return (IAlgebraPlugin.beforeModifyPosition.selector, pluginFee); + return (IAlgebraPlugin.defaultPluginConfig.selector, pluginFee); } /// @notice The hook called after a position is modified diff --git a/src/core/test/AlgebraPool.spec.ts b/src/core/test/AlgebraPool.spec.ts index f5bac29d..0526c7c3 100644 --- a/src/core/test/AlgebraPool.spec.ts +++ b/src/core/test/AlgebraPool.spec.ts @@ -2430,7 +2430,7 @@ describe('AlgebraPool', () => { }); }); - describe('#pluginFee', () => { + describe.only('#pluginFee', () => { let poolPlugin : MockPoolPlugin; beforeEach('initialize the pool', async () => { @@ -2442,15 +2442,19 @@ describe('AlgebraPool', () => { await mint(wallet.address, minTick, maxTick, expandTo18Decimals(1)); }); - it('swap fails if plugin fee greater than override fee', async () => { - await poolPlugin.setPluginFees(3000, 4000); + it('swap/burn fails if plugin fee exceeds max value', async () => { + await poolPlugin.setPluginFees(4000, 1000000); await expect(swapExact0For1(expandTo18Decimals(1), wallet.address)).to.be.revertedWithCustomError(pool, 'incorrectPluginFee'); + await expect(pool.burn(minTick, maxTick, expandTo18Decimals(1), '0x')).to.be.revertedWithCustomError(pool, 'incorrectPluginFee'); }) - it('swap fails if plugin fee exceeds max value', async () => { - await poolPlugin.setPluginFees(1000000, 4000); + it('swap fails if fees sum exceeds max value', async () => { + await poolPlugin.setPluginFees(15000, 990000); + await expect(swapExact0For1(expandTo18Decimals(1), wallet.address)).to.be.revertedWithCustomError(pool, 'incorrectPluginFee'); + await poolPlugin.setPluginFees(0, 990000); + await pool.setPluginConfig(1) + await pool.setFee(15000) await expect(swapExact0For1(expandTo18Decimals(1), wallet.address)).to.be.revertedWithCustomError(pool, 'incorrectPluginFee'); - await expect(pool.burn(minTick, maxTick, expandTo18Decimals(1), '0x')).to.be.revertedWithCustomError(pool, 'incorrectPluginFee'); }) it('swap fails if plugin return incorrect selector', async () => { @@ -2470,29 +2474,32 @@ describe('AlgebraPool', () => { }) it('works correct on swap, fee is 50%, 75%, 99%', async () => { - await poolPlugin.setPluginFees(500000, 500000); + await poolPlugin.setPluginFees(0, 500000); await swapExact0For1(expandTo18Decimals(1), wallet.address); await swapExact1For0(expandTo18Decimals(1), wallet.address); let pluginFees = await pool.getPluginFeePending(); expect(pluginFees[1]).to.be.eq(expandTo18Decimals(1)/2n); - await poolPlugin.setPluginFees(750000, 750000); + await poolPlugin.setPluginFees(0, 750000); await swapExact1For0(expandTo18Decimals(1), wallet.address); pluginFees = await pool.getPluginFeePending(); expect(pluginFees[1]).to.be.eq(expandTo18Decimals(1)* 125n / 100n); - await poolPlugin.setPluginFees(990000, 990000); + await poolPlugin.setPluginFees(0, 990000); await swapExact1For0(expandTo18Decimals(1), wallet.address); pluginFees = await pool.getPluginFeePending(); expect(pluginFees[1]).to.be.eq(expandTo18Decimals(1)* 224n / 100n); }) it('works correct on burn', async () => { - await poolPlugin.setPluginFees(6000, 0); + await poolPlugin.setPluginFees(0, 6000); + const pluginBalance0Before = await token0.balanceOf(poolPlugin); + const pluginBalance1Before = await token1.balanceOf(poolPlugin); await pool.burn(minTick, maxTick, expandTo18Decimals(1), '0x') - let pluginFees = await pool.getPluginFeePending(); - expect(pluginFees[0]).to.be.eq(6n * 10n**15n-1n); - expect(pluginFees[1]).to.be.eq(6n * 10n**15n-1n) + const pluginBalance0After = await token0.balanceOf(poolPlugin); + const pluginBalance1After = await token1.balanceOf(poolPlugin); + expect(pluginBalance0After - pluginBalance0Before).to.be.eq(6n * 10n**15n-1n); + expect(pluginBalance1After - pluginBalance1Before).to.be.eq(6n * 10n**15n-1n); }) it('fees transfered to plugin', async () => { @@ -2506,8 +2513,9 @@ describe('AlgebraPool', () => { expect(pluginBalance1After - pluginBalance1Before).to.be.eq(0); }) + it('works correct with communityFee', async () => { - await poolPlugin.setPluginFees(5000, 4000); + await poolPlugin.setPluginFees(1000, 4000); await pool.setCommunityFee(500); await swapExact0For1(expandTo18Decimals(1), wallet.address); await swapExact0For1(expandTo18Decimals(1), wallet.address); From ccf54f964067fb047bccac2c72b12a649893672c Mon Sep 17 00:00:00 2001 From: IliaAzhel Date: Thu, 5 Sep 2024 13:49:38 +0300 Subject: [PATCH 06/11] [Core] fix tests & updates snapshots --- src/core/test/AlgebraPool.gas.spec.ts | 30 ++++++- src/core/test/AlgebraPool.spec.ts | 3 +- .../__snapshots__/AlgebraFactory.spec.ts.snap | 10 +-- .../AlgebraPool.gas.spec.ts.snap | 80 +++++++++++-------- 4 files changed, 81 insertions(+), 42 deletions(-) diff --git a/src/core/test/AlgebraPool.gas.spec.ts b/src/core/test/AlgebraPool.gas.spec.ts index 97dbba34..0f2e46f3 100644 --- a/src/core/test/AlgebraPool.gas.spec.ts +++ b/src/core/test/AlgebraPool.gas.spec.ts @@ -1,7 +1,7 @@ import { ethers } from 'hardhat'; import { Wallet } from 'ethers'; import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -import { MockTimeAlgebraPool, AlgebraPool } from '../typechain'; +import { MockTimeAlgebraPool, AlgebraPool, MockPoolPlugin } from '../typechain'; import { expect } from './shared/expect'; import { poolFixture } from './shared/fixtures'; @@ -122,6 +122,34 @@ describe('AlgebraPool gas tests [ @skip-on-coverage ]', () => { }); }) + describe('#swapExact1For0 with plugin fee on', () => { + + beforeEach('load the fixture', async () => { + const MockPoolPluginFactory = await ethers.getContractFactory('MockPoolPlugin'); + let poolPlugin = (await MockPoolPluginFactory.deploy(await pool.getAddress())) as any as MockPoolPlugin; + await poolPlugin.setPluginFees(0, 1000); + await pool.setPlugin(poolPlugin); + await pool.setPluginConfig(255); + }); + + it('first swap in block with no tick movement, without transfer', async () => { + await swapExact1For0(1000, wallet.address) + await pool.advanceTime(1) + await snapshotGasCost(swapExact1For0(1000, wallet.address)); + }); + + it('first swap in block with no tick movement, with transfer', async () => { + await snapshotGasCost(swapExact1For0(10000, wallet.address)); + }); + + it('first swap in block moves tick, no initialized crossings, with transfer', async () => { + await swapExact1For0(1000, wallet.address); + await pool.advanceTime(86400) + await snapshotGasCost(swapExact1For0(expandTo18Decimals(1) / 10000n, wallet.address)); + }); + + }) + describe('#swapExact0For1', () => { it('first swap in block with no tick movement', async () => { await snapshotGasCost(swapExact0For1(2000, wallet.address)); diff --git a/src/core/test/AlgebraPool.spec.ts b/src/core/test/AlgebraPool.spec.ts index 0526c7c3..31f0f192 100644 --- a/src/core/test/AlgebraPool.spec.ts +++ b/src/core/test/AlgebraPool.spec.ts @@ -2430,7 +2430,7 @@ describe('AlgebraPool', () => { }); }); - describe.only('#pluginFee', () => { + describe('#pluginFee', () => { let poolPlugin : MockPoolPlugin; beforeEach('initialize the pool', async () => { @@ -2513,7 +2513,6 @@ describe('AlgebraPool', () => { expect(pluginBalance1After - pluginBalance1Before).to.be.eq(0); }) - it('works correct with communityFee', async () => { await poolPlugin.setPluginFees(1000, 4000); await pool.setCommunityFee(500); diff --git a/src/core/test/__snapshots__/AlgebraFactory.spec.ts.snap b/src/core/test/__snapshots__/AlgebraFactory.spec.ts.snap index 6a713244..b6088c8f 100644 --- a/src/core/test/__snapshots__/AlgebraFactory.spec.ts.snap +++ b/src/core/test/__snapshots__/AlgebraFactory.spec.ts.snap @@ -1,13 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`AlgebraFactory #createCustomPool gas [ @skip-on-coverage ] 1`] = `4796400`; +exports[`AlgebraFactory #createCustomPool gas [ @skip-on-coverage ] 1`] = `4802891`; -exports[`AlgebraFactory #createCustomPool gas for second pool [ @skip-on-coverage ] 1`] = `4796400`; +exports[`AlgebraFactory #createCustomPool gas for second pool [ @skip-on-coverage ] 1`] = `4802891`; -exports[`AlgebraFactory #createPool gas [ @skip-on-coverage ] 1`] = `4784203`; +exports[`AlgebraFactory #createPool gas [ @skip-on-coverage ] 1`] = `4790694`; -exports[`AlgebraFactory #createPool gas for second pool [ @skip-on-coverage ] 1`] = `4784203`; +exports[`AlgebraFactory #createPool gas for second pool [ @skip-on-coverage ] 1`] = `4790694`; exports[`AlgebraFactory factory bytecode size [ @skip-on-coverage ] 1`] = `10699`; -exports[`AlgebraFactory pool bytecode size [ @skip-on-coverage ] 1`] = `22658`; +exports[`AlgebraFactory pool bytecode size [ @skip-on-coverage ] 1`] = `22687`; diff --git a/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap b/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap index 23776de6..56716539 100644 --- a/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap +++ b/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap @@ -58,39 +58,45 @@ exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #mint below curr exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #poke best case 1`] = `63735`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block moves tick, no initialized crossings 1`] = `103318`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block moves tick, no initialized crossings 1`] = `103487`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block with no tick movement 1`] = `103287`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block with no tick movement 1`] = `103456`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block, large swap crossing a single initialized tick 1`] = `119063`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block, large swap crossing a single initialized tick 1`] = `119232`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block, large swap crossing several initialized ticks 1`] = `152577`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block, large swap crossing several initialized ticks 1`] = `152746`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block, large swap, no initialized crossings 1`] = `103456`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block, large swap, no initialized crossings 1`] = `103625`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 large swap crossing several initialized ticks after some time passes 1`] = `152577`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 large swap crossing several initialized ticks after some time passes 1`] = `152746`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 large swap crossing several initialized ticks second time after some time passes 1`] = `171777`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 large swap crossing several initialized ticks second time after some time passes 1`] = `171946`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block moves tick, no initialized crossings 1`] = `103318`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block moves tick, no initialized crossings 1`] = `103487`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block with no tick movement 1`] = `103282`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block with no tick movement 1`] = `103451`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block, large swap crossing a single initialized tick 1`] = `119887`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block, large swap crossing a single initialized tick 1`] = `120056`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block, large swap crossing several initialized ticks 1`] = `153428`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block, large swap crossing several initialized ticks 1`] = `153597`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 several large swaps with pauses 1`] = `171777`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 several large swaps with pauses 1`] = `171946`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 small swap after several large swaps with pauses 1`] = `103156`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 small swap after several large swaps with pauses 1`] = `103325`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 small swap with filled dataStorage 1`] = `103152`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 small swap with filled dataStorage 1`] = `103321`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 first swap in block moves tick, no initialized crossings 1`] = `103379`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 first swap in block moves tick, no initialized crossings 1`] = `103548`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 first swap in block with no tick movement 1`] = `103327`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 first swap in block with no tick movement 1`] = `103496`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 second swap in block with no tick movement 1`] = `103343`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 second swap in block with no tick movement 1`] = `103512`; + +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `141761`; + +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `175909`; + +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block with no tick movement, without transfer 1`] = `148849`; exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #burn above current price burn entire position after some time passes 1`] = `117084`; @@ -146,36 +152,42 @@ exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #mint below curre exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #poke best case 1`] = `63735`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block moves tick, no initialized crossings 1`] = `113817`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block moves tick, no initialized crossings 1`] = `114074`; + +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block with no tick movement 1`] = `103693`; + +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap crossing a single initialized tick 1`] = `130056`; + +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap crossing several initialized ticks 1`] = `164281`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block with no tick movement 1`] = `103524`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap, no initialized crossings 1`] = `114212`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap crossing a single initialized tick 1`] = `129799`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 large swap crossing several initialized ticks after some time passes 1`] = `164281`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap crossing several initialized ticks 1`] = `164024`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 large swap crossing several initialized ticks second time after some time passes 1`] = `183481`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap, no initialized crossings 1`] = `113955`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block moves tick, no initialized crossings 1`] = `114074`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 large swap crossing several initialized ticks after some time passes 1`] = `164024`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block with no tick movement 1`] = `103688`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 large swap crossing several initialized ticks second time after some time passes 1`] = `183224`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block, large swap crossing a single initialized tick 1`] = `130880`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block moves tick, no initialized crossings 1`] = `113817`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block, large swap crossing several initialized ticks 1`] = `165132`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block with no tick movement 1`] = `103519`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 several large swaps with pauses 1`] = `183481`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block, large swap crossing a single initialized tick 1`] = `130623`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 small swap after several large swaps with pauses 1`] = `103562`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block, large swap crossing several initialized ticks 1`] = `164875`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 small swap with filled dataStorage 1`] = `103558`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 several large swaps with pauses 1`] = `183224`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 first swap in block moves tick, no initialized crossings 1`] = `114146`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 small swap after several large swaps with pauses 1`] = `103393`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 first swap in block with no tick movement 1`] = `103733`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 small swap with filled dataStorage 1`] = `103389`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 second swap in block with no tick movement 1`] = `103749`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 first swap in block moves tick, no initialized crossings 1`] = `113889`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `185944`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 first swap in block with no tick movement 1`] = `103564`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `149086`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 second swap in block with no tick movement 1`] = `103580`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, without transfer 1`] = `131986`; From fccb22b04b051c49856ededdf4b81943a40db602 Mon Sep 17 00:00:00 2001 From: debych Date: Thu, 5 Sep 2024 18:17:24 +0300 Subject: [PATCH 07/11] [Core] Optimisations --- src/core/contracts/AlgebraFactory.sol | 2 +- src/core/contracts/AlgebraPool.sol | 2 +- src/core/contracts/base/SwapCalculation.sol | 7 +- .../__snapshots__/AlgebraFactory.spec.ts.snap | 10 +-- .../AlgebraPool.gas.spec.ts.snap | 80 +++++++++---------- .../contracts/libraries/PoolAddress.sol | 2 +- 6 files changed, 53 insertions(+), 50 deletions(-) diff --git a/src/core/contracts/AlgebraFactory.sol b/src/core/contracts/AlgebraFactory.sol index 7c99afbe..4731231b 100644 --- a/src/core/contracts/AlgebraFactory.sol +++ b/src/core/contracts/AlgebraFactory.sol @@ -57,7 +57,7 @@ contract AlgebraFactory is IAlgebraFactory, Ownable2Step, AccessControlEnumerabl /// @inheritdoc IAlgebraFactory /// @dev keccak256 of AlgebraPool init bytecode. Used to compute pool address deterministically - bytes32 public constant POOL_INIT_CODE_HASH = 0x95cae1693e5a3bc78f48679682e43b3ce024da4362d51eccdac32de2ccaba0ba; + bytes32 public constant POOL_INIT_CODE_HASH = 0x0dafac8587f1d8bb6a31389a83c5066ab6ac14bc257709e735d9c5a256839885; constructor(address _poolDeployer) { require(_poolDeployer != address(0)); diff --git a/src/core/contracts/AlgebraPool.sol b/src/core/contracts/AlgebraPool.sol index 18cdfa1e..9a3de794 100644 --- a/src/core/contracts/AlgebraPool.sol +++ b/src/core/contracts/AlgebraPool.sol @@ -373,7 +373,7 @@ contract AlgebraPool is AlgebraPoolBase, TickStructure, ReentrancyGuard, Positio if (_isPlugin()) return (0, 0); bytes4 selector; (selector, overrideFee, pluginFee) = IAlgebraPlugin(plugin).beforeSwap(msg.sender, recipient, zto, amount, limitPrice, payInAdvance, data); - if ((overrideFee + pluginFee) >= 1e6) revert incorrectPluginFee(); + // we will check that fee is less than denominator inside the swap calculation selector.shouldReturn(IAlgebraPlugin.beforeSwap.selector); } } diff --git a/src/core/contracts/base/SwapCalculation.sol b/src/core/contracts/base/SwapCalculation.sol index f00fb196..91dab597 100644 --- a/src/core/contracts/base/SwapCalculation.sol +++ b/src/core/contracts/base/SwapCalculation.sol @@ -62,10 +62,13 @@ abstract contract SwapCalculation is AlgebraPoolBase { if (currentPrice == 0) revert notInitialized(); if (overrideFee != 0) { cache.fee = overrideFee + pluginFee; + if (cache.fee >= 1e6) revert incorrectPluginFee(); } else { - cache.fee += pluginFee; + if (pluginFee != 0) { + cache.fee += pluginFee; + if (cache.fee >= 1e6) revert incorrectPluginFee(); + } } - if (cache.fee >= 1e6) revert incorrectPluginFee(); if (zeroToOne) { if (limitSqrtPrice >= currentPrice || limitSqrtPrice <= TickMath.MIN_SQRT_RATIO) revert invalidLimitSqrtPrice(); diff --git a/src/core/test/__snapshots__/AlgebraFactory.spec.ts.snap b/src/core/test/__snapshots__/AlgebraFactory.spec.ts.snap index b6088c8f..66626d6f 100644 --- a/src/core/test/__snapshots__/AlgebraFactory.spec.ts.snap +++ b/src/core/test/__snapshots__/AlgebraFactory.spec.ts.snap @@ -1,13 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`AlgebraFactory #createCustomPool gas [ @skip-on-coverage ] 1`] = `4802891`; +exports[`AlgebraFactory #createCustomPool gas [ @skip-on-coverage ] 1`] = `4802491`; -exports[`AlgebraFactory #createCustomPool gas for second pool [ @skip-on-coverage ] 1`] = `4802891`; +exports[`AlgebraFactory #createCustomPool gas for second pool [ @skip-on-coverage ] 1`] = `4802491`; -exports[`AlgebraFactory #createPool gas [ @skip-on-coverage ] 1`] = `4790694`; +exports[`AlgebraFactory #createPool gas [ @skip-on-coverage ] 1`] = `4790294`; -exports[`AlgebraFactory #createPool gas for second pool [ @skip-on-coverage ] 1`] = `4790694`; +exports[`AlgebraFactory #createPool gas for second pool [ @skip-on-coverage ] 1`] = `4790294`; exports[`AlgebraFactory factory bytecode size [ @skip-on-coverage ] 1`] = `10699`; -exports[`AlgebraFactory pool bytecode size [ @skip-on-coverage ] 1`] = `22687`; +exports[`AlgebraFactory pool bytecode size [ @skip-on-coverage ] 1`] = `22685`; diff --git a/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap b/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap index 56716539..66b15c58 100644 --- a/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap +++ b/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap @@ -58,45 +58,45 @@ exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #mint below curr exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #poke best case 1`] = `63735`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block moves tick, no initialized crossings 1`] = `103487`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block moves tick, no initialized crossings 1`] = `103344`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block with no tick movement 1`] = `103456`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block with no tick movement 1`] = `103313`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block, large swap crossing a single initialized tick 1`] = `119232`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block, large swap crossing a single initialized tick 1`] = `119089`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block, large swap crossing several initialized ticks 1`] = `152746`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block, large swap crossing several initialized ticks 1`] = `152603`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block, large swap, no initialized crossings 1`] = `103625`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 first swap in block, large swap, no initialized crossings 1`] = `103482`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 large swap crossing several initialized ticks after some time passes 1`] = `152746`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 large swap crossing several initialized ticks after some time passes 1`] = `152603`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 large swap crossing several initialized ticks second time after some time passes 1`] = `171946`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 large swap crossing several initialized ticks second time after some time passes 1`] = `171803`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block moves tick, no initialized crossings 1`] = `103487`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block moves tick, no initialized crossings 1`] = `103344`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block with no tick movement 1`] = `103451`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block with no tick movement 1`] = `103308`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block, large swap crossing a single initialized tick 1`] = `120056`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block, large swap crossing a single initialized tick 1`] = `119913`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block, large swap crossing several initialized ticks 1`] = `153597`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 second swap in block, large swap crossing several initialized ticks 1`] = `153454`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 several large swaps with pauses 1`] = `171946`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 several large swaps with pauses 1`] = `171803`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 small swap after several large swaps with pauses 1`] = `103325`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 small swap after several large swaps with pauses 1`] = `103182`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 small swap with filled dataStorage 1`] = `103321`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact0For1 small swap with filled dataStorage 1`] = `103178`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 first swap in block moves tick, no initialized crossings 1`] = `103548`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 first swap in block moves tick, no initialized crossings 1`] = `103405`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 first swap in block with no tick movement 1`] = `103496`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 first swap in block with no tick movement 1`] = `103353`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 second swap in block with no tick movement 1`] = `103512`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 second swap in block with no tick movement 1`] = `103369`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `141761`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `141676`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `175909`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `175824`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block with no tick movement, without transfer 1`] = `148849`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block with no tick movement, without transfer 1`] = `148764`; exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #burn above current price burn entire position after some time passes 1`] = `117084`; @@ -152,42 +152,42 @@ exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #mint below curre exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #poke best case 1`] = `63735`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block moves tick, no initialized crossings 1`] = `114074`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block moves tick, no initialized crossings 1`] = `113931`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block with no tick movement 1`] = `103693`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block with no tick movement 1`] = `103550`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap crossing a single initialized tick 1`] = `130056`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap crossing a single initialized tick 1`] = `129913`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap crossing several initialized ticks 1`] = `164281`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap crossing several initialized ticks 1`] = `164138`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap, no initialized crossings 1`] = `114212`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap, no initialized crossings 1`] = `114069`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 large swap crossing several initialized ticks after some time passes 1`] = `164281`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 large swap crossing several initialized ticks after some time passes 1`] = `164138`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 large swap crossing several initialized ticks second time after some time passes 1`] = `183481`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 large swap crossing several initialized ticks second time after some time passes 1`] = `183338`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block moves tick, no initialized crossings 1`] = `114074`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block moves tick, no initialized crossings 1`] = `113931`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block with no tick movement 1`] = `103688`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block with no tick movement 1`] = `103545`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block, large swap crossing a single initialized tick 1`] = `130880`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block, large swap crossing a single initialized tick 1`] = `130737`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block, large swap crossing several initialized ticks 1`] = `165132`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block, large swap crossing several initialized ticks 1`] = `164989`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 several large swaps with pauses 1`] = `183481`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 several large swaps with pauses 1`] = `183338`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 small swap after several large swaps with pauses 1`] = `103562`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 small swap after several large swaps with pauses 1`] = `103419`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 small swap with filled dataStorage 1`] = `103558`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 small swap with filled dataStorage 1`] = `103415`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 first swap in block moves tick, no initialized crossings 1`] = `114146`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 first swap in block moves tick, no initialized crossings 1`] = `114003`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 first swap in block with no tick movement 1`] = `103733`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 first swap in block with no tick movement 1`] = `103590`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 second swap in block with no tick movement 1`] = `103749`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 second swap in block with no tick movement 1`] = `103606`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `185944`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `185859`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `149086`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `149001`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, without transfer 1`] = `131986`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, without transfer 1`] = `131901`; diff --git a/src/periphery/contracts/libraries/PoolAddress.sol b/src/periphery/contracts/libraries/PoolAddress.sol index f991d857..894215c5 100644 --- a/src/periphery/contracts/libraries/PoolAddress.sol +++ b/src/periphery/contracts/libraries/PoolAddress.sol @@ -5,7 +5,7 @@ pragma solidity >=0.5.0; /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery library PoolAddress { - bytes32 internal constant POOL_INIT_CODE_HASH = 0x95cae1693e5a3bc78f48679682e43b3ce024da4362d51eccdac32de2ccaba0ba; + bytes32 internal constant POOL_INIT_CODE_HASH = 0x0dafac8587f1d8bb6a31389a83c5066ab6ac14bc257709e735d9c5a256839885; /// @notice The identifying key of the pool struct PoolKey { From 257e0b1ea720d98e299fe5d9e39f71e4c25cf8f6 Mon Sep 17 00:00:00 2001 From: debych Date: Thu, 5 Sep 2024 21:27:20 +0300 Subject: [PATCH 08/11] [Core] Fix test with no tick movement --- src/core/contracts/AlgebraFactory.sol | 2 +- src/core/test/AlgebraPool.gas.spec.ts | 6 +++--- src/periphery/contracts/libraries/PoolAddress.sol | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/contracts/AlgebraFactory.sol b/src/core/contracts/AlgebraFactory.sol index 4731231b..a50d922a 100644 --- a/src/core/contracts/AlgebraFactory.sol +++ b/src/core/contracts/AlgebraFactory.sol @@ -57,7 +57,7 @@ contract AlgebraFactory is IAlgebraFactory, Ownable2Step, AccessControlEnumerabl /// @inheritdoc IAlgebraFactory /// @dev keccak256 of AlgebraPool init bytecode. Used to compute pool address deterministically - bytes32 public constant POOL_INIT_CODE_HASH = 0x0dafac8587f1d8bb6a31389a83c5066ab6ac14bc257709e735d9c5a256839885; + bytes32 public constant POOL_INIT_CODE_HASH = 0x8fd873dd382d0ec6661164092e11d9b512eecf61c83826aa564a953b49710e0b; constructor(address _poolDeployer) { require(_poolDeployer != address(0)); diff --git a/src/core/test/AlgebraPool.gas.spec.ts b/src/core/test/AlgebraPool.gas.spec.ts index 0f2e46f3..9863a187 100644 --- a/src/core/test/AlgebraPool.gas.spec.ts +++ b/src/core/test/AlgebraPool.gas.spec.ts @@ -47,7 +47,7 @@ describe('AlgebraPool gas tests [ @skip-on-coverage ]', () => { }); }); - for (const communityFee of [0, 60]) { + for (const communityFee of [0, 500]) { describe(communityFee > 0 ? 'fee is on' : 'fee is off', () => { const startingPrice = encodePriceSqrt(100001, 100000); const startingTick = 0; @@ -104,7 +104,7 @@ describe('AlgebraPool gas tests [ @skip-on-coverage ]', () => { describe('#swapExact1For0', () => { it('first swap in block with no tick movement', async () => { - await snapshotGasCost(swapExact1For0(2000, wallet.address)); + await snapshotGasCost(swapExact1For0(4000, wallet.address)); expect((await pool.globalState()).price).to.not.eq(startingPrice); expect((await pool.globalState()).tick).to.eq(startingTick); }); @@ -152,7 +152,7 @@ describe('AlgebraPool gas tests [ @skip-on-coverage ]', () => { describe('#swapExact0For1', () => { it('first swap in block with no tick movement', async () => { - await snapshotGasCost(swapExact0For1(2000, wallet.address)); + await snapshotGasCost(swapExact0For1(4000, wallet.address)); expect((await pool.globalState()).price).to.not.eq(startingPrice); expect((await pool.globalState()).tick).to.eq(startingTick); }); diff --git a/src/periphery/contracts/libraries/PoolAddress.sol b/src/periphery/contracts/libraries/PoolAddress.sol index 894215c5..e8f68f5c 100644 --- a/src/periphery/contracts/libraries/PoolAddress.sol +++ b/src/periphery/contracts/libraries/PoolAddress.sol @@ -5,7 +5,7 @@ pragma solidity >=0.5.0; /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery library PoolAddress { - bytes32 internal constant POOL_INIT_CODE_HASH = 0x0dafac8587f1d8bb6a31389a83c5066ab6ac14bc257709e735d9c5a256839885; + bytes32 internal constant POOL_INIT_CODE_HASH = 0x8fd873dd382d0ec6661164092e11d9b512eecf61c83826aa564a953b49710e0b; /// @notice The identifying key of the pool struct PoolKey { From 9d92a0f042a0d5dbb643c38af64dcf3de9e94570 Mon Sep 17 00:00:00 2001 From: debych Date: Thu, 5 Sep 2024 21:40:07 +0300 Subject: [PATCH 09/11] [Core] Rework changeReserves --- src/core/contracts/AlgebraFactory.sol | 2 +- src/core/contracts/base/ReservesManager.sol | 181 +++++++++++------- .../interfaces/pool/IAlgebraPoolErrors.sol | 3 - src/core/test/AlgebraPool.spec.ts | 5 +- .../__snapshots__/AlgebraFactory.spec.ts.snap | 10 +- .../AlgebraPool.gas.spec.ts.snap | 38 ++-- .../contracts/libraries/PoolAddress.sol | 2 +- 7 files changed, 145 insertions(+), 96 deletions(-) diff --git a/src/core/contracts/AlgebraFactory.sol b/src/core/contracts/AlgebraFactory.sol index a50d922a..ea7b77b6 100644 --- a/src/core/contracts/AlgebraFactory.sol +++ b/src/core/contracts/AlgebraFactory.sol @@ -57,7 +57,7 @@ contract AlgebraFactory is IAlgebraFactory, Ownable2Step, AccessControlEnumerabl /// @inheritdoc IAlgebraFactory /// @dev keccak256 of AlgebraPool init bytecode. Used to compute pool address deterministically - bytes32 public constant POOL_INIT_CODE_HASH = 0x8fd873dd382d0ec6661164092e11d9b512eecf61c83826aa564a953b49710e0b; + bytes32 public constant POOL_INIT_CODE_HASH = 0x3093a65c28d1e6def42997fdea76d033dfd42b432c107e19412cf91a1eac0f91; constructor(address _poolDeployer) { require(_poolDeployer != address(0)); diff --git a/src/core/contracts/base/ReservesManager.sol b/src/core/contracts/base/ReservesManager.sol index d1aa3dc1..7a65c496 100644 --- a/src/core/contracts/base/ReservesManager.sol +++ b/src/core/contracts/base/ReservesManager.sol @@ -2,6 +2,7 @@ pragma solidity =0.8.20; import '../libraries/SafeCast.sol'; +import '../libraries/Plugins.sol'; import './AlgebraPoolBase.sol'; import '../interfaces/plugin/IAlgebraPlugin.sol'; import '../interfaces/pool/IAlgebraPoolErrors.sol'; @@ -9,6 +10,7 @@ import '../interfaces/pool/IAlgebraPoolErrors.sol'; /// @notice Encapsulates logic for tracking and changing pool reserves /// @dev The reserve mechanism allows the pool to keep track of unexpected increases in balances abstract contract ReservesManager is AlgebraPoolBase { + using Plugins for bytes4; using SafeCast for uint256; /// @dev The tracked token0 and token1 reserves of pool @@ -67,46 +69,85 @@ abstract contract ReservesManager is AlgebraPoolBase { } } + /// @notice Accrues fees and transfers them to `recipient` + /// @dev If we transfer fees, writes zeros to the storage slot specified by the slot argument + /// If we do not transfer fees, returns actual pendingFees function _accrueAndTransferFees( uint256 fee0, uint256 fee1, uint256 lastTimestamp, - address recipient, - bytes32 slot - ) internal returns (uint256, uint256, uint256, uint256) { - uint256 feePending0; - uint256 feePending1; - - assembly { - // Load the storage slot specified by the slot argument - let sl := sload(slot) - - // Extract the uint104 value - feePending0 := and(sl, 0xFFFFFFFFFFFFFFFFFFFFFFFFFF) - - // Shift right by 104 bits and extract the uint104 value - feePending1 := and(shr(104, sl), 0xFFFFFFFFFFFFFFFFFFFFFFFFFF) - } - - feePending0 += fee0; - feePending1 += fee1; - - if (_blockTimestamp() - lastTimestamp >= Constants.FEE_TRANSFER_FREQUENCY || feePending0 > type(uint104).max || feePending1 > type(uint104).max) { - (uint256 feeSent0, uint256 feeSent1) = _transferFees(feePending0, feePending1, recipient); + bytes32 receiverSlot, + bytes32 feePendingSlot + ) internal returns (uint104, uint104, uint256, uint256) { + if (fee0 | fee1 != 0) { + uint256 feePending0; + uint256 feePending1; assembly { - sstore(slot, 0) + // Load the storage slot specified by the slot argument + let sl := sload(feePendingSlot) + // Extract the uint104 value + feePending0 := and(sl, 0xFFFFFFFFFFFFFFFFFFFFFFFFFF) + // Shift right by 104 bits and extract the uint104 value + feePending1 := and(shr(104, sl), 0xFFFFFFFFFFFFFFFFFFFFFFFFFF) + } + feePending0 += fee0; + feePending1 += fee1; + + if ( + _blockTimestamp() - lastTimestamp >= Constants.FEE_TRANSFER_FREQUENCY || feePending0 > type(uint104).max || feePending1 > type(uint104).max + ) { + // use sload from slot (like pointer dereference) to avoid gas + address recipient; + assembly { + recipient := sload(receiverSlot) + } + (uint256 feeSent0, uint256 feeSent1) = _transferFees(feePending0, feePending1, recipient); + // use sload from slot (like pointer dereference) to avoid gas + // override `lastFeeTransferTimestamp` with zeros is OK + // because we will update it later + assembly { + sstore(feePendingSlot, 0) + } + // sent fees return 0 pending and sent fees + return (0, 0, feeSent0, feeSent1); + } else { + // didn't send fees return pending fees and 0 sent + return (uint104(feePending0), uint104(feePending1), 0, 0); } - return (0, 0, feeSent0, feeSent1); } else { - return (feePending0, feePending1, 0, 0); + if (_blockTimestamp() - lastTimestamp >= Constants.FEE_TRANSFER_FREQUENCY) { + uint256 feePending0; + uint256 feePending1; + assembly { + // Load the storage slot specified by the slot argument + let sl := sload(feePendingSlot) + // Extract the uint104 value + feePending0 := and(sl, 0xFFFFFFFFFFFFFFFFFFFFFFFFFF) + // Shift right by 104 bits and extract the uint104 value + feePending1 := and(shr(104, sl), 0xFFFFFFFFFFFFFFFFFFFFFFFFFF) + } + + if (feePending0 | feePending1 != 0) { + address recipient; + // use sload from slot (like pointer dereference) to avoid gas + assembly { + recipient := sload(receiverSlot) + } + (uint256 feeSent0, uint256 feeSent1) = _transferFees(feePending0, feePending1, recipient); + // use sload from slot (like pointer dereference) to avoid gas + assembly { + sstore(feePendingSlot, 0) + } + // sent fees return 0 pending and sent fees + return (0, 0, feeSent0, feeSent1); + } + } + // didn't either sent fees or increased pending + return (0, 0, 0, 0); } } - function _transferFees( - uint256 feePending0, - uint256 feePending1, - address feesRecipient - ) private returns (uint256, uint256) { + function _transferFees(uint256 feePending0, uint256 feePending1, address feesRecipient) private returns (uint256, uint256) { uint256 feeSent0; uint256 feeSent1; @@ -137,49 +178,57 @@ abstract contract ReservesManager is AlgebraPoolBase { uint256 pluginFee1 ) internal { if (communityFee0 > 0 || communityFee1 > 0 || pluginFee0 > 0 || pluginFee1 > 0) { - bytes32 slot; + bytes32 feePendingSlot; + bytes32 feeRecipientSlot; uint32 lastTimestamp = lastFeeTransferTimestamp; - uint32 currentTimestamp = _blockTimestamp(); bool feeSent; - if (communityFee0 | communityFee1 != 0) { - assembly { - slot := communityFeePending0.slot - } - (uint256 feePending0, uint256 feePending1, uint256 feeSent0, uint256 feeSent1) = _accrueAndTransferFees(communityFee0, communityFee1, lastTimestamp, communityVault, slot); - if (feeSent0 | feeSent1 != 0) { - (deltaR0, deltaR1) = (deltaR0 - feeSent0.toInt256(), deltaR1 - feeSent1.toInt256()); - feeSent = true; - } else { - (communityFeePending0, communityFeePending1) = (uint104(feePending0), uint104(feePending1)); - } + assembly { + feePendingSlot := communityFeePending0.slot + feeRecipientSlot := communityVault.slot + } + // pass feeRecipientSlot to avoid redundant sload of an address + (uint104 feePending0, uint104 feePending1, uint256 feeSent0, uint256 feeSent1) = _accrueAndTransferFees( + communityFee0, + communityFee1, + lastTimestamp, + feeRecipientSlot, + feePendingSlot + ); + if (feeSent0 | feeSent1 != 0) { + // sent fees so decrease deltas + (deltaR0, deltaR1) = (deltaR0 - feeSent0.toInt256(), deltaR1 - feeSent1.toInt256()); + feeSent = true; + } else { + // update pending if we accrued fees + if (feePending0 | feePending1 != 0) (communityFeePending0, communityFeePending1) = (feePending0, feePending1); } - if (pluginFee0 | pluginFee1 != 0) { - assembly { - slot := pluginFeePending0.slot - } - - (uint256 feePending0, uint256 feePending1, uint256 feeSent0, uint256 feeSent1) = _accrueAndTransferFees(pluginFee0, pluginFee1, lastTimestamp, plugin, slot); - if (feeSent0 | feeSent1 != 0) { - (deltaR0, deltaR1) = (deltaR0 - feeSent0.toInt256(), deltaR1 - feeSent1.toInt256()); - feeSent = true; - - if (IAlgebraPlugin(plugin).handlePluginFee(feeSent0, feeSent1) != IAlgebraPlugin.handlePluginFee.selector) revert IAlgebraPoolErrors.invalidPluginResponce(); - } else { - (pluginFeePending0, pluginFeePending1) = (uint104(feePending0), uint104(feePending1)); - } - } else if (feeSent) { - (uint256 feeSent0, uint256 feeSent1) = _transferFees(pluginFeePending0, pluginFeePending1, plugin); - if (feeSent0 | feeSent1 != 0) { - (pluginFeePending0, pluginFeePending1) = (0, 0); - (deltaR0, deltaR1) = (deltaR0 - feeSent0.toInt256(), deltaR1 - feeSent1.toInt256()); - - if (IAlgebraPlugin(plugin).handlePluginFee(feeSent0, feeSent1) != IAlgebraPlugin.handlePluginFee.selector) revert IAlgebraPoolErrors.invalidPluginResponce(); - } + assembly { + feePendingSlot := pluginFeePending0.slot + feeRecipientSlot := plugin.slot + } + // pass feeRecipientSlot to avoid redundant sload of an address + (feePending0, feePending1, feeSent0, feeSent1) = _accrueAndTransferFees( + pluginFee0, + pluginFee1, + lastTimestamp, + feeRecipientSlot, + feePendingSlot + ); + if (feeSent0 | feeSent1 != 0) { + // sent fees so decrease deltas + (deltaR0, deltaR1) = (deltaR0 - feeSent0.toInt256(), deltaR1 - feeSent1.toInt256()); + feeSent = true; + + // notify plugin about sent fees + IAlgebraPlugin(plugin).handlePluginFee(feeSent0, feeSent1).shouldReturn(IAlgebraPlugin.handlePluginFee.selector); + } else { + // update pending if we accrued fees + if (feePending0 | feePending1 != 0) (pluginFeePending0, pluginFeePending1) = (feePending0, feePending1); } - if (feeSent) lastFeeTransferTimestamp = currentTimestamp; + if (feeSent) lastFeeTransferTimestamp = _blockTimestamp(); } if (deltaR0 | deltaR1 == 0) return; diff --git a/src/core/contracts/interfaces/pool/IAlgebraPoolErrors.sol b/src/core/contracts/interfaces/pool/IAlgebraPoolErrors.sol index d91bf4d1..f3a88582 100644 --- a/src/core/contracts/interfaces/pool/IAlgebraPoolErrors.sol +++ b/src/core/contracts/interfaces/pool/IAlgebraPoolErrors.sol @@ -28,9 +28,6 @@ interface IAlgebraPoolErrors { /// @notice Emitted if plugin fee param greater than fee/override fee error incorrectPluginFee(); - /// @notice Emitted if a plugin returns invalid selector after pluginFeeHandle call - error invalidPluginResponce(); - /// @notice Emitted if the pool received fewer tokens than it should have error insufficientInputAmount(); diff --git a/src/core/test/AlgebraPool.spec.ts b/src/core/test/AlgebraPool.spec.ts index 31f0f192..a950e68d 100644 --- a/src/core/test/AlgebraPool.spec.ts +++ b/src/core/test/AlgebraPool.spec.ts @@ -2460,7 +2460,10 @@ describe('AlgebraPool', () => { it('swap fails if plugin return incorrect selector', async () => { await poolPlugin.disablePluginFeeHandle(); await poolPlugin.setPluginFees(5000, 4000); - await expect(swapExact0For1(expandTo18Decimals(1), wallet.address)).to.be.revertedWithCustomError(pool, 'invalidPluginResponce') ; + const selector = poolPlugin.interface.getFunction('handlePluginFee').selector; + + await expect(swapExact0For1(expandTo18Decimals(1), wallet.address)). + to.be.revertedWithCustomError(pool, 'invalidHookResponse').withArgs(selector); }) it('works correct on swap', async () => { diff --git a/src/core/test/__snapshots__/AlgebraFactory.spec.ts.snap b/src/core/test/__snapshots__/AlgebraFactory.spec.ts.snap index 66626d6f..5facdf49 100644 --- a/src/core/test/__snapshots__/AlgebraFactory.spec.ts.snap +++ b/src/core/test/__snapshots__/AlgebraFactory.spec.ts.snap @@ -1,13 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`AlgebraFactory #createCustomPool gas [ @skip-on-coverage ] 1`] = `4802491`; +exports[`AlgebraFactory #createCustomPool gas [ @skip-on-coverage ] 1`] = `4745061`; -exports[`AlgebraFactory #createCustomPool gas for second pool [ @skip-on-coverage ] 1`] = `4802491`; +exports[`AlgebraFactory #createCustomPool gas for second pool [ @skip-on-coverage ] 1`] = `4745061`; -exports[`AlgebraFactory #createPool gas [ @skip-on-coverage ] 1`] = `4790294`; +exports[`AlgebraFactory #createPool gas [ @skip-on-coverage ] 1`] = `4732864`; -exports[`AlgebraFactory #createPool gas for second pool [ @skip-on-coverage ] 1`] = `4790294`; +exports[`AlgebraFactory #createPool gas for second pool [ @skip-on-coverage ] 1`] = `4732864`; exports[`AlgebraFactory factory bytecode size [ @skip-on-coverage ] 1`] = `10699`; -exports[`AlgebraFactory pool bytecode size [ @skip-on-coverage ] 1`] = `22685`; +exports[`AlgebraFactory pool bytecode size [ @skip-on-coverage ] 1`] = `22399`; diff --git a/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap b/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap index 66b15c58..625afec5 100644 --- a/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap +++ b/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap @@ -92,11 +92,11 @@ exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 second swap in block with no tick movement 1`] = `103369`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `141676`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `142275`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `175824`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `176423`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block with no tick movement, without transfer 1`] = `148764`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block with no tick movement, without transfer 1`] = `148985`; exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #burn above current price burn entire position after some time passes 1`] = `117084`; @@ -152,42 +152,42 @@ exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #mint below curre exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #poke best case 1`] = `63735`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block moves tick, no initialized crossings 1`] = `113931`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block moves tick, no initialized crossings 1`] = `112143`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block with no tick movement 1`] = `103550`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block with no tick movement 1`] = `112112`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap crossing a single initialized tick 1`] = `129913`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap crossing a single initialized tick 1`] = `128125`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap crossing several initialized ticks 1`] = `164138`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap crossing several initialized ticks 1`] = `162350`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap, no initialized crossings 1`] = `114069`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 first swap in block, large swap, no initialized crossings 1`] = `112281`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 large swap crossing several initialized ticks after some time passes 1`] = `164138`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 large swap crossing several initialized ticks after some time passes 1`] = `162350`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 large swap crossing several initialized ticks second time after some time passes 1`] = `183338`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 large swap crossing several initialized ticks second time after some time passes 1`] = `181550`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block moves tick, no initialized crossings 1`] = `113931`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block moves tick, no initialized crossings 1`] = `112143`; exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block with no tick movement 1`] = `103545`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block, large swap crossing a single initialized tick 1`] = `130737`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block, large swap crossing a single initialized tick 1`] = `128949`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block, large swap crossing several initialized ticks 1`] = `164989`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 second swap in block, large swap crossing several initialized ticks 1`] = `163201`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 several large swaps with pauses 1`] = `183338`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 several large swaps with pauses 1`] = `181550`; exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 small swap after several large swaps with pauses 1`] = `103419`; exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact0For1 small swap with filled dataStorage 1`] = `103415`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 first swap in block moves tick, no initialized crossings 1`] = `114003`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 first swap in block moves tick, no initialized crossings 1`] = `112215`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 first swap in block with no tick movement 1`] = `103590`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 first swap in block with no tick movement 1`] = `112163`; exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 second swap in block with no tick movement 1`] = `103606`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `185859`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `185790`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `149001`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `152690`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, without transfer 1`] = `131901`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, without transfer 1`] = `132122`; diff --git a/src/periphery/contracts/libraries/PoolAddress.sol b/src/periphery/contracts/libraries/PoolAddress.sol index e8f68f5c..6696fa65 100644 --- a/src/periphery/contracts/libraries/PoolAddress.sol +++ b/src/periphery/contracts/libraries/PoolAddress.sol @@ -5,7 +5,7 @@ pragma solidity >=0.5.0; /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery library PoolAddress { - bytes32 internal constant POOL_INIT_CODE_HASH = 0x8fd873dd382d0ec6661164092e11d9b512eecf61c83826aa564a953b49710e0b; + bytes32 internal constant POOL_INIT_CODE_HASH = 0x3093a65c28d1e6def42997fdea76d033dfd42b432c107e19412cf91a1eac0f91; /// @notice The identifying key of the pool struct PoolKey { From 17c5046a16fc3ae5fef86126b4d9d88e4461eae5 Mon Sep 17 00:00:00 2001 From: IliaAzhel Date: Thu, 5 Sep 2024 22:47:06 +0300 Subject: [PATCH 10/11] [Core] fix plugin fee snapshots --- src/core/test/AlgebraPool.gas.spec.ts | 18 ++++++++++++------ .../__snapshots__/AlgebraPool.gas.spec.ts.snap | 8 ++++---- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/core/test/AlgebraPool.gas.spec.ts b/src/core/test/AlgebraPool.gas.spec.ts index 9863a187..c9d1135f 100644 --- a/src/core/test/AlgebraPool.gas.spec.ts +++ b/src/core/test/AlgebraPool.gas.spec.ts @@ -93,6 +93,7 @@ describe('AlgebraPool gas tests [ @skip-on-coverage ]', () => { let swapExact1For0: SwapFunction; let swapToHigherPrice: SwapToPriceFunction; let swapToLowerPrice: SwapToPriceFunction; + let poolPlugin: MockPoolPlugin; let pool: MockTimeAlgebraPool; let mint: MintFunction; @@ -123,31 +124,36 @@ describe('AlgebraPool gas tests [ @skip-on-coverage ]', () => { }) describe('#swapExact1For0 with plugin fee on', () => { - beforeEach('load the fixture', async () => { const MockPoolPluginFactory = await ethers.getContractFactory('MockPoolPlugin'); - let poolPlugin = (await MockPoolPluginFactory.deploy(await pool.getAddress())) as any as MockPoolPlugin; + poolPlugin = (await MockPoolPluginFactory.deploy(await pool.getAddress())) as any as MockPoolPlugin; await poolPlugin.setPluginFees(0, 1000); await pool.setPlugin(poolPlugin); await pool.setPluginConfig(255); }); it('first swap in block with no tick movement, without transfer', async () => { - await swapExact1For0(1000, wallet.address) + await swapExact1For0(10000, wallet.address) await pool.advanceTime(1) - await snapshotGasCost(swapExact1For0(1000, wallet.address)); + await snapshotGasCost(swapExact1For0(10000, wallet.address)); + expect((await pool.globalState()).price).to.not.eq(startingPrice); + expect((await pool.globalState()).tick).to.eq(startingTick); + expect((await pool.getPluginFeePending())[1]).to.be.gt(0) }); it('first swap in block with no tick movement, with transfer', async () => { + await pool.advanceTime(86400) await snapshotGasCost(swapExact1For0(10000, wallet.address)); + expect((await pool.globalState()).price).to.not.eq(startingPrice); + expect((await pool.globalState()).tick).to.eq(startingTick); }); it('first swap in block moves tick, no initialized crossings, with transfer', async () => { - await swapExact1For0(1000, wallet.address); await pool.advanceTime(86400) await snapshotGasCost(swapExact1For0(expandTo18Decimals(1) / 10000n, wallet.address)); + expect((await pool.getPluginFeePending())[1]).to.be.eq(0) + expect((await pool.globalState()).tick).to.eq(startingTick + 1); }); - }) describe('#swapExact0For1', () => { diff --git a/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap b/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap index 625afec5..71d3fbe6 100644 --- a/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap +++ b/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap @@ -92,7 +92,7 @@ exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 second swap in block with no tick movement 1`] = `103369`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `142275`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `176475`; exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `176423`; @@ -186,8 +186,8 @@ exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 f exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 second swap in block with no tick movement 1`] = `103606`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `185790`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `187790`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `152690`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `187738`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, without transfer 1`] = `132122`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, without transfer 1`] = `135590`; From fb345424f27a84ff24e14350f6b9e5303ad756e5 Mon Sep 17 00:00:00 2001 From: debych Date: Fri, 6 Sep 2024 21:02:49 +0300 Subject: [PATCH 11/11] [Core] Reset pending fees in plugin fee gas tests --- src/core/test/AlgebraPool.gas.spec.ts | 7 +++++++ .../test/__snapshots__/AlgebraPool.gas.spec.ts.snap | 10 +++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/core/test/AlgebraPool.gas.spec.ts b/src/core/test/AlgebraPool.gas.spec.ts index c9d1135f..ce2e2166 100644 --- a/src/core/test/AlgebraPool.gas.spec.ts +++ b/src/core/test/AlgebraPool.gas.spec.ts @@ -130,6 +130,13 @@ describe('AlgebraPool gas tests [ @skip-on-coverage ]', () => { await poolPlugin.setPluginFees(0, 1000); await pool.setPlugin(poolPlugin); await pool.setPluginConfig(255); + + await pool.advanceTime(86400); + await swapExact0For1(expandTo18Decimals(1), wallet.address); + await pool.advanceTime(1); + await swapToHigherPrice(startingPrice, wallet.address); + expect((await pool.globalState()).tick).to.eq(startingTick); + expect((await pool.globalState()).price).to.eq(startingPrice); }); it('first swap in block with no tick movement, without transfer', async () => { diff --git a/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap b/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap index 71d3fbe6..6c95b0ec 100644 --- a/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap +++ b/src/core/test/__snapshots__/AlgebraPool.gas.spec.ts.snap @@ -92,11 +92,11 @@ exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 second swap in block with no tick movement 1`] = `103369`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `176475`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `157375`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `176423`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `157323`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block with no tick movement, without transfer 1`] = `148985`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is off #swapExact1For0 with plugin fee on first swap in block with no tick movement, without transfer 1`] = `131885`; exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #burn above current price burn entire position after some time passes 1`] = `117084`; @@ -186,8 +186,8 @@ exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 f exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 second swap in block with no tick movement 1`] = `103606`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `187790`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block moves tick, no initialized crossings, with transfer 1`] = `168690`; -exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `187738`; +exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, with transfer 1`] = `168638`; exports[`AlgebraPool gas tests [ @skip-on-coverage ] fee is on #swapExact1For0 with plugin fee on first swap in block with no tick movement, without transfer 1`] = `135590`;