Skip to main content

CCA V2 Program Reference

Complete reference for the CCA V2 (Continuous Clearing Auction) program on Solana.

Program ID: F5DdorN9nawhpQJZkfLYx2SpcWxSTZnwh3ZRyNtXP5do Framework: Anchor 0.29.0

Account Types

The program manages six on-chain account types, plus three additional PDAs for vaults and signing authority.

AuctionConfig

Immutable auction parameters set at creation time.

PDA Seeds: ["cca_auction", authority, auctionId (u64 LE)] Size: 386 bytes (378 + 8 discriminator)

FieldRust TypeDescription
authorityPubkeyAuction creator/admin
auction_idu64Unique auction identifier
base_mintPubkeyBase token mint (tokens being auctioned)
quote_mintPubkeyQuote token mint (currency used to bid)
total_supplyu64Total base tokens offered
floor_priceu128Minimum clearing price (Q96)
max_bid_priceu128Maximum allowed bid price (Q96)
tick_spacingu32Minimum gap between tick prices
start_slotu64Solana slot when auction starts
end_slotu64Solana slot when auction ends
claim_slotu64Solana slot when token claims begin
required_currency_raisedu128Currency threshold for graduation
funds_recipientPubkeyReceives swept quote currency
tokens_recipientPubkeyReceives unsold base tokens
supply_schedule_accountPubkeyAssociated SupplySchedule PDA
auction_block_intervalu64Solana slots per auction block
min_bid_amountu64Minimum bid size
min_new_tick_amountu64Minimum bid to create a new tick
max_ticksu32Max initialized ticks for this auction
tokens_receivedboolWhether base tokens deposited
graduatedboolDeprecated -- graduation is computed dynamically
bumpu8PDA bump seed

AuctionState

Mutable singleton tracking live auction state.

PDA Seeds: ["cca_state", auctionConfig] Size: 357 bytes (349 + 8 discriminator)

FieldRust TypeDescription
auction_configPubkeyParent AuctionConfig reference
clearing_priceu128Current clearing price (Q96)
sum_currency_demand_above_clearing[u8; 32] (U256)Total demand from ticks above clearing
next_active_tick_priceu128Price of next initialized tick above clearing
current_step_indexu32Current supply schedule step index
cumulative_mpsu32Cumulative supply issued (milli-basis-points)
currency_raised_q96_x7[u8; 32] (U256)X7-scaled total currency raised (graduation check)
currency_raised[u8; 32] (U256)Total currency raised
currency_raised_at_clearing_price[u8; 32] (U256)Cumulative currency at clearing price tick
latest_checkpoint_slotu64Solana slot of most recent checkpoint
latest_checkpoint_auction_blocku64Auction block of most recent checkpoint
checkpoint_countu64Total checkpoints created
total_bidsu64Total bids placed
total_ticksu32Total initialized ticks
total_cleared_q96_x7[u8; 32] (U256)X7-scaled total base tokens cleared
currency_sweptboolWhether quote currency has been swept
tokens_sweptboolWhether unsold tokens have been swept
bumpu8PDA bump seed

SupplySchedule

Defines token release rate over time via step-based issuance.

PDA Seeds: ["cca_supply", auctionConfig] Size: Dynamic (depends on number of steps)

FieldRust TypeDescription
auction_configPubkeyParent AuctionConfig reference
num_stepsu16Number of supply steps
total_blocksu64Total auction blocks across all steps
stepsVec<SupplyStep>Supply step definitions
bumpu8PDA bump seed

SupplyStep fields: mps (u32), block_delta (u64), start_block (u64), end_block (u64).

Tick

Price-level node in a singly-linked list (descending by price).

PDA Seeds: ["cca_tick", auctionConfig, price (u128 LE)] Size: 146 bytes (138 + 8 discriminator)

FieldRust TypeDescription
auction_configPubkeyParent AuctionConfig reference
priceu128Price level (Q96)
currency_demand_q96[u8; 32] (U256)Total effective currency demand at this price
next_tick_priceu128Price of next lower tick (0 = end of list)
is_initializedboolWhether this tick has been activated
bumpu8PDA bump seed

Checkpoint

Epoch snapshot tracking cumulative supply, clearing price, and accumulators.

