From 0d2804ee1f7c2663fe46ba9b3e5a16b873b8c657 Mon Sep 17 00:00:00 2001 From: Jem <0x0xjem@gmail.com> Date: Wed, 19 Jun 2024 14:46:37 +0400 Subject: [PATCH] Update BaselineAxisLaunch to check the BPOOL's active tick against the auction price. Updates tests accordingly. Remove redundant TimeslotLib. --- script/salts/salts.json | 4 +- .../BaselineV2/BaselineAxisLaunch.sol | 73 ++++++++--- .../liquidity/BaselineV2/lib/TimeslotLib.sol | 30 ----- .../BaselineV2/AllocatedAllowlist/onBid.t.sol | 9 ++ .../AllocatedAllowlist/onCreate.t.sol | 2 + .../AllocatedAllowlist/setMerkleRoot.t.sol | 4 + .../BaselineV2/BaselineAxisLaunchTest.sol | 122 +++++++++++------- .../liquidity/BaselineV2/mocks/MockBPOOL.sol | 1 + .../liquidity/BaselineV2/onCancel.t.sol | 6 + .../liquidity/BaselineV2/onCreate.t.sol | 106 +++++++++++++-- .../liquidity/BaselineV2/onCurate.t.sol | 10 +- .../liquidity/BaselineV2/onSettle.t.sol | 8 ++ .../BaselineV2/withdrawReserves.t.sol | 4 +- 13 files changed, 264 insertions(+), 115 deletions(-) delete mode 100644 src/callbacks/liquidity/BaselineV2/lib/TimeslotLib.sol diff --git a/script/salts/salts.json b/script/salts/salts.json index d67c11e3..0df117d3 100644 --- a/script/salts/salts.json +++ b/script/salts/salts.json @@ -19,10 +19,10 @@ "0xeea914831cafc1587d76be464f11002411abf2a8819b9fdb690b0861a50b7013": "0xfc5a3e878c2ebbe399fd000b0874c27ddc00fccafbebc26a47062384fb792271" }, "Test_BaselineAllocatedAllowlist": { - "0xdf4e330322b2cf16b983e30be68fdcc9f28aa9ca3ea5668db2da4680e00f7656": "0x90d7692e46b872b1176d8f108f9ffa9f37afd52ab59b2411c01b53d585a47df2" + "0x03bef2ceffa258ff6109ad6bc16d951564cde898281cb9d4d0011390a461e977": "0xbb9a94cda3e330636bc8519044b22888a2e0f5fa06f48c1203c824730d429978" }, "Test_BaselineAxisLaunch": { - "0x93fb862631c4414f2d4108397ca06e077a3caf62374b7a6c8fb38d35c275f02a": "0xd116feb11c4c04385a9476d1f1a1da81cfedca07a1b3638abd751622fbeffb8a" + "0x5554c48c8c661389476240aa7a1f3ec5cc9eee83e418504c25ee333d29d9bf87": "0x5ed9eb6bba3f801a5c7155da7e61545c108a342439c577724bf5514a06dd54a2" }, "Test_CappedMerkleAllowlist": { "0xd46fcdc05daffec5dc7bd7b165f3ffef024c5074d5f5d8f096ad176a348b93e9": "0x9a505eb6b9322904cad8128403089877c62cbbfad4b91ab17f83e0e51bc519e2", diff --git a/src/callbacks/liquidity/BaselineV2/BaselineAxisLaunch.sol b/src/callbacks/liquidity/BaselineV2/BaselineAxisLaunch.sol index 2d650662..1c5bd822 100644 --- a/src/callbacks/liquidity/BaselineV2/BaselineAxisLaunch.sol +++ b/src/callbacks/liquidity/BaselineV2/BaselineAxisLaunch.sol @@ -23,7 +23,6 @@ import { Permissions as BaselinePermissions } from "src/callbacks/liquidity/BaselineV2/lib/Kernel.sol"; import {Range, IBPOOLv1} from "src/callbacks/liquidity/BaselineV2/lib/IBPOOL.sol"; -import {TimeslotLib} from "src/callbacks/liquidity/BaselineV2/lib/TimeslotLib.sol"; import {TickMath} from "lib/uniswap-v3-core/contracts/libraries/TickMath.sol"; // Other libraries @@ -37,14 +36,40 @@ import {SqrtPriceMath} from "src/lib/uniswap-v3/SqrtPriceMath.sol"; /// It is designed to be used with a single auction and Baseline pool contract BaselineAxisLaunch is BaseCallback, Policy, Owned { using FixedPointMathLib for uint256; - using TimeslotLib for uint256; // ========== ERRORS ========== // + /// @notice The address of the base token (passed in the `onCreate` callback) does not match the address of the bAsset that the callback was initialized with + error Callback_Params_BAssetTokenMismatch(address baseToken_, address bAsset_); + + /// @notice The address of the quote token (passed in the `onCreate` callback) does not match the address of the reserve that the callback was initialized with + error Callback_Params_ReserveTokenMismatch(address quoteToken_, address reserve_); + + /// @notice The auction price and the pool active tick do not match + error Callback_Params_PoolTickMismatch(int24 auctionTick_, int24 poolTick_); + + /// @notice The auction format is not supported + error Callback_Params_UnsupportedAuctionFormat(); + + /// @notice The anchor tick width is invalid + error Callback_Params_InvalidAnchorTickWidth(); + + /// @notice The discovery tick width is invalid + error Callback_Params_InvalidDiscoveryTickWidth(); + + /// @notice The floor reserves percent is invalid + error Callback_Params_InvalidFloorReservesPercent(); + + /// @notice The auction tied to this callbacks contract has already been completed error Callback_AlreadyComplete(); + + /// @notice The required funds were not sent to this callbacks contract error Callback_MissingFunds(); + /// @notice The BPOOL reserve token does not match the configured `RESERVE` address error InvalidModule(); + + /// @notice Deploying reserves and liquidity would result in the Baseline pool being insolvent error Insolvent(); // ========== EVENTS ========== // @@ -165,13 +190,12 @@ contract BaselineAxisLaunch is BaseCallback, Policy, Owned { { BaselineKeycode bpool = toBaselineKeycode("BPOOL"); - requests = new BaselinePermissions[](6); - requests[0] = BaselinePermissions(bpool, BPOOL.initializePool.selector); - requests[1] = BaselinePermissions(bpool, BPOOL.addReservesTo.selector); - requests[2] = BaselinePermissions(bpool, BPOOL.addLiquidityTo.selector); - requests[3] = BaselinePermissions(bpool, BPOOL.burnAllBAssetsInContract.selector); - requests[4] = BaselinePermissions(bpool, BPOOL.mint.selector); - requests[5] = BaselinePermissions(bpool, BPOOL.setTicks.selector); + requests = new BaselinePermissions[](5); + requests[0] = BaselinePermissions(bpool, BPOOL.addReservesTo.selector); + requests[1] = BaselinePermissions(bpool, BPOOL.addLiquidityTo.selector); + requests[2] = BaselinePermissions(bpool, BPOOL.burnAllBAssetsInContract.selector); + requests[3] = BaselinePermissions(bpool, BPOOL.mint.selector); + requests[4] = BaselinePermissions(bpool, BPOOL.setTicks.selector); } // ========== CALLBACK FUNCTIONS ========== // @@ -198,12 +222,12 @@ contract BaselineAxisLaunch is BaseCallback, Policy, Owned { /// - `baseToken_` is not the same as `bAsset` /// - `quoteToken_` is not the same as `RESERVE` /// - `lotId` is already set - /// - `CreateData.percentReservesFloor` is less than 0% or greater than 100% + /// - `CreateData.floorReservesPercent` is less than 0% or greater than 100% /// - `CreateData.anchorTickWidth` is 0 /// - `CreateData.discoveryTickWidth` is 0 /// - The auction format is not supported - /// - FPB auction format: `CreateData.initAnchorTick` is 0 /// - The auction is not prefunded + /// - The active tick of the Baseline pool (from `baseToken_`) is not the same as the tick corresponding to the auction price function _onCreate( uint96 lotId_, address seller_, @@ -215,8 +239,11 @@ contract BaselineAxisLaunch is BaseCallback, Policy, Owned { ) internal override { // Validate the base token is the baseline token // and the quote token is the reserve - if (baseToken_ != address(bAsset) || quoteToken_ != address(RESERVE)) { - revert Callback_InvalidParams(); + if (baseToken_ != address(bAsset)) { + revert Callback_Params_BAssetTokenMismatch(baseToken_, address(bAsset)); + } + if (quoteToken_ != address(RESERVE)) { + revert Callback_Params_ReserveTokenMismatch(quoteToken_, address(RESERVE)); } // Validate that the lot ID is not already set @@ -227,22 +254,22 @@ contract BaselineAxisLaunch is BaseCallback, Policy, Owned { // Validate that the anchor tick width is at least 1 tick spacing if (cbData.anchorTickWidth <= 0) { - revert Callback_InvalidParams(); + revert Callback_Params_InvalidAnchorTickWidth(); } // Validate that the discovery tick width is at least 1 tick spacing if (cbData.discoveryTickWidth <= 0) { - revert Callback_InvalidParams(); + revert Callback_Params_InvalidDiscoveryTickWidth(); } // Validate that the floor reserves percent is between 0% and 100% if (cbData.floorReservesPercent > ONE_HUNDRED_PERCENT) { - revert Callback_InvalidParams(); + revert Callback_Params_InvalidFloorReservesPercent(); } // Auction must be prefunded for batch auctions (which is the only type supported with this callback), // this can't fail because it's checked in the AH as well, but including for completeness - if (!prefund_) revert Callback_InvalidParams(); + if (!prefund_) revert Callback_Params_UnsupportedAuctionFormat(); // Set the lot ID lotId = lotId_; @@ -257,7 +284,7 @@ contract BaselineAxisLaunch is BaseCallback, Policy, Owned { // Only supports Fixed Price Batch Auctions initially if (fromAxisKeycode(auctionFormat) != bytes5("FPBA")) { - revert Callback_InvalidParams(); + revert Callback_Params_UnsupportedAuctionFormat(); } // This contract can be extended with an allowlist for the auction @@ -286,10 +313,14 @@ contract BaselineAxisLaunch is BaseCallback, Policy, Owned { address(RESERVE), address(bAsset), auctionPrice, 10 ** baseTokenDecimals ); activeTick = TickMath.getTickAtSqrtRatio(sqrtPriceX96); - } - // Initialize the Baseline pool at the tick determined by the auction price - BPOOL.initializePool(activeTick); + // Check that the pool is initialized at the active tick + // This is to ensure that the pool is initialized at the auction price + (, int24 poolCurrentTick,,,,,) = BPOOL.pool().slot0(); + if (poolCurrentTick != activeTick) { + revert Callback_Params_PoolTickMismatch(activeTick, poolCurrentTick); + } + } int24 tickSpacing = BPOOL.TICK_SPACING(); diff --git a/src/callbacks/liquidity/BaselineV2/lib/TimeslotLib.sol b/src/callbacks/liquidity/BaselineV2/lib/TimeslotLib.sol deleted file mode 100644 index cfc356c8..00000000 --- a/src/callbacks/liquidity/BaselineV2/lib/TimeslotLib.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.0; - -library TimeslotLib { - /// @notice uint256 is the unix timestamp at the end of the day - /// @param timestamp_ Unix timestamp - function getTimeslot(uint256 timestamp_) internal pure returns (uint256) { - return timestamp_ - (timestamp_ % 1 days) + 1 days - 1; - } - - function today() internal view returns (uint256) { - return getTimeslot(block.timestamp); - } - - function addDays(uint256 oldTimeslot_, uint256 numDays_) internal pure returns (uint256) { - return getTimeslot(oldTimeslot_ + numDays_ * 1 days); - } - - function subDays(uint256 oldTimeslot_, uint256 numDays_) internal pure returns (uint256) { - return getTimeslot(oldTimeslot_ - numDays_ * 1 days); - } - - function diffDays(uint256 from_, uint256 to_) internal pure returns (uint256) { - if (from_ > to_) { - return (from_ - to_) / 1 days; - } else { - return (to_ - from_) / 1 days; - } - } -} diff --git a/test/callbacks/liquidity/BaselineV2/AllocatedAllowlist/onBid.t.sol b/test/callbacks/liquidity/BaselineV2/AllocatedAllowlist/onBid.t.sol index a554bfe1..85f9f837 100644 --- a/test/callbacks/liquidity/BaselineV2/AllocatedAllowlist/onBid.t.sol +++ b/test/callbacks/liquidity/BaselineV2/AllocatedAllowlist/onBid.t.sol @@ -69,6 +69,7 @@ contract BaselineAllocatedAllowlistOnBidTest is BaselineAllocatedAllowlistTest { function test_parametersInvalid_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAllowlistParams(_MERKLE_ROOT) @@ -84,6 +85,7 @@ contract BaselineAllocatedAllowlistOnBidTest is BaselineAllocatedAllowlistTest { function test_merkleProofInvalid_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAllowlistParams(_MERKLE_ROOT) @@ -101,6 +103,7 @@ contract BaselineAllocatedAllowlistOnBidTest is BaselineAllocatedAllowlistTest { function test_buyerNotInMerkleTree_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAllowlistParams(_MERKLE_ROOT) @@ -119,6 +122,7 @@ contract BaselineAllocatedAllowlistOnBidTest is BaselineAllocatedAllowlistTest { function test_buyerLimitSpent_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAllowlistParams(_MERKLE_ROOT) @@ -140,6 +144,7 @@ contract BaselineAllocatedAllowlistOnBidTest is BaselineAllocatedAllowlistTest { function test_buyerZeroLimit_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAllowlistParams(_MERKLE_ROOT) @@ -159,6 +164,7 @@ contract BaselineAllocatedAllowlistOnBidTest is BaselineAllocatedAllowlistTest { function test_noBids_aboveLimit_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAllowlistParams(_MERKLE_ROOT) @@ -177,6 +183,7 @@ contract BaselineAllocatedAllowlistOnBidTest is BaselineAllocatedAllowlistTest { function test_noBids_belowLimit() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAllowlistParams(_MERKLE_ROOT) @@ -193,6 +200,7 @@ contract BaselineAllocatedAllowlistOnBidTest is BaselineAllocatedAllowlistTest { function test_remainingLimit_aboveLimit_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAllowlistParams(_MERKLE_ROOT) @@ -214,6 +222,7 @@ contract BaselineAllocatedAllowlistOnBidTest is BaselineAllocatedAllowlistTest { function test_remainingLimit_belowLimit() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAllowlistParams(_MERKLE_ROOT) diff --git a/test/callbacks/liquidity/BaselineV2/AllocatedAllowlist/onCreate.t.sol b/test/callbacks/liquidity/BaselineV2/AllocatedAllowlist/onCreate.t.sol index 025b395f..819fc2c8 100644 --- a/test/callbacks/liquidity/BaselineV2/AllocatedAllowlist/onCreate.t.sol +++ b/test/callbacks/liquidity/BaselineV2/AllocatedAllowlist/onCreate.t.sol @@ -21,6 +21,7 @@ contract BaselineAllocatedAllowlistOnCreateTest is BaselineAllocatedAllowlistTes function test_allowlistParamsIncorrect_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated { @@ -37,6 +38,7 @@ contract BaselineAllocatedAllowlistOnCreateTest is BaselineAllocatedAllowlistTes function test_success_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAllowlistParams(_MERKLE_ROOT) diff --git a/test/callbacks/liquidity/BaselineV2/AllocatedAllowlist/setMerkleRoot.t.sol b/test/callbacks/liquidity/BaselineV2/AllocatedAllowlist/setMerkleRoot.t.sol index c39fb7ec..79ce14e1 100644 --- a/test/callbacks/liquidity/BaselineV2/AllocatedAllowlist/setMerkleRoot.t.sol +++ b/test/callbacks/liquidity/BaselineV2/AllocatedAllowlist/setMerkleRoot.t.sol @@ -32,6 +32,7 @@ contract BaselineAllocatedAllowlistSetMerkleRootTest is BaselineAllocatedAllowli function test_notOwner_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAllowlistParams(_MERKLE_ROOT) @@ -46,6 +47,7 @@ contract BaselineAllocatedAllowlistSetMerkleRootTest is BaselineAllocatedAllowli function test_auctionNotRegistered_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAllowlistParams(_MERKLE_ROOT) @@ -61,6 +63,7 @@ contract BaselineAllocatedAllowlistSetMerkleRootTest is BaselineAllocatedAllowli function test_auctionCompleted_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAllowlistParams(_MERKLE_ROOT) @@ -80,6 +83,7 @@ contract BaselineAllocatedAllowlistSetMerkleRootTest is BaselineAllocatedAllowli function test_success() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAllowlistParams(_MERKLE_ROOT) diff --git a/test/callbacks/liquidity/BaselineV2/BaselineAxisLaunchTest.sol b/test/callbacks/liquidity/BaselineV2/BaselineAxisLaunchTest.sol index 6efdc2b9..b877b28f 100644 --- a/test/callbacks/liquidity/BaselineV2/BaselineAxisLaunchTest.sol +++ b/test/callbacks/liquidity/BaselineV2/BaselineAxisLaunchTest.sol @@ -13,6 +13,8 @@ import {UniswapV3Factory} from "test/lib/uniswap-v3/UniswapV3Factory.sol"; import {ComputeAddress} from "test/lib/ComputeAddress.sol"; import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol"; import {TestConstants} from "test/Constants.sol"; +import {SqrtPriceMath} from "src/lib/uniswap-v3/SqrtPriceMath.sol"; +import {TickMath} from "uniswap-v3-core/libraries/TickMath.sol"; // Axis core import {IAuction} from "src/interfaces/modules/IAuction.sol"; @@ -48,6 +50,10 @@ abstract contract BaselineAxisLaunchTest is Test, Permit2User, WithSalts, TestCo uint256 internal constant _BASE_SCALE = 1e18; uint8 internal _quoteTokenDecimals = 18; uint8 internal _baseTokenDecimals = 18; + bool internal _isBaseTokenAddressLower = false; + uint24 internal _feeTier = _FEE_TIER; + /// @dev Set in `_updatePoolInitialTick()` + int24 internal _poolInitialTick; uint48 internal constant _START = 1_000_000; @@ -123,28 +129,60 @@ abstract contract BaselineAxisLaunchTest is Test, Permit2User, WithSalts, TestCo revert("Quote Token address mismatch"); } - // Generate a salt so that the base token address is higher than the quote token + _tickSpacing = _uniV3Factory.feeAmountTickSpacing(_feeTier); + + // Base token is created in the givenBPoolIsCreated modifier + + // Calculate the initial tick + _updatePoolInitialTick(); + } + + // ========== MODIFIERS ========== // + + function _updatePoolInitialTick() internal { + _poolInitialTick = + _getTickFromPrice(_fpbParams.price, _baseTokenDecimals, _isBaseTokenAddressLower); + } + + modifier givenBPoolIsCreated() { + // Generate a salt so that the base token address is higher (or lower) than the quote token bytes32 baseTokenSalt = ComputeAddress.generateSalt( _BASELINE_QUOTE_TOKEN, - true, + !_isBaseTokenAddressLower, type(MockBPOOL).creationCode, abi.encode( - "Base Token", "BT", 18, address(_uniV3Factory), _BASELINE_QUOTE_TOKEN, _FEE_TIER + "Base Token", + "BT", + _baseTokenDecimals, + address(_uniV3Factory), + _BASELINE_QUOTE_TOKEN, + _feeTier, + _poolInitialTick ), address(this) ); - // Set base token to BPOOL - _baseToken = new MockBPOOL{salt: baseTokenSalt}( - "Base Token", "BT", 18, address(_uniV3Factory), _BASELINE_QUOTE_TOKEN, 3000 + // Create a new mock BPOOL with the given fee tier + _baseToken = new MockBPOOL( + "Base Token", + "BT", + _baseTokenDecimals, + address(_uniV3Factory), + _BASELINE_QUOTE_TOKEN, + _feeTier, + _poolInitialTick ); - _baseTokenDecimals = 18; - _tickSpacing = _uniV3Factory.feeAmountTickSpacing(_FEE_TIER); - } - // ========== MODIFIERS ========== // + // Update the mock + _mockBaselineGetModuleForKeycode(); + _; + } modifier givenCallbackIsCreated() virtual { + if (address(_baseToken) == address(0)) { + revert("Base token not created"); + } + // Get the salt bytes memory args = abi.encode(address(_auctionHouse), _BASELINE_KERNEL, _BASELINE_QUOTE_TOKEN, _OWNER); @@ -162,7 +200,6 @@ abstract contract BaselineAxisLaunchTest is Test, Permit2User, WithSalts, TestCo _dtlAddress = address(_dtl); // Call configureDependencies to set everything that's needed - _mockBaselineGetModuleForKeycode(); _dtl.configureDependencies(); _; } @@ -229,57 +266,29 @@ abstract contract BaselineAxisLaunchTest is Test, Permit2User, WithSalts, TestCo } modifier givenBPoolFeeTier(uint24 feeTier_) { - // Generate a salt so that the base token address is higher than the quote token - bytes32 baseTokenSalt = ComputeAddress.generateSalt( - _BASELINE_QUOTE_TOKEN, - true, - type(MockBPOOL).creationCode, - abi.encode( - "Base Token", "BT", 18, address(_uniV3Factory), _BASELINE_QUOTE_TOKEN, feeTier_ - ), - address(this) - ); - - // Create a new mock BPOOL with the given fee tier - _baseToken = new MockBPOOL( - "Base Token", "BT", 18, address(_uniV3Factory), _BASELINE_QUOTE_TOKEN, feeTier_ - ); - _tickSpacing = _uniV3Factory.feeAmountTickSpacing(feeTier_); + _feeTier = feeTier_; + _tickSpacing = _uniV3Factory.feeAmountTickSpacing(_feeTier); _; } modifier givenBaseTokenAddressLower() { - // Generate a salt so that the base token address is lower than the quote token - bytes32 baseTokenSalt = ComputeAddress.generateSalt( - _BASELINE_QUOTE_TOKEN, - false, - type(MockBPOOL).creationCode, - abi.encode( - "Base Token", "BT", 18, address(_uniV3Factory), _BASELINE_QUOTE_TOKEN, _FEE_TIER - ), - address(this) - ); + _isBaseTokenAddressLower = false; - // Create a new mock BPOOL with the given address - _baseToken = new MockBPOOL{salt: baseTokenSalt}( - "Base Token", "BT", 18, address(_uniV3Factory), _BASELINE_QUOTE_TOKEN, _FEE_TIER - ); - _tickSpacing = _uniV3Factory.feeAmountTickSpacing(_FEE_TIER); + _updatePoolInitialTick(); _; } modifier givenBaseTokenDecimals(uint8 decimals_) { - // Create a new mock BPOOL with the given decimals - _baseToken = new MockBPOOL( - "Base Token", "BT", decimals_, address(_uniV3Factory), _BASELINE_QUOTE_TOKEN, _FEE_TIER - ); _baseTokenDecimals = decimals_; - _tickSpacing = _uniV3Factory.feeAmountTickSpacing(_FEE_TIER); + + _updatePoolInitialTick(); _; } modifier givenFixedPrice(uint256 fixedPrice_) { _fpbParams.price = fixedPrice_; + + _updatePoolInitialTick(); _; } @@ -307,6 +316,25 @@ abstract contract BaselineAxisLaunchTest is Test, Permit2User, WithSalts, TestCo _; } + function _getTickFromPrice( + uint256 price_, + uint8 baseTokenDecimals_, + bool isBaseTokenAddressLower_ + ) internal pure returns (int24 tick) { + // Get sqrtPriceX96 + uint160 sqrtPriceX96 = SqrtPriceMath.getSqrtPriceX96( + _BASELINE_QUOTE_TOKEN, + isBaseTokenAddressLower_ + ? address(0x0000000000000000000000000000000000000001) + : address(0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF), + price_, + 10 ** baseTokenDecimals_ + ); + + // Convert to tick + return TickMath.getTickAtSqrtRatio(sqrtPriceX96); + } + // ========== MOCKS ========== // function _mockGetAuctionModuleForId() internal { diff --git a/test/callbacks/liquidity/BaselineV2/mocks/MockBPOOL.sol b/test/callbacks/liquidity/BaselineV2/mocks/MockBPOOL.sol index 33e62340..1fd013c8 100644 --- a/test/callbacks/liquidity/BaselineV2/mocks/MockBPOOL.sol +++ b/test/callbacks/liquidity/BaselineV2/mocks/MockBPOOL.sol @@ -43,6 +43,7 @@ contract MockBPOOL is IBPOOLv1, ERC20 { // Set the initial active tick pool.initialize(TickMath.getSqrtRatioAtTick(initialActiveTick_)); + activeTick = initialActiveTick_; } function getLiquidity(Range range_) external view override returns (uint128) { diff --git a/test/callbacks/liquidity/BaselineV2/onCancel.t.sol b/test/callbacks/liquidity/BaselineV2/onCancel.t.sol index c7b5a034..0408d3ee 100644 --- a/test/callbacks/liquidity/BaselineV2/onCancel.t.sol +++ b/test/callbacks/liquidity/BaselineV2/onCancel.t.sol @@ -28,6 +28,7 @@ contract BaselineOnCancelTest is BaselineAxisLaunchTest { function test_lotNotRegistered_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAddressHasBaseTokenBalance(_dtlAddress, _LOT_CAPACITY) @@ -42,6 +43,7 @@ contract BaselineOnCancelTest is BaselineAxisLaunchTest { function test_notAuctionHouse_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenOnCreate @@ -57,6 +59,7 @@ contract BaselineOnCancelTest is BaselineAxisLaunchTest { function test_lotAlreadyCancelled_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenOnCreate @@ -74,6 +77,7 @@ contract BaselineOnCancelTest is BaselineAxisLaunchTest { function test_lotAlreadySettled_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenOnCreate @@ -92,6 +96,7 @@ contract BaselineOnCancelTest is BaselineAxisLaunchTest { function test_insufficientRefund_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenOnCreate @@ -106,6 +111,7 @@ contract BaselineOnCancelTest is BaselineAxisLaunchTest { function test_success() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenOnCreate diff --git a/test/callbacks/liquidity/BaselineV2/onCreate.t.sol b/test/callbacks/liquidity/BaselineV2/onCreate.t.sol index f361425b..3ad7eb3b 100644 --- a/test/callbacks/liquidity/BaselineV2/onCreate.t.sol +++ b/test/callbacks/liquidity/BaselineV2/onCreate.t.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.19; import {BaselineAxisLaunchTest} from "test/callbacks/liquidity/BaselineV2/BaselineAxisLaunchTest.sol"; +import {BaselineAxisLaunch} from "src/callbacks/liquidity/BaselineV2/BaselineAxisLaunch.sol"; import {BaseCallback} from "src/callbacks/BaseCallback.sol"; import {Range} from "src/callbacks/liquidity/BaselineV2/lib/IBPOOL.sol"; @@ -185,6 +186,8 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { // [X] it reverts // [X] when the auction is not prefunded // [X] it reverts + // [X] when the auction price does not match the pool active tick + // [X] it reverts // [X] when the floorReservesPercent is 0-100% // [X] it correctly records the allocation // [X] when the tick spacing is narrow @@ -207,6 +210,7 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_callbackDataIncorrect_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated { @@ -226,7 +230,12 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { ); } - function test_notAuctionHouse_reverts() public givenCallbackIsCreated givenAuctionIsCreated { + function test_notAuctionHouse_reverts() + public + givenBPoolIsCreated + givenCallbackIsCreated + givenAuctionIsCreated + { // Expect revert _expectNotAuthorized(); @@ -244,6 +253,7 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_lotAlreadyRegistered_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated { @@ -257,9 +267,19 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { _onCreate(); } - function test_baseTokenNotBPool_reverts() public givenCallbackIsCreated givenAuctionIsCreated { + function test_baseTokenNotBPool_reverts() + public + givenBPoolIsCreated + givenCallbackIsCreated + givenAuctionIsCreated + { // Expect revert - _expectInvalidParams(); + bytes memory err = abi.encodeWithSelector( + BaselineAxisLaunch.Callback_Params_BAssetTokenMismatch.selector, + address(_quoteToken), + address(_baseToken) + ); + vm.expectRevert(err); // Perform the call vm.prank(address(_auctionHouse)); @@ -276,11 +296,17 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_quoteTokenNotReserve_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated { // Expect revert - _expectInvalidParams(); + bytes memory err = abi.encodeWithSelector( + BaselineAxisLaunch.Callback_Params_ReserveTokenMismatch.selector, + address(_baseToken), + address(_quoteToken) + ); + vm.expectRevert(err); // Perform the call vm.prank(address(_auctionHouse)); @@ -297,6 +323,7 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_floorReservesPercentInvalid_reverts(uint24 floorReservesPercent_) public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated { @@ -305,7 +332,10 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { _createData.floorReservesPercent = floorReservesPercent; // Expect revert - _expectInvalidParams(); + bytes memory err = abi.encodeWithSelector( + BaselineAxisLaunch.Callback_Params_InvalidFloorReservesPercent.selector + ); + vm.expectRevert(err); // Perform the call _onCreate(); @@ -313,6 +343,7 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_anchorTickWidthInvalid_reverts(int24 anchorTickWidth_) public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated { @@ -320,7 +351,10 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { _createData.anchorTickWidth = anchorTickWidth; // Expect revert - _expectInvalidParams(); + bytes memory err = abi.encodeWithSelector( + BaselineAxisLaunch.Callback_Params_InvalidAnchorTickWidth.selector + ); + vm.expectRevert(err); // Perform the call _onCreate(); @@ -328,6 +362,7 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_discoveryTickWidthInvalid_reverts(int24 discoveryTickWidth_) public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated { @@ -335,7 +370,10 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { _createData.discoveryTickWidth = discoveryTickWidth; // Expect revert - _expectInvalidParams(); + bytes memory err = abi.encodeWithSelector( + BaselineAxisLaunch.Callback_Params_InvalidDiscoveryTickWidth.selector + ); + vm.expectRevert(err); // Perform the call _onCreate(); @@ -343,12 +381,16 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_givenAuctionFormatNotFixedPriceBatch_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionFormatIsEmp givenAuctionIsCreated { // Expect revert - _expectInvalidParams(); + bytes memory err = abi.encodeWithSelector( + BaselineAxisLaunch.Callback_Params_UnsupportedAuctionFormat.selector + ); + vm.expectRevert(err); // Perform the call _onCreate(); @@ -356,11 +398,15 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_auctionNotPrefunded_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated { // Expect revert - _expectInvalidParams(); + bytes memory err = abi.encodeWithSelector( + BaselineAxisLaunch.Callback_Params_UnsupportedAuctionFormat.selector + ); + vm.expectRevert(err); // Perform the call vm.prank(address(_auctionHouse)); @@ -375,7 +421,31 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { ); } - function test_success() public givenCallbackIsCreated givenAuctionIsCreated { + function test_auctionPriceDoesNotMatchPoolActiveTick_reverts() + public + givenBPoolIsCreated // BPOOL will have an active tick of _FIXED_PRICE + givenCallbackIsCreated + givenFixedPrice(2e18) + givenAuctionIsCreated // Has to be after the fixed price is set + { + // Expect revert + bytes memory err = abi.encodeWithSelector( + BaselineAxisLaunch.Callback_Params_PoolTickMismatch.selector, + _getTickFromPrice(2e18, _baseTokenDecimals, _isBaseTokenAddressLower), + _baseToken.activeTick() + ); + vm.expectRevert(err); + + // Perform the call + _onCreate(); + } + + function test_success() + public + givenBPoolIsCreated + givenCallbackIsCreated + givenAuctionIsCreated + { // Perform the call _onCreate(); @@ -399,6 +469,7 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_floorReservesPercent(uint24 floorReservesPercent_) public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated { @@ -415,6 +486,7 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_tickSpacingNarrow() public givenBPoolFeeTier(500) + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated { @@ -429,8 +501,9 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_auctionHighPrice() public - givenCallbackIsCreated givenFixedPrice(3e56) + givenBPoolIsCreated + givenCallbackIsCreated givenAuctionIsCreated { // Perform the call @@ -463,8 +536,9 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_auctionLowPrice() public - givenCallbackIsCreated givenFixedPrice(1) + givenBPoolIsCreated + givenCallbackIsCreated givenAuctionIsCreated { // Perform the call @@ -494,6 +568,7 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_narrowAnchorTickWidth() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAnchorTickWidth(1) @@ -509,6 +584,7 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_narrowDiscoveryTickWidth() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenDiscoveryTickWidth(1) @@ -525,6 +601,7 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_baseTokenAddressLower() public givenBaseTokenAddressLower + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated { @@ -549,6 +626,7 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_baseTokenDecimalsHigher() public givenBaseTokenDecimals(19) + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated { @@ -577,6 +655,7 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_baseTokenDecimalsLower() public givenBaseTokenDecimals(17) + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated { @@ -605,8 +684,9 @@ contract BaselineOnCreateTest is BaselineAxisLaunchTest { function test_activeTickRounded() public givenBPoolFeeTier(10_000) - givenCallbackIsCreated givenFixedPrice(1e18) + givenBPoolIsCreated + givenCallbackIsCreated givenAuctionIsCreated { // Perform the call diff --git a/test/callbacks/liquidity/BaselineV2/onCurate.t.sol b/test/callbacks/liquidity/BaselineV2/onCurate.t.sol index b536e7c4..877fb65c 100644 --- a/test/callbacks/liquidity/BaselineV2/onCurate.t.sol +++ b/test/callbacks/liquidity/BaselineV2/onCurate.t.sol @@ -26,7 +26,12 @@ contract BaselineOnCurateTest is BaselineAxisLaunchTest { // [X] it reverts // [X] it does nothing - function test_lotNotRegistered_reverts() public givenCallbackIsCreated givenAuctionIsCreated { + function test_lotNotRegistered_reverts() + public + givenBPoolIsCreated + givenCallbackIsCreated + givenAuctionIsCreated + { // Expect revert bytes memory err = abi.encodeWithSelector(BaseCallback.Callback_NotAuthorized.selector); vm.expectRevert(err); @@ -37,6 +42,7 @@ contract BaselineOnCurateTest is BaselineAxisLaunchTest { function test_notAuctionHouse_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenOnCreate @@ -51,6 +57,7 @@ contract BaselineOnCurateTest is BaselineAxisLaunchTest { function test_curatorFeeNonZero_reverts(uint256 curatorFee_) public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenOnCreate @@ -67,6 +74,7 @@ contract BaselineOnCurateTest is BaselineAxisLaunchTest { function test_curatorFeeZero() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenOnCreate diff --git a/test/callbacks/liquidity/BaselineV2/onSettle.t.sol b/test/callbacks/liquidity/BaselineV2/onSettle.t.sol index 11d94ded..8b1988de 100644 --- a/test/callbacks/liquidity/BaselineV2/onSettle.t.sol +++ b/test/callbacks/liquidity/BaselineV2/onSettle.t.sol @@ -36,6 +36,7 @@ contract BaselineOnSettleTest is BaselineAxisLaunchTest { function test_lotNotRegistered_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenAddressHasQuoteTokenBalance(_dtlAddress, _PROCEEDS_AMOUNT) @@ -51,6 +52,7 @@ contract BaselineOnSettleTest is BaselineAxisLaunchTest { function test_notAuctionHouse_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenOnCreate @@ -69,6 +71,7 @@ contract BaselineOnSettleTest is BaselineAxisLaunchTest { function test_lotAlreadySettled_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenOnCreate @@ -87,6 +90,7 @@ contract BaselineOnSettleTest is BaselineAxisLaunchTest { function test_lotAlreadyCancelled_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenOnCreate @@ -104,6 +108,7 @@ contract BaselineOnSettleTest is BaselineAxisLaunchTest { function test_insufficientProceeds_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenOnCreate @@ -119,6 +124,7 @@ contract BaselineOnSettleTest is BaselineAxisLaunchTest { function test_insufficientRefund_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenOnCreate @@ -134,6 +140,7 @@ contract BaselineOnSettleTest is BaselineAxisLaunchTest { function test_success() public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated givenOnCreate @@ -184,6 +191,7 @@ contract BaselineOnSettleTest is BaselineAxisLaunchTest { function test_floorReservesPercent_fuzz(uint24 floorReservesPercent_) public + givenBPoolIsCreated givenCallbackIsCreated givenAuctionIsCreated { diff --git a/test/callbacks/liquidity/BaselineV2/withdrawReserves.t.sol b/test/callbacks/liquidity/BaselineV2/withdrawReserves.t.sol index 93b53871..5a0d691c 100644 --- a/test/callbacks/liquidity/BaselineV2/withdrawReserves.t.sol +++ b/test/callbacks/liquidity/BaselineV2/withdrawReserves.t.sol @@ -15,6 +15,7 @@ contract BaselineWithdrawReservesTest is BaselineAxisLaunchTest { function test_notOwner_reverts() public + givenBPoolIsCreated givenCallbackIsCreated givenAddressHasBaseTokenBalance(_dtlAddress, 1e18) { @@ -26,7 +27,7 @@ contract BaselineWithdrawReservesTest is BaselineAxisLaunchTest { _dtl.withdrawReserves(); } - function test_noReserves_returnsZero() public givenCallbackIsCreated { + function test_noReserves_returnsZero() public givenBPoolIsCreated givenCallbackIsCreated { // Perform callback vm.prank(_OWNER); uint256 reserves = _dtl.withdrawReserves(); @@ -37,6 +38,7 @@ contract BaselineWithdrawReservesTest is BaselineAxisLaunchTest { function test_success() public + givenBPoolIsCreated givenCallbackIsCreated givenAddressHasQuoteTokenBalance(_dtlAddress, 1e18) {