From 0cf3d13d855242331ceec634c0fa5e5432ebeefc Mon Sep 17 00:00:00 2001 From: Eric Zhong Date: Thu, 21 May 2026 17:35:39 -0400 Subject: [PATCH] fix: require graduation for lbp params --- snapshots/AuctionTest.json | 2 +- src/ContinuousClearingAuction.sol | 5 ++-- .../btt/auction/lbpInitializationParams.t.sol | 26 +++++++++++++++++++ .../initializeDistribution.t.sol | 1 + 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/snapshots/AuctionTest.json b/snapshots/AuctionTest.json index 3f1bd9cf..642b056b 100644 --- a/snapshots/AuctionTest.json +++ b/snapshots/AuctionTest.json @@ -1,5 +1,5 @@ { - "Auction bytecode size": "20323", + "Auction bytecode size": "20415", "checkpoint_advanceToCurrentStep": "180672", "checkpoint_noBids": "166644", "checkpoint_zeroSupply": "117018", diff --git a/src/ContinuousClearingAuction.sol b/src/ContinuousClearingAuction.sol index 89535640..1adaa95f 100644 --- a/src/ContinuousClearingAuction.sol +++ b/src/ContinuousClearingAuction.sol @@ -130,12 +130,13 @@ contract ContinuousClearingAuction is } /// @inheritdoc ILBPInitializer - /// @dev The calling contract must be aware that the values returned in this function for `currencyRaised` and `tokensSold` - /// may not be reflective of the actual values if the auction did not graduate. + /// @dev Reverts if the auction has not graduated, since `currencyRaised` and `tokensSold` are not actual settled + /// values for an unsuccessful auction. /// @dev Protocol fees are queried from the controller at call time and may differ from fees at auction creation. function lbpInitializationParams() external view returns (LBPInitializationParams memory params) { // Require that the auction has been checkpointed at the end block before returning initialization params if ($lastCheckpointedBlock != END_BLOCK) revert AuctionIsNotFinalized(); + if (!_isGraduated()) revert NotGraduated(); // Subtract the protocol fee from the currency raised uint256 currencyRaised = currencyRaised(); uint256 protocolFeeAmount = diff --git a/test/btt/auction/lbpInitializationParams.t.sol b/test/btt/auction/lbpInitializationParams.t.sol index 6853232e..a196a3ed 100644 --- a/test/btt/auction/lbpInitializationParams.t.sol +++ b/test/btt/auction/lbpInitializationParams.t.sol @@ -6,6 +6,7 @@ import {MockContinuousClearingAuction} from 'btt/mocks/MockContinuousClearingAuc import {MockProtocolFeeController} from 'btt/mocks/MockProtocolFeeController.sol'; import {LBPInitializationParams} from 'liquidity-launcher/src/interfaces/ILBPInitializer.sol'; import {ERC20Mock} from 'openzeppelin-contracts/contracts/mocks/token/ERC20Mock.sol'; +import {IAuctionStorage} from 'src/interfaces/IAuctionStorage.sol'; import {IContinuousClearingAuction} from 'src/interfaces/IContinuousClearingAuction.sol'; contract LBPInitializationParamsTest is BttBase { @@ -32,10 +33,34 @@ contract LBPInitializationParamsTest is BttBase { _; } + function test_WhenAuctionIsFinalizedButNotGraduated(AuctionFuzzConstructorParams memory _params) + external + givenAuctionIsFinalized + { + // it reverts with {NotGraduated} + AuctionFuzzConstructorParams memory mParams = validAuctionConstructorInputs(_params); + mParams.token = address(new ERC20Mock()); + mParams.parameters.requiredCurrencyRaised = 1; + + MockContinuousClearingAuction auction = + new MockContinuousClearingAuction(mParams.token, mParams.totalSupply, mParams.parameters, address(0)); + + ERC20Mock(mParams.token).mint(address(auction), requiredTokenDeposit(mParams)); + auction.onTokensReceived(); + + vm.roll(auction.endBlock()); + auction.checkpoint(); + + assertFalse(auction.isGraduated(), 'auction is graduated'); + vm.expectRevert(IAuctionStorage.NotGraduated.selector); + auction.lbpInitializationParams(); + } + function test_WhenAuctionIsFinalized(AuctionFuzzConstructorParams memory _params) external givenAuctionIsFinalized { // it returns the correct initialization params AuctionFuzzConstructorParams memory mParams = validAuctionConstructorInputs(_params); mParams.token = address(new ERC20Mock()); + mParams.parameters.requiredCurrencyRaised = 0; MockContinuousClearingAuction auction = new MockContinuousClearingAuction(mParams.token, mParams.totalSupply, mParams.parameters, address(0)); @@ -65,6 +90,7 @@ contract LBPInitializationParamsTest is BttBase { mParams.token = address(new ERC20Mock()); mParams.parameters.currency = address(0); mParams.parameters.validationHook = address(0); + mParams.parameters.requiredCurrencyRaised = 0; MockProtocolFeeController protocolFeeController = new MockProtocolFeeController(); MockContinuousClearingAuction auction = new MockContinuousClearingAuction( diff --git a/test/btt/auctionFactory/initializeDistribution.t.sol b/test/btt/auctionFactory/initializeDistribution.t.sol index b5cad41d..152cd3f8 100644 --- a/test/btt/auctionFactory/initializeDistribution.t.sol +++ b/test/btt/auctionFactory/initializeDistribution.t.sol @@ -35,6 +35,7 @@ contract InitializeDistributionTest is BttBase { _params.totalSupply = uint128(bound(_params.totalSupply, 1, type(uint128).max)); _params.parameters.currency = address(0); _params.parameters.validationHook = address(0); + _params.parameters.requiredCurrencyRaised = 0; MockProtocolFeeController protocolFeeController = new MockProtocolFeeController(); factory = new ContinuousClearingAuctionFactory(address(protocolFeeController));