PDA Seeds: ["cca_checkpoint", auctionConfig, auctionBlock (u64 LE)] Size: 324 bytes (316 + 8 discriminator)

FieldRust TypeDescription
auction_configPubkeyParent AuctionConfig reference
auction_blocku64Auction block number
slotu64Solana slot when created
clearing_priceu128Clearing price at this checkpoint (Q96)
cumulative_mpsu32Cumulative supply MPS at this checkpoint
cumulative_mps_per_price[u8; 32] (U256)Settlement accumulator: sum of (delta_mps / clearing_price)
currency_raised_at_clearing_price_q96_x7[u8; 32] (U256)X7-scaled cumulative currency raised at clearing tick
prev_checkpoint_auction_blocku64Previous checkpoint (doubly-linked list)
next_checkpoint_auction_blocku64Next checkpoint (0 = last/final)
statusCheckpointStatusUninitialized / Resolving / Finalized
bumpu8PDA bump seed

Bid

Individual bid receipt tracking position, fill status, and settlement.

PDA Seeds: ["cca_bid", auctionConfig, bidId (u64 LE)] Size: 226 bytes (218 + 8 discriminator)

FieldRust TypeDescription
auction_configPubkeyParent AuctionConfig reference
bid_idu64Sequential bid identifier
ownerPubkeyBidder's wallet address
max_priceu128Maximum price willing to pay (Q96)
amount_q96[u8; 32] (U256)Effective bid amount (Q96-scaled, MPS-adjusted)
raw_amountu64Original quote currency amount deposited
start_slotu64Solana slot when bid was placed
start_auction_blocku64Auction block when bid was placed
start_cumulative_mpsu32Cumulative MPS at time of bid placement
exited_slotu64Solana slot when exited (0 = not exited)
tokens_filledu64Base tokens earned (set at exit, zeroed at claim)
currency_spentu64Quote currency actually spent (set at exit)
bumpu8PDA bump seed

Instructions (13 total)

initialize_auction

Creates the auction configuration, state singleton, and supply schedule.

PropertyValue
Discriminatorsha256("global:initialize_auction")[..8]
Access ControlAuthority (signer)
PrerequisitesNone (first instruction in lifecycle)

Accounts:

AccountTypeMutSignerSeeds
authoritySignerYesYes--
auction_configAuctionConfigYesNo["cca_auction", authority, auction_id LE]
auction_stateAuctionStateYesNo["cca_state", auction_config]
supply_scheduleSupplyScheduleYesNo["cca_supply", auction_config]
system_programSystemNoNo--

Arguments:

FieldTypeDescription
auction_idu64Unique auction identifier
total_supplyu64Total base tokens to auction
floor_priceu128Minimum clearing price (Q96)
max_bid_priceu128Maximum bid price allowed (Q96)
tick_spacingu32Minimum gap between tick prices
start_slotu64Auction start slot
end_slotu64Auction end slot
claim_slotu64Token claim start slot
required_currency_raisedu128Graduation threshold
auction_block_intervalu64Slots per auction block
min_bid_amountu64Minimum bid size
min_new_tick_amountu64Minimum bid for new tick creation
max_ticksu32Max ticks for this auction
supply_stepsVec<SupplyStepInput>Supply schedule step definitions (mps: u32, block_delta: u64)

Validation: total_supply > 0, floor_price > 0, max_bid_price > floor_price, tick_spacing >= 2, start_slot < end_slot, claim_slot >= end_slot, sum of all mps * block_delta must equal 10,000,000 (MPS).


initialize_vaults

Creates the base token vault PDA and sets mint references on AuctionConfig.

PropertyValue
Discriminatorsha256("global:initialize_vaults")[..8]
Access ControlAuthority only (has_one = authority)
Prerequisitesinitialize_auction

Accounts:

AccountTypeMutSignerSeeds
authoritySignerYesYes--
auction_configAuctionConfigYesNohas_one = authority
base_mintMint (Interface)NoNo--
quote_mintMint (Interface)NoNo--
vault_authorityUncheckedAccountNoNo["cca_vault_auth", auction_config]
base_vaultTokenAccount (Interface)YesNo["cca_base_vault", auction_config]
system_programSystemNoNo--
token_programTokenInterfaceNoNo--
rentRentNoNo--

initialize_quote_vault

