Accounts and PDAs
Every seed#
Two kinds of address. The five state accounts are program-derived from named seeds. The seven token accounts are associated token accounts, derived by the associated token program from an owner and a mint, which is what lets them be sized correctly against a real tokenized stock.
| Account | Derivation | One per |
|---|---|---|
Config | ["config"] | protocol |
Origin | ["origin", id] | origin id (u8) |
Model | ["model", id] | model id (u16, little-endian) |
Policy | ["policy", mint] | launched token |
VenueAccount | ["venue", policy, token_account] | allowlisted destination |
bankroll_auth | ["bankroll_auth", policy] | policy, owns the bankroll |
holder_auth | ["holder_auth", policy] | policy, owns holder_rewards |
fee_key_auth | ["fee_key_auth", policy] | policy, owns fee_key_account |
lp_auth | ["compound_auth", policy] | policy, owns lp_quote and lp_base |
quote_escrow | ATA(policy, quote_mint) | policy |
base_escrow | ATA(policy, base_mint) | policy |
bankroll | ATA(bankroll_auth, quote_mint) | policy |
holder_rewards | ATA(holder_auth, quote_mint) | policy |
fee_key_account | ATA(fee_key_auth, fee_key_mint) | policy |
lp_quote | ATA(lp_auth, quote_mint) | policy. Created by route, not at launch |
lp_base | ATA(lp_auth, base_mint) | policy. Created by compound_lp, not at launch |
Four separate authorities exist because only one associated token account can exist per owner and mint, and quote_escrow, bankroll, holder_rewards and lp_quote are all in the quote mint. init_policy creates five of the seven token accounts; the two lp_auth accounts are created on first use, with the caller paying, so the launch flow's account list did not have to change. LaunchLab's own pool is at ["pool", base_mint, quote_mint], which is the venue's derivation and not this program's.
The VenueAccount seeds bind an allowlist entry to both the policy and one exact token account. That is what makes the entry unforgeable: a caller supplying a balance for the equity calculation must supply an entry that derives to the right address, so a token account belonging to somebody else cannot be passed off as deployed capital.
Config#
initialize and never read or written again. There is no accept_admin instruction, so there is no two-step handover. The field exists and does nothing.claim_fees.compound_lp and buyback_and_burn.to_bankroll_bps.initialize. No instruction can ever change it.Origin#
Policy.risk for policies of this origin.Model#
Policy.model_id refers to.Claude Opus 5.Anthropic.register_model is init_if_needed, so an id is create-or-overwrite. There is no price, no context window and no capability flags: those change, and the chain is a poor place for something that changes.
Policy#
Identity#
register_venue_account rejects anything else.fee_key_account. Not part of LaunchLab's actual claim path. See how a launch works.set_agent.The deployer's choices#
init_policy. Nothing can change it.to_bankroll_bps is capped by Config.max_bankroll_bps.max_risk.passive_deploy refuses any venue whose asset_mint is not this exact key.locked is one way. paused can be set by the guardian and cleared only by the authority, and is also set automatically by a deviating attestation.State and counters#
| Field | Unit | Written by |
|---|---|---|
hwm | quote base units | sweep_profit |
fees_claimed | quote base units | claim_fees, quote leg only |
protocol_fees | quote base units | route |
routed_to_lp | quote base units | compound_lp, by the measured spend |
routed_to_bankroll | quote base units | route |
profit_swept | quote base units | sweep_profit, by what physically moved |
paid_to_holders | quote base units | buyback_and_burn, by the measured quote spent |
tokens_burned | base token units | buyback_and_burn and burn_base_leg |
credit_spent | off-chain metering units | note_credit |
venue_count | count | register_venue_account and revoke_venue_account |
tokens_burned is the only counter denominated in the launched token rather than the quote, and the two mints typically have different decimals.
VenueAccount#
Local, the SPL token account the agent may fund. For Remote, the bridge endpoint funds are sent to on the way out.passive_deploy against the target asset.revoke_venue_account closes the account and returns the rent to the authority, so a revoked entry leaves no on-chain trace beyond the VenueRevoked event. The indexer keeps a revoked flag so the history survives in the API.
The seven token accounts#
| Account | Mint | Who can debit it |
|---|---|---|
quote_escrow | quote | route only |
base_escrow | base | buyback_and_burn, burn_base_leg, by burning only |
bankroll | quote | passive_deploy, agent_fund_venue, sweep_profit |
holder_rewards | quote | buyback_and_burn only |
fee_key_account | the fee key mint | nothing. No instruction debits it. |
lp_quote | quote | compound_lp only, and only through the AMM |
lp_base | base | compound_lp only, and only through the AMM |
Five of the seven are created by init_policy in a single transaction. The two lp_auth accounts are created on first use instead, lp_quote by route and lp_base by compound_lp, with the caller paying the rent, which is why the launch flow's account list did not change when they were added. All seven are associated token accounts and all use the Token-2022 interface, so the program works against either token program without duplicating its contexts.
Two are owned by the policy itself; the other five are owned by their own authority address, because only one associated token account can exist per owner and mint. Which authority owns an account is not bookkeeping: it is what decides how far a forwarded venue instruction can reach, because a passthrough can spend exactly what its one signer owns.
| Account | Owner | Signs with |
|---|---|---|
quote_escrow | the policy | ["policy", mint] |
base_escrow | the policy | ["policy", mint] |
bankroll | bankroll_auth | ["bankroll_auth", policy] |
holder_rewards | holder_auth | ["holder_auth", policy] |
fee_key_account | fee_key_auth | ["fee_key_auth", policy] |
lp_quote | lp_auth | ["compound_auth", policy] |
lp_base | lp_auth | ["compound_auth", policy] |
Enums and bit values#
STABLE = 1 << 0 = 1
MAJOR = 1 << 1 = 2
SOL_MEME = 1 << 2 = 4
STOCK = 1 << 3 = 8
PERP = 1 << 4 = 16
OPTION = 1 << 5 = 32
LP = 1 << 6 = 64
COUNT = 8 (the array has one unused slot)| Enum | Variants | Where it is fixed |
|---|---|---|
Mode | Passive, Agent | init_policy, permanently |
VenueKind | Local, Remote | register_venue_account, permanently for that entry |
The bit position of an asset class is also its index into Config.min_risk_for_class, which is why register_venue_account computes it with trailing_zeros() after requiring that the class is a power of two.