diff --git a/.forge-snapshots/BinHookTest#testBurnSucceedsWithHook.snap b/.forge-snapshots/BinHookTest#testBurnSucceedsWithHook.snap index 436357a..a7b4c57 100644 --- a/.forge-snapshots/BinHookTest#testBurnSucceedsWithHook.snap +++ b/.forge-snapshots/BinHookTest#testBurnSucceedsWithHook.snap @@ -1 +1 @@ -178130 \ No newline at end of file +178365 \ No newline at end of file diff --git a/.forge-snapshots/BinHookTest#testMintSucceedsWithHook.snap b/.forge-snapshots/BinHookTest#testMintSucceedsWithHook.snap index 607b6b5..e3356bf 100644 --- a/.forge-snapshots/BinHookTest#testMintSucceedsWithHook.snap +++ b/.forge-snapshots/BinHookTest#testMintSucceedsWithHook.snap @@ -1 +1 @@ -311254 \ No newline at end of file +311472 \ No newline at end of file diff --git a/.forge-snapshots/BinMintBurnFeeHookTest#test_Burn.snap b/.forge-snapshots/BinMintBurnFeeHookTest#test_Burn.snap index d6fd559..7dac5b0 100644 --- a/.forge-snapshots/BinMintBurnFeeHookTest#test_Burn.snap +++ b/.forge-snapshots/BinMintBurnFeeHookTest#test_Burn.snap @@ -1 +1 @@ -170145 \ No newline at end of file +170380 \ No newline at end of file diff --git a/.forge-snapshots/BinMintBurnFeeHookTest#test_Mint.snap b/.forge-snapshots/BinMintBurnFeeHookTest#test_Mint.snap index 4128ba0..5a6422d 100644 --- a/.forge-snapshots/BinMintBurnFeeHookTest#test_Mint.snap +++ b/.forge-snapshots/BinMintBurnFeeHookTest#test_Mint.snap @@ -1 +1 @@ -410336 \ No newline at end of file +410554 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerBytecodeSize.snap b/.forge-snapshots/BinPoolManagerBytecodeSize.snap index c050174..3eceacd 100644 --- a/.forge-snapshots/BinPoolManagerBytecodeSize.snap +++ b/.forge-snapshots/BinPoolManagerBytecodeSize.snap @@ -1 +1 @@ -23287 \ No newline at end of file +23421 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testBurnNativeCurrency.snap b/.forge-snapshots/BinPoolManagerTest#testBurnNativeCurrency.snap index 0257459..fb2b3ed 100644 --- a/.forge-snapshots/BinPoolManagerTest#testBurnNativeCurrency.snap +++ b/.forge-snapshots/BinPoolManagerTest#testBurnNativeCurrency.snap @@ -1 +1 @@ -133892 \ No newline at end of file +134080 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testGasBurnHalfBin.snap b/.forge-snapshots/BinPoolManagerTest#testGasBurnHalfBin.snap index f53d2c9..577498a 100644 --- a/.forge-snapshots/BinPoolManagerTest#testGasBurnHalfBin.snap +++ b/.forge-snapshots/BinPoolManagerTest#testGasBurnHalfBin.snap @@ -1 +1 @@ -142717 \ No newline at end of file +142975 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testGasBurnNineBins.snap b/.forge-snapshots/BinPoolManagerTest#testGasBurnNineBins.snap index 994141b..de77604 100644 --- a/.forge-snapshots/BinPoolManagerTest#testGasBurnNineBins.snap +++ b/.forge-snapshots/BinPoolManagerTest#testGasBurnNineBins.snap @@ -1 +1 @@ -289683 \ No newline at end of file +291375 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testGasBurnOneBin.snap b/.forge-snapshots/BinPoolManagerTest#testGasBurnOneBin.snap index ba16a41..a27b295 100644 --- a/.forge-snapshots/BinPoolManagerTest#testGasBurnOneBin.snap +++ b/.forge-snapshots/BinPoolManagerTest#testGasBurnOneBin.snap @@ -1 +1 @@ -127065 \ No newline at end of file +127253 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-1.snap b/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-1.snap index dc44a72..b285a5a 100644 --- a/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-1.snap +++ b/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-1.snap @@ -1 +1 @@ -968475 \ No newline at end of file +970437 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-2.snap b/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-2.snap index 4a863ea..4442fbd 100644 --- a/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-2.snap +++ b/.forge-snapshots/BinPoolManagerTest#testGasMintNneBins-2.snap @@ -1 +1 @@ -327787 \ No newline at end of file +329749 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-1.snap b/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-1.snap index f71e10b..7e9f16b 100644 --- a/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-1.snap +++ b/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-1.snap @@ -1 +1 @@ -337511 \ No newline at end of file +337729 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-2.snap b/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-2.snap index 140b1dd..36edafd 100644 --- a/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-2.snap +++ b/.forge-snapshots/BinPoolManagerTest#testGasMintOneBin-2.snap @@ -1 +1 @@ -140062 \ No newline at end of file +140280 \ No newline at end of file diff --git a/.forge-snapshots/BinPoolManagerTest#testMintNativeCurrency.snap b/.forge-snapshots/BinPoolManagerTest#testMintNativeCurrency.snap index f9388fc..cb4c7ae 100644 --- a/.forge-snapshots/BinPoolManagerTest#testMintNativeCurrency.snap +++ b/.forge-snapshots/BinPoolManagerTest#testMintNativeCurrency.snap @@ -1 +1 @@ -304550 \ No newline at end of file +304768 \ No newline at end of file diff --git a/src/pool-bin/libraries/BinPool.sol b/src/pool-bin/libraries/BinPool.sol index 8fb7708..0486b8e 100644 --- a/src/pool-bin/libraries/BinPool.sol +++ b/src/pool-bin/libraries/BinPool.sol @@ -48,6 +48,7 @@ library BinPool { error BinPool__NoLiquidityToReceiveFees(); /// @dev if swap exactIn, x for y, unspecifiedToken = token y. if swap x for exact out y, unspecified token is x error BinPool__InsufficientAmountUnSpecified(); + error BinPool__BelowMinimumShare(uint256 balanceShare); /// @dev The state of a pool struct State { @@ -66,6 +67,9 @@ library BinPool { mapping(bytes32 => bytes32) level2; } + /// @dev when liquidity is removed, ensure there is either greater than min_share or 0 liquidity left + uint256 constant MINIMUM_SHARE = 1e9; + function initialize(State storage self, uint24 activeId, uint24 protocolFee, uint24 lpFee) internal { /// An initialized pool will not have activeId: 0 if (self.slot0.activeId() != 0) revert PoolAlreadyInitialized(); @@ -464,12 +468,26 @@ library BinPool { function _subShare(State storage self, address owner, uint24 binId, bytes32 salt, uint256 shares) internal { self.positions.get(owner, binId, salt).subShare(shares); self.shareOfBin[binId] -= shares; + + /// @dev Ensure bin total share is either 0 or greater than minimum share + uint256 balanceShare = self.shareOfBin[binId]; + if (balanceShare > 0 && balanceShare < MINIMUM_SHARE) { + revert BinPool__BelowMinimumShare(balanceShare); + } } /// @notice Add share to user's position and update total share supply of bin function _addShare(State storage self, address owner, uint24 binId, bytes32 salt, uint256 shares) internal { self.positions.get(owner, binId, salt).addShare(shares); self.shareOfBin[binId] += shares; + + /// @dev Ensure bin total share is either 0 or greater than minimum share + /// to discuss if we want to enforce this -- otherwise user can potentially add below 1e9 liquidity + /// but can't withdraw if there's no other lp to help push the min share up + uint256 balanceShare = self.shareOfBin[binId]; + if (balanceShare < MINIMUM_SHARE) { + revert BinPool__BelowMinimumShare(balanceShare); + } } /// @notice Enable bin id for a pool diff --git a/test/pool-bin/libraries/BinPoolDonate.t.sol b/test/pool-bin/libraries/BinPoolDonate.t.sol index 9efc1dd..667a9b8 100644 --- a/test/pool-bin/libraries/BinPoolDonate.t.sol +++ b/test/pool-bin/libraries/BinPoolDonate.t.sol @@ -61,8 +61,9 @@ contract BinPoolDonateTest is BinTestHelper { poolManager.initialize(key, activeId); addLiquidityToBin(key, poolManager, alice, activeId, 1e18, 1e18, 1e18, 1e18, ""); - // Remove all share leaving less than MIN_LIQUIDITY_BEFORE_DONATE shares - remainingShare = bound(remainingShare, 1, poolManager.minBinShareForDonate() - 1); + /// @dev Remove all share leaving between 1e9 and minShareForDinate + /// if its less than 1e9, it will throw BinPool__BelowMinimumShareInBurn error + remainingShare = bound(remainingShare, 1e9, poolManager.minBinShareForDonate() - 1); uint256 aliceShare = poolManager.getPosition(poolId, alice, activeId, 0).share; removeLiquidityFromBin(key, poolManager, alice, activeId, aliceShare - remainingShare, "");