Creates the quote currency vault PDA.

PropertyValue
Discriminatorsha256("global:initialize_quote_vault")[..8]
Access ControlAuthority only
Prerequisitesinitialize_auction, initialize_vaults

Accounts:

AccountTypeMutSeeds
authoritySignerYes--
auction_configAuctionConfigNohas_one = authority
quote_mintMint (Interface)No--
vault_authorityUncheckedAccountNo["cca_vault_auth", auction_config]
quote_vaultTokenAccount (Interface)Yes["cca_quote_vault", auction_config]
system_programSystemNo--
token_programTokenInterfaceNo--
rentRentNo--

initialize_floor_tick

Creates the floor price tick (sentinel node at the bottom of the tick linked list).

PropertyValue
Discriminatorsha256("global:initialize_floor_tick")[..8]
Access ControlAuthority only
Prerequisitesinitialize_auction

Accounts:

AccountTypeMutSeeds
authoritySignerYes--
auction_configAuctionConfigNohas_one = authority
floor_tickTickYes["cca_tick", auction_config, floor_price LE]
system_programSystemNo--

receive_tokens

Transfers total_supply base tokens from authority's token account to the base vault.

PropertyValue
Discriminatorsha256("global:receive_tokens")[..8]
Access ControlAuthority only
Prerequisitesinitialize_vaults

Accounts:

AccountTypeMutSeeds
authoritySignerYes--
auction_configAuctionConfigYeshas_one = authority
authority_token_accountTokenAccount (Interface)Yes--
base_vaultTokenAccount (Interface)Yes["cca_base_vault", auction_config]
token_programTokenInterfaceNo--

Errors: TokensAlreadyReceived (6118), InsufficientVaultBalance (6117).


create_checkpoint

Core clearing price discovery. Creates or resumes a checkpoint for a given auction block, walking the tick linked list to find the clearing price.

PropertyValue
Discriminatorsha256("global:create_checkpoint")[..8]
Access ControlPermissionless -- anyone can call
PrerequisitesAll setup complete (initialize_*, receive_tokens)

Accounts:

AccountTypeMutSeeds
payerSignerYes--
auction_configAuctionConfigNo--
auction_stateAuctionStateYes["cca_state", auction_config]
supply_scheduleSupplyScheduleNo["cca_supply", auction_config]
checkpointCheckpointYes["cca_checkpoint", auction_config, auction_block LE]
system_programSystemNo--

remaining_accounts: Previous checkpoint PDA (for linking) + Tick PDAs for linked-list traversal.

Arguments: auction_block: u64 -- the auction block number to checkpoint.

info

Checkpoints must be created in strictly contiguous order. The instruction walks up to 10 ticks per transaction call. If more ticks exist, the checkpoint enters Resolving status and must be resumed with additional calls.


place_bid

Places a new bid at a specified max price, transferring quote currency to the vault.

PropertyValue
Discriminatorsha256("global:place_bid")[..8]
Access ControlAny signer (permissionless)
PrerequisitesAt least one checkpoint must exist

Accounts:

AccountTypeMutSeeds
bidderSignerYes--
auction_configAuctionConfigNo--
auction_stateAuctionStateYes["cca_state", auction_config]
bidBidYes["cca_bid", auction_config, total_bids LE]
latest_checkpointCheckpointYes--
bidder_quote_accountTokenAccount (Interface)Yes--
quote_vaultTokenAccount (Interface)Yes["cca_quote_vault", auction_config]
token_programTokenInterfaceNo--
system_programSystemNo--

remaining_accounts: Tick at max_price + previous tick PDA (for linked-list insertion).

Arguments:

FieldTypeDescription
max_priceu128Maximum price bidder will pay (Q96)
amountu64Quote currency to deposit
prev_tick_priceu128Price of preceding tick (insertion hint)

Key Logic: The effective bid amount is amount_q96 = raw_amount * Q96 * MPS / mps_remaining, where mps_remaining = MPS - cumulative_mps. This adjusts for the remaining supply fraction.


exit_bid

Exits a fully-filled or completely-unfilled bid. Computes settlement and refunds unspent quote currency.

PropertyValue
Discriminatorsha256("global:exit_bid")[..8]
Access ControlPermissionless -- anyone can trigger
PrerequisitesAuction ended, end checkpoint finalized

