From b2770c73331bd68c251e36ca8b4c943cf9e7eb8c Mon Sep 17 00:00:00 2001 From: ChefMist <133624774+ChefMist@users.noreply.github.com> Date: Thu, 14 Nov 2024 14:54:26 +0800 Subject: [PATCH] feat: burn 1e3 shares for first mint into BinPool - part 2 (#215) * feat: example if we tweak add/remove bin to tree * feat: updated gas cost * feat: add test around getNextNonEmptyBin --- ...omCurveHookTest#test_Swap_CustomCurve.snap | 2 +- .../BinHookTest#testBurnSucceedsWithHook.snap | 2 +- .../BinHookTest#testMintSucceedsWithHook.snap | 2 +- .../BinMintBurnFeeHookTest#test_Burn.snap | 2 +- .../BinMintBurnFeeHookTest#test_Mint.snap | 2 +- .../BinPoolManagerBytecodeSize.snap | 2 +- ...oolManagerTest#testBurnNativeCurrency.snap | 2 +- ...BinPoolManagerTest#testGasBurnHalfBin.snap | 2 +- ...inPoolManagerTest#testGasBurnNineBins.snap | 2 +- .../BinPoolManagerTest#testGasBurnOneBin.snap | 2 +- ...nPoolManagerTest#testGasMintNneBins-1.snap | 2 +- ...nPoolManagerTest#testGasMintNneBins-2.snap | 2 +- ...inPoolManagerTest#testGasMintOneBin-1.snap | 2 +- ...inPoolManagerTest#testGasMintOneBin-2.snap | 2 +- ...oolManagerTest#testMintNativeCurrency.snap | 2 +- ..._exactOutputMultipleBin_WithEmptyBins.snap | 2 +- src/pool-bin/libraries/BinPool.sol | 6 +- test/pool-bin/BinPoolManager.t.sol | 63 +++++++++++++++++++ 18 files changed, 83 insertions(+), 18 deletions(-) diff --git a/.forge-snapshots/BinCustomCurveHookTest#test_Swap_CustomCurve.snap b/.forge-snapshots/BinCustomCurveHookTest#test_Swap_CustomCurve.snap index ae6f29d..6589b3a 100644 --- a/.forge-snapshots/BinCustomCurveHookTest#test_Swap_CustomCurve.snap +++ b/.forge-snapshots/BinCustomCurveHookTest#test_Swap_CustomCurve.snap @@ -1 +1 @@ -137654 \ No newline at end of file +142478 \ No newline at end of file diff --git a/.forge-snapshots/BinHookTest#testBurnSucceedsWithHook.snap b/.forge-snapshots/BinHookTest#testBurnSucceedsWithHook.snap index 4c3331e..5aa3913 100644 --- a/.forge-snapshots/BinHookTest#testBurnSucceedsWithHook.snap +++ b/.forge-snapshots/BinHookTest#testBurnSucceedsWithHook.snap @@ -1 +1 @@ -196277 \ No newline at end of file +197607 \ No newline at end of file diff --git a/.forge-snapshots/BinHookTest#testMintSucceedsWithHook.snap b/.forge-snapshots/BinHookTest#testMintSucceedsWithHook.snap index 74fcdec..25ba0cc 100644 --- a/.forge-snapshots/BinHookTest#testMintSucceedsWithHook.snap +++ b/.forge-snapshots/BinHookTest#testMintSucceedsWithHook.snap @@ -1 +1 @@ -311574 \ No newline at end of file +311580 \ No newline at end of file diff --git a/.forge-snapshots/BinMintBurnFeeHookTest#test_Burn.snap b/.forge-snapshots/BinMintBurnFeeHookTest#test_Burn.snap index 761cf5c..2c98c3a 100644 --- a/.forge-snapshots/BinMintBurnFeeHookTest#test_Burn.snap +++ b/.forge-snapshots/BinMintBurnFeeHookTest#test_Burn.snap @@ -1 +1 @@ -184559 \ No newline at end of file +185889 \ No newline at end of file diff --git a/.forge-snapshots/BinMintBurnFeeHookTest#test_Mint.snap b/.forge-snapshots/BinMintBurnFeeHookTest#test_Mint.snap index d4c2ddf..4dc6d49 100644 --- a/.forge-snapshots/BinMintBurnFeeHookTest#test_Mint.snap +++ b/.forge-snapshots/BinMintBurnFeeHookTest#test_Mint.snap @@ -1 +1 @@ -410526 \ No newline at end of file +410532 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerBytecodeSize.snap b/.forge-snapshots/BinPoolManagerBytecodeSize.snap index ac40ef4..bcdade9 100644 --- a/.forge-snapshots/BinPoolManagerBytecodeSize.snap +++ b/.forge-snapshots/BinPoolManagerBytecodeSize.snap @@ -1 +1 @@ -23389 \ No newline at end of file +23404 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testBurnNativeCurrency.snap b/.forge-snapshots/BinPoolManagerTest#testBurnNativeCurrency.snap index 7bdc9af..fec8e37 100644 --- a/.forge-snapshots/BinPoolManagerTest#testBurnNativeCurrency.snap +++ b/.forge-snapshots/BinPoolManagerTest#testBurnNativeCurrency.snap @@ -1 +1 @@ -146654 \ No newline at end of file +147984 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testGasBurnHalfBin.snap b/.forge-snapshots/BinPoolManagerTest#testGasBurnHalfBin.snap index c418fa6..69ae72a 100644 --- a/.forge-snapshots/BinPoolManagerTest#testGasBurnHalfBin.snap +++ b/.forge-snapshots/BinPoolManagerTest#testGasBurnHalfBin.snap @@ -1 +1 @@ -142933 \ No newline at end of file +142994 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testGasBurnNineBins.snap b/.forge-snapshots/BinPoolManagerTest#testGasBurnNineBins.snap index e4d185a..57e79e2 100644 --- a/.forge-snapshots/BinPoolManagerTest#testGasBurnNineBins.snap +++ b/.forge-snapshots/BinPoolManagerTest#testGasBurnNineBins.snap @@ -1 +1 @@ -287239 \ No newline at end of file +295835 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testGasBurnOneBin.snap b/.forge-snapshots/BinPoolManagerTest#testGasBurnOneBin.snap index 87e7d4f..0371d19 100644 --- a/.forge-snapshots/BinPoolManagerTest#testGasBurnOneBin.snap +++ b/.forge-snapshots/BinPoolManagerTest#testGasBurnOneBin.snap @@ -1 +1 @@ -138120 \ No newline at end of file +139450 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-1.snap b/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-1.snap index bafeff3..8c11043 100644 --- a/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-1.snap +++ b/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-1.snap @@ -1 +1 @@ -971323 \ No newline at end of file +971377 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-2.snap b/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-2.snap index 494e0e1..a9ae958 100644 --- a/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-2.snap +++ b/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-2.snap @@ -1 +1 @@ -330068 \ No newline at end of file +330122 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-1.snap b/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-1.snap index 48956a3..c4acf5a 100644 --- a/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-1.snap +++ b/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-1.snap @@ -1 +1 @@ -337831 \ No newline at end of file +337837 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-2.snap b/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-2.snap index 98d849b..192a1ba 100644 --- a/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-2.snap +++ b/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-2.snap @@ -1 +1 @@ -140319 \ No newline at end of file +140325 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testMintNativeCurrency.snap b/.forge-snapshots/BinPoolManagerTest#testMintNativeCurrency.snap index 488b3ff..a8e9432 100644 --- a/.forge-snapshots/BinPoolManagerTest#testMintNativeCurrency.snap +++ b/.forge-snapshots/BinPoolManagerTest#testMintNativeCurrency.snap @@ -1 +1 @@ -304870 \ No newline at end of file +304876 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolSwapTest#testGas_exactOutputMultipleBin_WithEmptyBins.snap b/.forge-snapshots/BinPoolSwapTest#testGas_exactOutputMultipleBin_WithEmptyBins.snap index f43e4db..63c4f90 100644 --- a/.forge-snapshots/BinPoolSwapTest#testGas_exactOutputMultipleBin_WithEmptyBins.snap +++ b/.forge-snapshots/BinPoolSwapTest#testGas_exactOutputMultipleBin_WithEmptyBins.snap @@ -1 +1 @@ -137102 \ No newline at end of file +109014 \ No newline at end of file diff --git a/src/pool-bin/libraries/BinPool.sol b/src/pool-bin/libraries/BinPool.sol index 02cfc90..cb89681 100644 --- a/src/pool-bin/libraries/BinPool.sol +++ b/src/pool-bin/libraries/BinPool.sol @@ -325,7 +325,8 @@ library BinPool { binReserves = binReserves.sub(amountsOutFromBin); - if (supply == amountToBurn) _removeBinIdToTree(self, id); + /// @dev _removeBinIdToTree if supply is MINIMUM_SHARE after burning as min share is too low liquidity for trade anyway + if (supply - amountToBurn == MINIMUM_SHARE) _removeBinIdToTree(self, id); self.reserveOfBin[id] = binReserves; amounts[i] = amountsOutFromBin; @@ -459,7 +460,8 @@ library BinPool { } if (shares == 0 || amountsInToBin == 0) revert BinPool__ZeroShares(id); - if (supply == 0) _addBinIdToTree(self, id); + /// @dev if supply was originally MINIMUM_SHARE (people added and remove liquidity before) or 0 (new bin), add binId to tree + if (supply <= MINIMUM_SHARE) _addBinIdToTree(self, id); self.reserveOfBin[id] = binReserves.add(amountsInToBin); } diff --git a/test/pool-bin/BinPoolManager.t.sol b/test/pool-bin/BinPoolManager.t.sol index 2e6419e..48897b4 100644 --- a/test/pool-bin/BinPoolManager.t.sol +++ b/test/pool-bin/BinPoolManager.t.sol @@ -1194,6 +1194,69 @@ contract BinPoolManagerTest is Test, GasSnapshot, BinTestHelper { assertEq(shares, liquidity); } + function test_getNextNonEmptyBin() public { + poolManager.initialize(key, activeId); + + // add 1 eth of tokenX and 1 eth to activeId - 2 to active + 2 bins + token0.mint(address(this), 10 ether); + token1.mint(address(this), 10 ether); + (IBinPoolManager.MintParams memory mintParams,) = _getMultipleBinMintParams(activeId, 2 ether, 2 ether, 3, 3); + binLiquidityHelper.mint(key, mintParams, ""); + + // swapForY is true, means search for bin to the left as tokenY reside on the left side of the bin + bool swapForY = true; + for (uint24 i = 0; i < 5; i++) { + // [-2, -1, activeId, 1, 2] are bins initialized due to liqudiity adding above + uint24 nextEmptyBin = poolManager.getNextNonEmptyBin(key.toId(), swapForY, activeId + 3 - i); + assertEq(nextEmptyBin, activeId + 2 - i); + } + + IBinPoolManager.BurnParams memory burnParams; + + // burn activeId-1 + burnParams = _getSingleBinBurnLiquidityParams(key, poolManager, activeId - 1, address(binLiquidityHelper), 100); + binLiquidityHelper.burn(key, burnParams, ""); + + // as activeId-1 bin is empty now, verify the next non empty bin to the left of activeId is activeId-2 + assertEq(poolManager.getNextNonEmptyBin(key.toId(), true, activeId), activeId - 2); + + // burn activeId+1 + burnParams = _getSingleBinBurnLiquidityParams(key, poolManager, activeId + 1, address(binLiquidityHelper), 100); + binLiquidityHelper.burn(key, burnParams, ""); + + // as activeId+1 bin is empty now, verify the next non empty bin to the left of activeId+2 is activeId + assertEq(poolManager.getNextNonEmptyBin(key.toId(), true, activeId + 2), activeId); + } + + function test_getNextNonEmptyBin_AddRemoveAddLiquidity() public { + // initialize + poolManager.initialize(key, activeId); + + // mint, verify activeId is in treeMath + token0.mint(address(this), 2 ether); + token1.mint(address(this), 2 ether); + IBinPoolManager.MintParams memory mintParams = _getSingleBinMintParams(activeId, 1 ether, 1 ether); + binLiquidityHelper.mint(key, mintParams, ""); + assertEq(poolManager.getNextNonEmptyBin(key.toId(), true, activeId + 1), activeId); + + // remove, verify activeId not in treeMath + IBinPoolManager.BurnParams memory burnParams; + burnParams = _getSingleBinBurnLiquidityParams(key, poolManager, activeId, address(binLiquidityHelper), 100); + binLiquidityHelper.burn(key, burnParams, ""); + assertEq(poolManager.getNextNonEmptyBin(key.toId(), true, activeId + 1), type(uint24).max); + + // mint, verify activeId in treeMath again + binLiquidityHelper.mint(key, mintParams, ""); + assertEq(poolManager.getNextNonEmptyBin(key.toId(), true, activeId + 1), activeId); + } + + function test_getNextNonEmptyBin_NoBinWithLiqudiity() public { + poolManager.initialize(key, activeId); + + assertEq(poolManager.getNextNonEmptyBin(key.toId(), true, activeId), type(uint24).max); + assertEq(poolManager.getNextNonEmptyBin(key.toId(), false, activeId), 0); + } + receive() external payable {} function supportsInterface(bytes4) external pure returns (bool) {