Skip to content
Draft

dev #323

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions script/deploy/DeployAuctionStateLens.s.sol

This file was deleted.

16 changes: 16 additions & 0 deletions script/deploy/DeployCCALens.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {CCALens} from '../../src/lens/CCALens.sol';
import 'forge-std/Script.sol';
import 'forge-std/console2.sol';

contract DeployCCALensScript is Script {
function run() public returns (address lens) {
vm.startBroadcast();

lens = address(new CCALens{salt: bytes32(0)}());
console2.log('CCALens deployed to:', address(lens));
vm.stopBroadcast();
}
}
3 changes: 3 additions & 0 deletions snapshots/TickDataLensTest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"getInitializedTickData max buffer size": "5796546"
}
49 changes: 1 addition & 48 deletions src/ContinuousClearingAuction.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ contract ContinuousClearingAuction is
StepStorage,
TickStorage,
TokenCurrencyStorage,
BlockNumberish,
ReentrancyGuardTransient,
IContinuousClearingAuction
{
Expand All @@ -53,8 +52,6 @@ contract ContinuousClearingAuction is
/// @notice The maximum price which a bid can be submitted at
/// @dev Set during construction using MaxBidPriceLib.maxBidPrice() based on TOTAL_SUPPLY
uint256 public immutable MAX_BID_PRICE;
/// @notice The block at which purchased tokens can be claimed
uint64 internal immutable CLAIM_BLOCK;
/// @notice An optional hook to be called before a bid is registered
IValidationHook internal immutable VALIDATION_HOOK;

Expand All @@ -73,7 +70,7 @@ contract ContinuousClearingAuction is
bool private $_tokensReceived;

constructor(address _token, uint128 _totalSupply, AuctionParameters memory _parameters)
StepStorage(_parameters.auctionStepsData, _parameters.startBlock, _parameters.endBlock)
StepStorage(_parameters.auctionStepsData, _parameters.startBlock, _parameters.endBlock, _parameters.claimBlock)
TokenCurrencyStorage(
_token,
_parameters.currency,
Expand All @@ -84,11 +81,8 @@ contract ContinuousClearingAuction is
)
TickStorage(_parameters.tickSpacing, _parameters.floorPrice)
{
CLAIM_BLOCK = _parameters.claimBlock;
VALIDATION_HOOK = IValidationHook(_parameters.validationHook);

if (CLAIM_BLOCK < END_BLOCK) revert ClaimBlockIsBeforeEndBlock();

// See MaxBidPriceLib library for more details on the bid price calculations.
MAX_BID_PRICE = MaxBidPriceLib.maxBidPrice(TOTAL_SUPPLY);
// The floor price and tick spacing must allow for at least one tick above the floor price to be initialized
Expand All @@ -103,18 +97,6 @@ contract ContinuousClearingAuction is
emit ClearingPriceUpdated(_getBlockNumberish(), $clearingPrice);
}

/// @notice Modifier for functions which can only be called after the auction is over
modifier onlyAfterAuctionIsOver() {
if (_getBlockNumberish() < END_BLOCK) revert AuctionIsNotOver();
_;
}

/// @notice Modifier for claim related functions which can only be called after the claim block
modifier onlyAfterClaimBlock() {
if (_getBlockNumberish() < CLAIM_BLOCK) revert NotClaimable();
_;
}

/// @notice Modifier for functions which can only be called after the auction is started and the tokens have been received
modifier onlyActiveAuction() {
_onlyActiveAuction();
Expand Down Expand Up @@ -281,35 +263,6 @@ contract ContinuousClearingAuction is
return _checkpoint;
}

/// @notice Fast forward to the start of the current step and return the number of `mps` sold since the last checkpoint
/// @param _blockNumber The current block number
/// @param _lastCheckpointedBlock The block number of the last checkpointed block
/// @return step The current step in the auction which contains `_blockNumber`
/// @return deltaMps The number of `mps` sold between the last checkpointed block and the start of the current step
function _advanceToStartOfCurrentStep(uint64 _blockNumber, uint64 _lastCheckpointedBlock)
internal
returns (AuctionStep memory step, uint24 deltaMps)
{
// Advance the current step until the current block is within the step
// Start at the larger of the last checkpointed block or the start block of the current step
step = $step;
uint64 start = uint64(FixedPointMathLib.max(step.startBlock, _lastCheckpointedBlock));
uint64 end = step.endBlock;

uint24 mps = step.mps;
while (_blockNumber > end) {
uint64 blockDelta = end - start;
unchecked {
deltaMps += uint24(blockDelta * mps);
}
start = end;
if (end == END_BLOCK) break;
step = _advanceStep();
mps = step.mps;
end = step.endBlock;
}
}

/// @notice Iterate to find the tick where the total demand at and above it is strictly less than the remaining supply in the auction
/// @dev If the loop reaches the highest tick in the book, `nextActiveTickPrice` will be set to MAX_TICK_PTR
/// @param _untilTickPrice The tick price to iterate until
Expand Down
52 changes: 50 additions & 2 deletions src/StepStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@ pragma solidity 0.8.26;
import {IStepStorage} from './interfaces/IStepStorage.sol';
import {ConstantsLib} from './libraries/ConstantsLib.sol';
import {AuctionStep, StepLib} from './libraries/StepLib.sol';
import {BlockNumberish} from 'blocknumberish/src/BlockNumberish.sol';
import {FixedPointMathLib} from 'solady/utils/FixedPointMathLib.sol';
import {SSTORE2} from 'solady/utils/SSTORE2.sol';

/// @title StepStorage
/// @notice Abstract contract to store and read information about the auction issuance schedule
abstract contract StepStorage is IStepStorage {
abstract contract StepStorage is BlockNumberish, IStepStorage {
using StepLib for *;
using SSTORE2 for *;

/// @notice The block at which the auction starts
uint64 internal immutable START_BLOCK;
/// @notice The block at which the auction ends
uint64 internal immutable END_BLOCK;
/// @notice The block at which purchased tokens can be claimed
uint64 internal immutable CLAIM_BLOCK;
/// @notice Cached length of the auction steps data provided in the constructor
uint256 internal immutable _LENGTH;

Expand All @@ -26,10 +30,13 @@ abstract contract StepStorage is IStepStorage {
/// @notice The current active auction step
AuctionStep internal $step;

constructor(bytes memory _auctionStepsData, uint64 _startBlock, uint64 _endBlock) {
constructor(bytes memory _auctionStepsData, uint64 _startBlock, uint64 _endBlock, uint64 _claimBlock) {
if (_startBlock >= _endBlock) revert InvalidEndBlock();
if (_claimBlock < _endBlock) revert ClaimBlockIsBeforeEndBlock();

START_BLOCK = _startBlock;
END_BLOCK = _endBlock;
CLAIM_BLOCK = _claimBlock;
_LENGTH = _auctionStepsData.length;

address _pointer = _auctionStepsData.write();
Expand All @@ -39,6 +46,47 @@ abstract contract StepStorage is IStepStorage {
_advanceStep();
}

/// @notice Modifier for functions which can only be called after the auction is over
modifier onlyAfterAuctionIsOver() {
if (_getBlockNumberish() < END_BLOCK) revert AuctionIsNotOver();
_;
}

/// @notice Modifier for claim related functions which can only be called after the claim block
modifier onlyAfterClaimBlock() {
if (_getBlockNumberish() < CLAIM_BLOCK) revert NotClaimable();
_;
}

/// @notice Fast forward to the start of the current step and return the number of `mps` sold since the last checkpoint
/// @param _blockNumber The current block number
/// @param _lastCheckpointedBlock The block number of the last checkpointed block
/// @return _step The current step in the auction which contains `_blockNumber`
/// @return deltaMps The number of `mps` sold between the last checkpointed block and the start of the current step
function _advanceToStartOfCurrentStep(uint64 _blockNumber, uint64 _lastCheckpointedBlock)
internal
returns (AuctionStep memory _step, uint24 deltaMps)
{
// Advance the current step until the current block is within the step
// Start at the larger of the last checkpointed block or the start block of the current step
_step = $step;
uint64 start = uint64(FixedPointMathLib.max(_step.startBlock, _lastCheckpointedBlock));
uint64 end = _step.endBlock;

uint24 mps = _step.mps;
while (_blockNumber > end) {
uint64 blockDelta = end - start;
unchecked {
deltaMps += uint24(blockDelta * mps);
}
start = end;
if (end == END_BLOCK) break;
_step = _advanceStep();
mps = _step.mps;
end = _step.endBlock;
}
}

/// @notice Validate the data provided in the constructor
/// @dev Checks that the contract was correctly deployed by SSTORE2 and that the total mps and blocks are valid
function _validate(address _pointer) internal view {
Expand Down
6 changes: 0 additions & 6 deletions src/interfaces/IContinuousClearingAuction.sol
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ interface IContinuousClearingAuction is
error AuctionNotStarted();
/// @notice Error thrown when the tokens required for the auction have not been received
error TokensNotReceived();
/// @notice Error thrown when the claim block is before the end block
error ClaimBlockIsBeforeEndBlock();
/// @notice Error thrown when the floor price plus tick spacing is greater than the maximum bid price
error FloorPriceAndTickSpacingGreaterThanMaxBidPrice(uint256 nextTick, uint256 maxBidPrice);
/// @notice Error thrown when the floor price plus tick spacing would overflow a uint256
Expand All @@ -74,8 +72,6 @@ interface IContinuousClearingAuction is
error InvalidLastFullyFilledCheckpointHint();
/// @notice Error thrown when the outbid block checkpoint hint is invalid
error InvalidOutbidBlockCheckpointHint();
/// @notice Error thrown when the bid is not claimable
error NotClaimable();
/// @notice Error thrown when the bids are not owned by the same owner
error BatchClaimDifferentOwner(address expectedOwner, address receivedOwner);
/// @notice Error thrown when the bid has not been exited
Expand All @@ -84,8 +80,6 @@ interface IContinuousClearingAuction is
error CannotPartiallyExitBidBeforeGraduation();
/// @notice Error thrown when the token transfer fails
error TokenTransferFailed();
/// @notice Error thrown when the auction is not over
error AuctionIsNotOver();
/// @notice Error thrown when the end block is not checkpointed
error AuctionIsNotFinalized();
/// @notice Error thrown when the bid is too large
Expand Down
6 changes: 6 additions & 0 deletions src/interfaces/IStepStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ import {AuctionStep} from '../libraries/StepLib.sol';
interface IStepStorage {
/// @notice Error thrown when the end block is equal to or before the start block
error InvalidEndBlock();
/// @notice Error thrown when the claim block is before the end block
error ClaimBlockIsBeforeEndBlock();
/// @notice Error thrown when the auction is over
error AuctionIsOver();
/// @notice Error thrown when the auction is not over
error AuctionIsNotOver();
/// @notice Error thrown when the bid is not claimable
error NotClaimable();
/// @notice Error thrown when the auction data length is invalid
error InvalidAuctionDataLength();
/// @notice Error thrown when the block delta in a step is zero
Expand Down
4 changes: 2 additions & 2 deletions src/lens/AuctionStateLens.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ contract AuctionStateLens {
error InvalidRevertReasonLength();

/// @notice Function which can be called from offchain to get the latest state of the auction
function state(IContinuousClearingAuction auction) external returns (AuctionState memory) {
function state(IContinuousClearingAuction auction) public returns (AuctionState memory) {
try this.revertWithState(auction) {}
catch (bytes memory reason) {
return parseRevertReason(reason);
}
}

/// @notice Function which checkpoints the auction, gets global values and encodes them into a revert string
function revertWithState(IContinuousClearingAuction auction) external {
function revertWithState(IContinuousClearingAuction auction) public {
try auction.checkpoint() returns (Checkpoint memory checkpoint) {
AuctionState memory _state = AuctionState({
checkpoint: checkpoint,
Expand Down
10 changes: 10 additions & 0 deletions src/lens/CCALens.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import {AuctionStateLens} from './AuctionStateLens.sol';
import {TickDataLens} from './TickDataLens.sol';
import {Multicallable} from 'solady/utils/Multicallable.sol';

/// @title CCALens
/// @notice Lens contract for reading data from deployed CCA auctions
contract CCALens is Multicallable, AuctionStateLens, TickDataLens {}
Loading
Loading