Accounts:

AccountTypeMutSeeds
signerSignerNo--
auction_configAuctionConfigNo--
auction_stateAuctionStateYes["cca_state", auction_config]
bidBidYeshas_one = auction_config
start_checkpointCheckpointNo--
end_checkpointCheckpointNo--
quote_vaultTokenAccount (Interface)Yes["cca_quote_vault", auction_config]
bidder_quote_accountTokenAccount (Interface)Yes--
vault_authorityUncheckedAccountNo["cca_vault_auth", auction_config]
token_programTokenInterfaceNo--

Settlement formula:

  • tokens_filled = amount_q96 * cumulative_mps_per_price_delta / (Q96^2 * mps_remaining)
  • currency_spent = amount_q96 * cumulative_mps_delta / mps_remaining
  • refund = raw_amount - currency_spent

If the auction did not graduate, the bidder receives a full refund with zero tokens.


exit_partially_filled_bid

Exits a bid that was partially filled (at the clearing price for some period). Uses three-period settlement.

PropertyValue
Discriminatorsha256("global:exit_partially_filled_bid")[..8]
Access ControlPermissionless
PrerequisitesAuction ended, end checkpoint finalized

Accounts:

AccountTypeMutDescription
signerSignerNo--
auction_configAuctionConfigNo--
auction_stateAuctionStateYes--
bidBidYes--
start_checkpointCheckpointNoCovers bid start
last_fully_filled_checkpointCheckpointNoLast CP where bid was fully above clearing
next_of_last_fully_filled_checkpointCheckpointNoTransition to marginal
end_checkpointCheckpointNoFinal checkpoint
tick_at_max_priceTickNoFor demand share calculation
quote_vaultTokenAccount (Interface)Yes--
bidder_quote_accountTokenAccount (Interface)Yes--
vault_authorityUncheckedAccountNo--
token_programTokenInterfaceNo--

Three periods:

  1. Fully Filled (start to last_fully_filled): same formula as exit_bid
  2. At Clearing Price (marginal period): pro-rata based on bid.amount_q96 / tick.currency_demand_q96
  3. Outbid (if applicable): zero allocation

claim_tokens

Transfers earned base tokens from vault to bidder after bid exit.

PropertyValue
Discriminatorsha256("global:claim_tokens")[..8]
Access ControlBid owner only
PrerequisitesBid exited, claim_slot reached, auction graduated

Accounts:

AccountTypeMutSeeds
bidderSignerNo--
auction_configAuctionConfigNo--
auction_stateAuctionStateNo["cca_state", auction_config]
bidBidYeshas_one = auction_config, owner = bidder
base_vaultTokenAccount (Interface)Yes["cca_base_vault", auction_config]
bidder_base_accountTokenAccount (Interface)Yes--
vault_authorityUncheckedAccountNo["cca_vault_auth", auction_config]
token_programTokenInterfaceNo--
tip

For tokens launched via the Launchpad, always use TOKEN_2022_PROGRAM_ID as the token program.


set_claim_slot

Allows the authority to update the claim_slot on AuctionConfig.

PropertyValue
Discriminatorsha256("global:set_claim_slot")[..8]
Access ControlAuthority only

Arguments: new_claim_slot: u64 -- must be >= clock.slot and >= end_slot.


sweep_currency

Transfers all raised quote currency from the vault to the funds_recipient after a graduated auction ends.

PropertyValue
Discriminatorsha256("global:sweep_currency")[..8]
Access ControlPermissionless
PrerequisitesAuction ended, graduated, end checkpoint finalized

Accounts:

AccountTypeMutSeeds
signerSignerNo--
auction_configAuctionConfigNo--
auction_stateAuctionStateYes["cca_state", auction_config]
end_checkpointCheckpointNoMust be finalized + final
quote_vaultTokenAccount (Interface)Yes["cca_quote_vault", auction_config]
funds_recipient_accountTokenAccount (Interface)Yesowner = funds_recipient
vault_authorityUncheckedAccountNo["cca_vault_auth", auction_config]
token_programTokenInterfaceNo--

Sets currency_swept = true to prevent replay.


sweep_unsold_tokens

Transfers unsold base tokens to the tokens_recipient. If graduated, sweeps total_supply - total_cleared. If not graduated, sweeps all tokens.

PropertyValue
Discriminatorsha256("global:sweep_unsold_tokens")[..8]
Access ControlPermissionless
PrerequisitesAuction ended, end checkpoint finalized

Sets tokens_swept = true to prevent replay.


Instruction Lifecycle

1. initialize_auction          -- Authority creates config, state, supply schedule
2. initialize_vaults -- Authority creates base vault, sets mints
3. initialize_quote_vault -- Authority creates quote vault
4. initialize_floor_tick -- Authority creates floor tick (sentinel)
5. receive_tokens -- Authority deposits base tokens to vault
---- AUCTION ACTIVE (after start_slot) ----
6. create_checkpoint (ongoing) -- Anyone (keeper) creates epoch checkpoints
7. place_bid (ongoing) -- Bidders place bids
---- AUCTION ENDED (after end_slot) ----
8. create_checkpoint (final) -- Final checkpoint must be finalized
9. exit_bid / exit_partially_filled_bid -- Exit bids (settlement)
10. sweep_currency -- Anyone sweeps raised funds (graduated only)
sweep_unsold_tokens -- Anyone sweeps unsold tokens
---- CLAIM PERIOD (after claim_slot) ----
11. claim_tokens -- Bidders claim earned base tokens (graduated only)

Optional (any time after init):
set_claim_slot -- Authority updates claim slot

Key Invariants

  1. Clearing price monotonicity -- clearing_price never decreases across checkpoints
  2. Checkpoint contiguity -- Checkpoints must be created for consecutive auction blocks
  3. Graduation is computed, not stored -- graduated = currency_raised_q96_x7 >= required_currency_raised
  4. State-before-transfer -- claim_tokens zeros tokens_filled before CPI transfer
  5. Replay protection -- currency_swept and tokens_swept booleans prevent double-sweep
  6. Supply conservation -- sum(tokens_filled) + unsold_tokens == total_supply
  7. Currency conservation -- sum(currency_spent) + sum(refunds) == sum(raw_amount deposited)

Discriminators

Anchor instruction discriminators are sha256("global:<snake_case_name>")[..8]. Account discriminators are sha256("account:<PascalCaseName>")[..8].

InstructionDiscriminator Bytes
place_bid[238, 77, 148, 91, 200, 151, 92, 146]
claim_tokens[108, 216, 210, 231, 0, 212, 42, 64]
exit_bid[146, 67, 26, 184, 83, 215, 78, 14]
exit_partially_filled_bid[86, 66, 82, 227, 228, 7, 213, 147]
caution

Anchor uses the exact Rust function name in snake_case for discriminators. Using camelCase (placeBid instead of place_bid) produces a completely different discriminator and will cause the transaction to fail.

Error Codes

Configuration Errors (6000-6014)

CodeNameMessage
6000TotalSupplyExceedsMaxTotal supply exceeds maximum
6001FloorPriceBelowMinFloor price below minimum
6002TickSpacingBelowMinTick spacing below minimum
6003InvalidSlotRangeStart must be before end
6004SupplyScheduleExceedsMpsSteps sum exceeds MPS
6012InvalidClaimSlotClaim slot must be after end slot
6013TooManySupplyStepsToo many supply steps (max 50)

Bid Errors (6030-6040)

CodeNameMessage
6030BidAmountBelowMinBid amount below minimum
6032MaxPriceExceedsLimitMax price exceeds auction max bid price
6033MaxPriceBelowClearingMax price must be above clearing price
6035MaxTicksReachedMax ticks reached for this auction
6036BidAlreadyExitedBid already exited
6037BidNotExitedBid not exited yet
6039NoTokensToClaimNo tokens to claim

Phase Errors (6050-6053)

CodeNameMessage
6050AuctionNotGraduatedAuction not graduated
6051AuctionNotEndedAuction not ended
6052ClaimPeriodNotStartedClaim period not started
6053TokensNotReceivedTokens not yet received

Arithmetic Errors (6095-6099)

CodeNameMessage
6095ArithmeticOverflowArithmetic overflow
6096ArithmeticUnderflowArithmetic underflow
6097DivisionByZeroDivision by zero
6098MonotonicityViolatedClearing price monotonicity violated