Skip to content
@contractdna on X

Docs

How DNA works, explained two ways. Pick yours; you can switch any time.

01What this is

DNA is an ERC-20 on Ethereum, traded against ETH in one Uniswap v4 pool. The pool's hook, DNAHook, charges a dynamic fee whose policy is a swappable module: what CT calls a new hook, DNA calls a mutation. An AI agent proposes parameters for registered modules through ModuleRegistry (registering new Safe-approved bytecode needs level 10). A separate pipeline, the Sequencer, builds standalone game contracts and new modules (see The Sequencer). Each change waits in a public 1 h queue, then runs in shadow and on a slice of live trades before it is kept or rolled back.

Token
DNA (ticker DNA), 1,000,000,000 minted once. Burnable, no mint function, no ownerDNAToken.SUPPLY
Pool
ETH/DNA on Uniswap v4, dynamic fee, tick spacing 1, one canonical poolDNAHook.poolKey
Hook
Immutable, no owner, no upgrade pathSPEC §2
Agent
Runs in an Intel TDX enclave on Phala; its address is registry.agent()ModuleRegistry.agent
The Safe
2-of-3 multisig. Cancels, pauses, lowers the level. Can't touch your DNA or the hard limits (see The Safe)ModuleRegistry.safe

02Mutations (CT: hooks)

A mutation is a module, or new parameters for one, that DNA's one Uniswap v4 hook calls. DNAHook itself never changes. A module is a small pure contract: a fee policy the hook calls on every swap (AdaptiveFee) or a split policy FeeVault calls on every distribution (BaselineSplit). A module moves Proposed → Shadow → Canary → Active, one queued registry op per step, and anyone can execute an op once its 1 h delay has passed.

AdaptiveFee:  pips = min(base + mult × volEma / 1e4, cap)
canary fee is clamped to activeFee ± 10,000 pips (±1 point)
  1. Queue SetParams + SetShadow · 1 h
  2. Shadow · 2 h, every 10th swap, fee computed, nothing charged
  3. Queue SetCanary · 1 h
  4. Canary · 4 h, live fee on 100 of every 600 blocks
  • passesPromoteActive, queued 1 h (by the Safe until level 8): it becomes the live fee
  • fails or a kill check firesendCanary (the active fee stays) or rollback (the 2.2% baseline)
Mutation = hook
"Hook" is what CT calls it; "mutation" is DNA's name. Either way: a module the one hook calls, never a new hook contract. DNAHook is immutableDNAHook._staticcallPips → IFeePolicy.projectFee
Who writes them
The AI proposes every one. Today a mutation is a new parameter set for an approved module (an AdaptiveFee plate); brand-new bytecode needs autonomy level 10 and a code hash the Safe approved. ParamSplit, DirectionalFee and SizeTierFee are built and tested; the Safe has not registered them yet. Today the AI tunes AdaptiveFee onlyModuleRegistry.L10_OPS, ApproveCodehash; contracts/src/modules
Launch level
5: shadow, live test, parameters on non-active modules, rollback. Promotion needs the Safe until 8ModuleRegistry constructor level_, L5_OPS
Queue delay
1 h on every op, the agent's and the Safe's alikeModuleRegistry.MIN_DELAY
One experiment
About 8 h: 1 h + 2 h shadow + 1 h + 4 h canary, so at most 3 a day. A stage short of data is extended, up to 3× its lengthengine/src/policy.ts TIMING
Shadow sampling
Every 10th swap, 30,000 gas, failures ignoredDNAHook.SHADOW_EVERY
Canary window
100 of every 600 blocks (the contract requires ≥ 50)ModuleRegistry.MIN_CANARY_WINDOW
Module gas cap
40,000 gas. A revert, a bad return or running out of gas falls back to the 2.2% baseline in the same swapDNAHook.MODULE_GAS_CAP
Breaker
3 module failures within 300 blocks: anyone may roll the fee route back, and the engine's watcher does it at onceDNAHook.BREAKER_WINDOW, ModuleRegistry.BREAKER_N
Launch fee range
Base and cap 10,000–35,000 pips (1%–3.5%), multiplier 0.1×–1.8×script/Launch.s.sol feeBounds
Tuning
At most one parameter change per module per hour. From level 6 the live fee can move anywhere in its range; there is no step limitModuleRegistry.PARAMS_EPOCH
Autonomy levels
0–10. L4 shadow, L5 canary and rollback, L6 tune the live fee, L7 bounty allowance, L8 promote, L9 split modules, L10 register bytecode the Safe approvedModuleRegistry.L4_OPS–L10_OPS
Level changes
Raised only by the Safe, through the queue, ≥ 5 days after the last rollback. Lowered by the Safe instantlyModuleRegistry.LEVEL_RAISE_BLOCKS

03The Sequencer

An off-chain build pipeline. The brain picks what to build and signs the decision. The sequencer's models work in public CI on the public repo and can only open pull requests. The sealed engine re-runs every gate, compiles the merged commit itself and deploys after the public hour. No wallet key ever sits in CI.

  1. Idea → sealed intake → plain spec (builders never see the raw post)
  2. Brain: build or not, signed
  3. Lead plans; workers write contract, page and tests; tester attacks; fixer repairs (≤ 3 rounds); reviewer checks
  4. Brain verdict: ship, rework or kill, signed
  5. Public hour: deploy and funding queued, the Safe can cancel
  6. Sealed engine deploys; the site updates from the release branch
  • fails the gates or 3 roundsdropped, reason published
  • no players for 2 daysretired, ETH back to the Safe, claims stay
Brain
One model call per decision (build, verdict, retire, model swap, idea-round outcome, reward). Each is a signed record with the model, the sha256 of its context and of its inputengine/src/brain.ts
Models
Public registry of every role's model and backup, shown as a table on /models. These are the default models. Swapping one needs a public tryout on fixed test cases, then a public hour, and the Safe can veto. Swapping the brain itself needs two Safe owners to approveengine/models.json, docs/MODELS.md
Spend caps
A daily and a monthly cap on AI spending. Near the cap the sequencer pauses first, then research. Keepers never call a model, so trading, fees and payouts never need the AIengine/src/config.ts LLM
Gates
Fuzz and invariant tests, fork simulation, static analysis, a planted-bug check, a gas cap, no delegatecall, selfdestruct or upgradeability, no new dependencies, no CI edits. The sealed engine re-runs them; CI alone never decides
New games
Standalone contracts with no power over the hook, the fees or other games. Only the Safe can pause one. No user deposits until a higher ladder level
Live cap
At most 3 games live. A 4th retires the one with the fewest players over 2 days
Funding
Safe → Zodiac Roles (one allowed call, GameFunder.fund, bounded amount) → Delay (1 h, the Safe can cancel). GameFunder enforces a weekly budget and a per-game capcontracts/src/games/GameFunder.sol, test/fork/Funding.t.sol
Hook modules
A module the Sequencer builds still needs the Safe's code-hash approval before it can be registeredModuleRegistry.ApproveCodehash
Status
Running in the sealed engine since 11 Oct 2026: the brain, model registry, spend caps, funding path (fork-tested), module library, idea rewards, idea routing, X wallet links and the sequencer's build loop

04Hard limits

The hook is immutable. No proxy admin, no upgrade key, not even for us. These are constants in immutable bytecode. No key can change them, the Safe's included.

Project fee cap
50,000 pips (5.00%): every module's answer is clamped to it. Only the launch tax (blocks 0 to 8) is above itDNAHook.MAX_PROJECT_FEE
Baseline fee
22,000 pips (2.2%) when no module is active or a module fails. With Programmable's fee on top, traders pay 2.5%DNAHook.BASELINE_PROJECT_FEE
Launch fee
The baseline slides linearly from 30,000 to 22,000 pips (3% to 2.2%; 3.3% to 2.5% for traders) over the first hour after pool initialization, then stays at 2.2%. It applies only as the baseline/fallback (no module active, or a module failed). The clock is set once, at initialization. Blocks 0 to 8 pay the launch tax instead (90% down to 10%, to BuybackBurn)DNAHook.LAUNCH_PROJECT_FEE, LAUNCH_DECAY
Platform fee
3,000 pips (0.30%) on top: Programmable's launchpad fee, not ours (the share its profile 3.6.0 binds)DNAHook.PLATFORM_FEE
Canary clamp
±10,000 pips (±1 point) around the active feeDNAHook.CANARY_MAX_DELTA
Supply
1,000,000,000 DNA, minted once. There is no mint function, so supply only goes downDNAToken.SUPPLY
Launch liquidity
Two positions, both owned by 0xdEaD: the whole supply as one DNA-only position, and the launch buy's DNA with the rest of the launch ETH as one full-range position. Bootstrap reverts unless ownerOf == 0xdEaD for eachBootstrap.DEAD
Launch buy
Its DNA is locked in the full-range position. Only the excess the position could not pair, about 47,000 DNA, was burned. Bootstrap ends holding nothingBootstrap.initialize
Launch tax
900,000 pips (90%) in the pool's first block, 100,000 less each block after: blocks 0 to 8 pay 90% down to 10%, plus the platform fee. All of it goes to BuybackBurn. The launch buy itself pays the normal feeDNAHook.LAUNCH_TAX, LAUNCH_TAX_STEP, LAUNCH_TAX_BLOCKS
Launch caps
For 4 minutes after launch: at most 20,000,000 DNA (2% of supply) out of the pool per block, net of sells, and at most 10,000,000 DNA (1%) bought per sending wallet (tx.origin) in all, gross (sells don't count back), enforced from block 4. DNA's own buybacks are never taxed, capped or countedDNAHook.LAUNCH_BLOCK_CAP, LAUNCH_WALLET_CAP, LAUNCH_CAP_WINDOW
Liquidity lock
No liquidity can be added for 4 minutes after launch, except by the launch transaction. Removing liquidity is never blockedDNAHook.LiquidityLocked
Added liquidity
LiquidityVault only adds; it has no withdraw or decrease pathLiquidityVault.add
Queue
1 h minimum delay on every registry opModuleRegistry.MIN_DELAY
Split bounds
Buyback 20–50%, liquidity 20–50%, treasury 10–40%, games 0–20%, summing to 100%. Anything else falls back to 35/35/30/0FeeVault.currentSplit
Game bounds
Draws every 12 h–3 d, prize ≤ 3 ETH, per-wallet cap 0.5–2%, idea reward ≤ 25% of the idea reserveGamePot constants

What can change, inside those bounds: the fee (1%–3.5% at launch), the split, and the game settings.

05Where fees go

Fees are taken in ETH, on the swap's ETH leg. The project fee is minted to FeeVault as ERC-6909 claims; the platform fee goes to PlatformRevenue, whose only recipient is Programmable: it is the launchpad's fee, not DNA's.

fee     = gross × (projectPips + 3,000) / 1e6
project = floor(gross × projectPips / 1e6)   → FeeVault
platform = fee − project                     → PlatformRevenue
baseline = 22,000 + 8,000 × (1 h − elapsed) / 1 h   for the first hour after initialization, then 22,000
  1. Swap pays DNA's fee (2.2% baseline, 1%–3.5% tuned) + Programmable's 0.30% (not ours), in ETH
  2. FeeVault.distribute(), anyone, at ≥ 0.05 ETH
  • 35%BuybackBurn: buys DNA and burns it
  • 35%LiquidityVault: adds liquidity, never removes it
  • 30%Treasury: ETH to the Safe
  • 0% nowGamePot: 70% jackpot, 30% idea rewards. Games share turns on later (up to 20%)
Project fee
2.2% default (2.5% with the platform fee); the AI tunes it inside 1%–3.5%DNAHook.BASELINE_PROJECT_FEE, Launch.s.sol feeBounds
Launch fee
The baseline slides linearly from 30,000 to 22,000 pips (3% to 2.2%; 3.3% to 2.5% for traders) over the first hour after pool initialization, then stays at 2.2%. It applies only as the baseline/fallback (no module active, or a module failed). The clock is set once, at initialization. Blocks 0 to 8 pay the launch tax instead (90% down to 10%, to BuybackBurn)DNAHook.LAUNCH_PROJECT_FEE, LAUNCH_DECAY
Platform fee
0.30% on top, to an immutable recipient: Programmable's launchpad fee, not ours (Programmable profile 3.6.0)DNAHook.PLATFORM_FEE, PlatformRevenue.recipient
Launch split
3,500 / 3,000 / 2,500 / 1,000 bps (buyback / liquidity / treasury / games)BaselineSplit.split
Split fallback
3,500 / 3,500 / 3,000 / 0 if the split module is rolled back. The games stop; nothing else doesFeeVault.BASELINE_*
Buyback
≤ 1 ETH per call, 1 h cooldown (≤ 24 ETH a day), 0.50% price limit. Pays only the 0.30% platform share, no project fee. All bought DNA is burnedBuybackBurn.MAX_SIZE, COOLDOWN
Liquidity adds
Every ≥ 4 h, an ETH-only range 2,000 ticks wide just above the priceLiquidityVault.COOLDOWN, WIDTH
Games
GamePot splits arrivals 70% jackpot / 30% idea reserve, each capped at 15 ETH. Overflow goes to the buybackGamePot.JACKPOT_BPS, POT_CAP, RESERVE_CAP
Who triggers it
Anyone: distribute, process, add and sync are permissionless. The engine's keepers call themFeeVault, BuybackBurn, LiquidityVault, GamePot
2.2%DNA's fee3% in the first hour, after the launch tax (90% → 10%, blocks 0 to 8)+0.30% Programmable launchpad fee (not ours)= 2.5%per trade, all in3.3% in the first hour, sliding to 2.5%

06Holder jackpot

Every DNA holder is in. Tickets are a time-weighted average balance over the draw window, built in the enclave from the full Transfer history and committed on-chain as a Merkle root. One Chainlink VRF v2.5 word, delivered after the list is fixed, picks 10 winners, who split the prize equally (at least 0.25 ETH).

tickets = floor( Σ balance × seconds × mult / (windowSeconds × 10,000) / 1e18 )
mult = 10,000 (×1) for held DNA, the staking weight (×2–×4) for staked DNA
eligible iff the unweighted average balance ≥ minBalance
cap: find L so every wallet above L gets exactly L and L ≤ capBps / 10,000 × Σ tickets
ticket_j = keccak256(abi.encode(rand, j)) mod totalTickets, j = 0, 1, … until 10 distinct wallets (at most 32 tickets)
share = prize / 10; unfilled places and dust stay in the pot
  1. The AI posts the window's rules (cap, minimum, excluded exchanges) with its reasoning, anchored before the window opens
  2. Window closes; the AI posts root, total tickets and holders
  3. 1 h veto: the Safe can cancel, a watchdog rebuilds the list
  4. requestDraw: VRF, 3 confirmations
  5. anyone settles with the leaf and proof of every ticket the walk draws; one transaction pays all 10
  • wallet accepts ETHits share is pushed in the same transaction
  • wallet rejects ETHthat winner claims within 7 days, else the share goes back to the pot
  • ticket's wallet already won or is excludedskipped; the next ticket is drawn
Draw window
24 h by default; the AI sets it within 12–24 h (the chain allows 12 h–3 d). A window is drawn only if its rules were anchored on-chain before it opened; otherwise its pot carries overengine/src/games.ts GAME_POLICY.maxInterval, engine/src/jackpot.ts paramsOf; GamePot.MIN_INTERVAL, MAX_INTERVAL
Per-wallet cap
2%, or 1% while a draw in the last two windows had 100+ wallets. Wallets above the cap are cut down to it. Chain bounds 0.5% to 2%. The cap is per wallet, so one person can split across walletsengine/src/tickets.ts capForWindow, CAP_POLICY; GamePot.MIN_CAP_BPS / MAX_CAP_BPS
Too few wallets
Fewer than 50 eligible wallets: no level fits even a 2% cap, so there is no draw and the pot carries overengine/src/tickets.ts waterfill
Minimum balance
1,000 DNA average over the window (chain bounds 100–1,000,000)engine/src/jackpot.ts JACKPOT_POLICY, GamePot.MIN_BALANCE_FLOOR / CEIL
List veto
1 h after postList; the list must be posted within 24 h of the window's endGamePot.LIST_DELAY, LIST_GRACE
Winners
Ten distinct wallets, equal shares, at most 32 tickets drawn. Fewer wallets in the list means fewer winners; the rest stays in the potGamePot.WINNERS, MAX_TICKETS, settle
Timing target
The AI picks the interval so a draw is worth about 1 ETH, up to 24 h, and changes it only when the move is over 25%engine/src/games.ts GAME_POLICY
Prize
min(pot − VRF top-up, 3 ETH), and at least 0.25 ETH (0.025 per winner) or the draw waits. The top-up refills the VRF subscription to 0.1364 ETH (the whole 0.1364 ETH while the subscription is empty), so the first draw needs a pot of 0.3864 ETHGamePot.PRIZE_CAP, MIN_PRIZE, SUB_MIN
Pot cap
15 ETH; anything above goes to the buybackGamePot.POT_CAP
Gas gate
No draw while the VRF cost would be more than 20% of the prizeGamePot.MAX_COST_BPS
Payout
Each share pushed with 50,000 gas; the settle reverts rather than starve a push. A failed push becomes a claim within 7 d; after that anyone returns it to the potGamePot.PUSH_GAS, CLAIM_WINDOW
VRF stall
No answer in 36 h: the draw is aborted and the same list is requested againGamePot.VRF_TIMEOUT
Excluded on-chain
The Safe, its signers and team wallets, the agent and anchor keys, the protocol contracts, the PoolManager, 0x0 and 0xdEaDGamePot.isExcluded
Excluded off-chain
PlatformRevenue, Bootstrap, and exchange wallets listed in the params before the windowengine/src/tickets.ts
Known limit
The list is fixed before the random number, so a VRF operator who withholds an answer would know the winners first. Bounded by the 3 ETH prize capSPEC §13

07Staking

ConvictionVault holds staked DNA in non-transferable positions. One weight function serves both jackpot tickets and votes.

weight = amount × min(tierMult × streakMult, 40,000) / 10,000
tierMult (hundredths) = 200 / 250 / 300 while the term runs, 200 after
streakMult (hundredths) = 125 at 2 d, 150 at 5 d, 200 at 10 d of position age
Minimum stake
10,000 DNAConvictionVault.MIN_LOCK
Terms
12 h ×2, 3 d ×2.5, 7 d ×3ConvictionVault.term, tierMult
After the term
×2 while it stays stakedConvictionVault.currentWeight
Streak
×1.25 at 2 d, ×1.5 at 5 d, ×2 at 10 dConvictionVault.streakMult
Ceiling
×4 combined (a 7 d term at a 10 d streak is ×4, not ×6)ConvictionVault.MAX_MULT
Not staked
Held DNA counts ×1 for the jackpot. It does not voteengine/src/tickets.ts
Vote eligibility
A position votes once it is 12 h old at the ballot's startConvictionVault.MIN_AGE
Withdraw
Any time after the term in force. recommit starts a new term and keeps the streakConvictionVault.withdraw, recommit
Who can't stake
The Safe, its signers, team wallets and the AI's keysConvictionVault.lock

08Mutation vote

MutationBoard runs ballots over candidate parameter sets. Votes pick what is tested next, never what is kept: the winner still goes through queue, shadow and canary.

Cadence
At most one ballot per 48 hMutationBoard.BALLOT_EVERY
Veto
Voting opens 1 h after the proposal. The Safe can cancel a ballot until it is resolvedMutationBoard.VETO_WINDOW
Voting
24 h, 3 optionsMutationBoard.VOTING
Weight
vault.weightAt(position, ballotStart): staked positions only, streak included. Re-voting moves your weightMutationBoard.vote
Winner
Highest tally; ties and an all-zero ballot go to the lowest indexMutationBoard.winner
Proposer
The agent (level ≥ 5) or the SafeMutationBoard.MIN_LEVEL
1% gate
The AI proposes ballots only while ≥ 1% of supply is staked. Below that it runs its own picks, labelled "AI pick (votes open at 1% staked)"engine/src/games.ts ballotMinStakedBps
On-chain record
ballotRun(ballot, option, registryOpId) while the op is queued, or ballotSkipped(reason)MutationBoard.ballotRun

09Mystery mutation

A commit-reveal on MutationBoard. The payload is a candidate parameter vector; after the reveal it is gated and tested like any other candidate.

commitment = keccak256(salt32 ‖ payload)
Seal
seal(commitment, revealAt), revealAt between seal + 2 d and seal + 7 d. One sealed at a timeMutationBoard.REVEAL_MIN, REVEAL_MAX
Cadence
The engine seals one a week, set to open 2 d 1 h after the sealengine/src/games.ts mysteryEveryS
Reveal
Anyone with the salt and payload (≤ 2,048 bytes), within 24 h of revealAt. After that it can be marked brokenMutationBoard.REVEAL_WINDOW, MAX_PAYLOAD
Outcome
mysteryRun(id, registryOpId) if it passes the gates, else mysteryRejected(id, reason)MutationBoard.mysteryRun
Veto
The Safe can cancelSealMutationBoard.cancelSeal
Check it
The Play page recomputes the commitment in your browser after a revealweb/app/play/MysteryCheck.tsx

10Idea rewards

GamePot pays idea rewards from its idea reserve (30% of the games share). The brain picks each amount inside the contract caps; every reward is escrowed, waits 1 h in public, and the Safe can cancel it.

  1. A build ships, or a fee experiment is kept
  2. The brain signs a reward record and calls queueReward(to, amount, ideaRef)
  3. 1 h public queue: the Safe can cancelReward
  • after 1 hanyone calls payReward: ETH is sent to the recipient
  • push failsa 7-day claim, like an unclaimed prize; unclaimed, it returns to the jackpot
Queue
queueReward(to, amount, ideaRef) by the agent (level ≥ 5, not paused) or the Safe; the amount leaves the reserve at once, into escrowGamePot.queueReward
Size
At least 0.01 ETH and at most 25% of the idea reserve per rewardGamePot.queueReward, MAX_REWARD_BPS, MIN_REWARD
Daily cap
At most 25% of the reserve queued per rolling day (measured at the day's first queue)GamePot.MAX_REWARD_BPS, dayBudget
Public hour
Payable 1 h after it is queued. payReward is open to anyone and pays only while the agent is not pausedGamePot.payReward
Veto
The Safe can cancelReward until it is paid; the escrow goes back to the reserveGamePot.cancelReward
Never to
The Safe, the agent, the protocol's contracts or the excluded list: the same set the jackpot excludesGamePot.isExcluded
Reserve cap
15 ETH; arrivals above it go to the buybackGamePot.RESERVE_CAP
Who is paid
IdeaMarket ideas: the submitter's address, read on-chain. X ideas: the wallet the author's X account linked by posting @contractdna and one 0x address, and nothing else (public; any other words make it no link). The first link counts at once and gets one reply; a change takes effect 48 h later, announced on the site. At most 3 link posts a dayengine/src/bindings.ts BINDING_LIMITS, rewards.ts REBIND_DELAY_MS
Hold
A reward with no linked wallet, or no room under the caps, waits up to 30 days. Then it is dropped and the money stays in the reserveengine/src/policy.ts REWARD_HOLD_DAYS
Status
Fee-idea rewards and X wallet links run now. Build-idea rewards start with the Sequencer's first shipped buildengine/src/idea-queue.ts
Events
RewardQueued, RewardPaid, RewardCancelledGamePot

11Ideas

Two doors into IdeaMarket: X mentions, filtered by the engine and submitted by the agent at zero stake, or a direct on-chain submit with a stake. Each 24 h round settles on its own.

A = stake on accepted ideas, R = stake on rejected ideas
accepted position s → s + floor(s × R / A);  rejected → 0;  void → s;  A = 0 → everyone gets s back
  1. Post on X tagging @contractdna
  2. Gate: any account, no links, no duplicates
  3. Screen: fee / build / impossible / question / chat / joke / shill / spam, scored out of 30; then 1 idea per person per round (live: per UTC day)
  4. Top 16 of the round submitted at the start of the next
  • outcome proposed in timefinal 24 h later unless the Safe cancels; accepted backers split the rejected stakes
  • no outcome within 3 danyone finalizes the round as void: every stake refunded
Round
24 hIdeaMarket.ROUND_LENGTH
Direct submit
≥ 10,000 DNA opening stake (refundable) + 1,000 DNA burnedIdeaMarket.MIN_SUBMIT, SUBMIT_FEE
Stake limits
≥ 1,000 DNA per stake; ≤ 1,000,000 per address per round; ≤ 2,000,000 per ideaIdeaMarket.MIN_STAKE, MAX_PER_ADDRESS, MAX_PER_IDEA
Slots
128 a round: 112 public, 16 for the agent's X intakeIdeaMarket.MAX_IDEAS, MAX_AGENT_IDEAS
Outcome
The Safe or the agent proposes within 3 d of the round's end; final after 24 h; the Safe can cancelIdeaMarket.RESOLVE_WINDOW, MIN_DELAY
Lock-up
At most about 5 d (24 h round + 3 d + 24 h)SPEC §10.2
Who judges
"Accepted" means picked for implementation after research and a red team. The oracle is the team's agent: the brain judges each round and signs the outcome. It is public for 1 h before the agent proposes it on-chain, and 2 Safe owners can veto it; then the Safe has 24 h to cancelSPEC §10.1, engine/src/ideas.ts

12Genome Vaults

GenomeVaults is an ERC-721 with at most 50 live tokens. A mint locks exactly 200,000 DNA in the contract; a burn returns it with the vault's unclaimed ETH in the same transaction. Only the Safe funds it, over an exact block window of fee inflows, and the ETH is shared per eligible vault through an accumulator.

fund(fromBlock, toBlock): fromBlock must equal fundedThrough (no window skipped or paid twice); value + carry split per eligible vault, the remainder carried
pending(id) = accPerToken − max(debt, accAfter[mintSeq + 1]); a vault minted since the last fund earns from the one after it
Live vaults
At most 50; a burned slot goes to the next mint, lowest free slot firstGenomeVaults.MAX_LIVE, _takeSlot
Deposit
Exactly 200,000 DNA per mint, returned in full by burn; nobody else can move itGenomeVaults.DEPOSIT, mint, burn
Funding
The Safe only, over the block window since the last fund, finalized blocks only. The signers decide the amount; their script proposes half of the treasury's fee share in the windowGenomeVaults.fund, engine/scripts/vault-fund.ts
Eligibility
A vault joins at the first fund after its mint and earns from every fund after thatGenomeVaults.pendingCount, eligible
Transfer
A standard ERC-721; unclaimed ETH stays with the vault, so a buyer gets it. 2.5% royalty to the SafeGenomeVaults.ROYALTY_BPS
Admin
No owner mint, no upgrade. The Safe can pause new mints only, never a burn or a claimGenomeVaults.setMintPaused
Art
50 images, one per slot, named in on-chain metadata with a strand that grows with what the vault earnedGenomeVaults.tokenURI
On X
Every mint, fund and burn is a plain post with its transaction; a reply about the vaults states only what the contract saysengine/src/vaults.ts

The vaults earn only what the Safe sends. A fund is a signed Safe transaction over a public block window; nothing here is automatic, and nothing is promised.

13How to check us

Three things are checkable: where the agent key lives, which code holds it, and what it decided. None of it is needed for the safety of your tokens; the contracts bound every key.

Enclave
The agent key is made and kept inside an Intel TDX machine on Phala. Phala's key service releases it only to code on the on-chain allow-list/proof
Allow-list
A DstackApp on Ethereum owned by a 1 h timelock: the first code version is allowed when the app is created, every later change waits 1 h in public, and only the Safe can propose or cancel one/proof
Status
Live since 11 Oct 2026. The release record (image digest, compose hash, measurements, log key) is pinned, and /proof checks a fresh quote against it/proof
Records
Every decision is an enclave-signed record: the model's output plus the chain data it judged, by block hashengine/src/records.ts
Brain decisions
Signed records carrying the model and the sha256 of its context and inputengine/src/brain.ts
Models
The public registry lists every role's model and backup (table on /models). These are the default models. A swap is a signed model-change record: a public tryout on fixed test cases, then a public hour, and the Safe can veto. Swapping the brain itself needs two Safe owners to approveengine/models.json
Anchors
anchor(root, uri) on ModuleRegistry. The agent's queue ops wait until their record's anchor is mined; each day's log head is anchored tooModuleRegistry.anchor
In your browser
/proof checks a fresh TDX quote, the compose hash and any record's signatureweb/app/proof
From the CLI
node scripts/verify.ts checks the same against Intel's collateral serviceengine/scripts/verify.ts
Jackpot lists
A separate watchdog with no keys rebuilds every ticket list and pages the Safe on a mismatchengine/scripts/watchdog.ts
Not claimed
That a text really came from a given model, or that the system is "trustless". Trust remains in Intel TDX, Phala's governance and the Safe/proof

14The Safe

The Safe is a 2-of-3 multisig whose address is immutable in every contract. Its fast powers only stop things; anything else it does goes through the same public 1 h queue as the agent.

Instant brakes
cancel any queued op, pauseAgent, lowerLevel, rollback, endCanaryModuleRegistry.cancel, pauseAgent, lowerLevel, rollback
Game vetoes
cancelList (jackpot), cancelBallot, cancelSeal, cancelReward, cancelDrawInterval, cancelOutcome (ideas)GamePot, MutationBoard, IdeaMarket
Queued like anyone
register modules, set parameters, promote, raise the level, rotate the agent key, approve bytecode: all public for 1 h firstModuleRegistry.queue
Cannot
Change any constant (5% cap, supply, queue delay, split bounds), alter the hook, remove liquidity, move anyone's DNA or staked DNA, or take the jackpot or the idea reserveSPEC §1, §13
Receives
The 30% treasury share of project fees, in ETHFeeVault.distribute
Also
Telegram /halt, /mute and /delete for signers: they only stop the engine or its posting, or remove one of its own posts/proof

15Risks

Read this before you buy, stake or submit anything.

Price
DNA can lose all its value. Nothing here promises a price or a return
Code
The contracts are new. They have tests, fuzzing, invariant suites and static analysis; no third-party audit is published in the repocontracts/audit/slither.md
The fee
From level 6 the AI can move the live fee anywhere in 1%–3.5% once an hour, with no step limitSPEC §3
Jackpot
A random draw. The prize is capped at 3 ETH and draws pause when the pot or the gas makes them uneconomic. It is not a yieldGamePot
Idea market
Stakes on rejected ideas are lost. Funds can be locked about 5 days. The judge is the team's agent and the Safe can vetoIdeaMarket
Sequencer
AI-written contracts can have bugs. The gates and the Safe lower the risk without removing it. New games start without user deposits
Dependencies
Intel TDX, Phala, Chainlink VRF, Uniswap v4, Programmable, the three Safe signers and the AI model providers
Uniswap
A future Uniswap protocol fee would apply on top of DNA's feesSPEC §2
Other pools
Anyone can open another DNA pool (Uniswap v2, v3 or v4 without DNA's hook, or another exchange), and nobody can stop it. Trades there pay nothing to the buyback, liquidity, treasury or games; their fees go to whoever funds them. Wallets and aggregators may route through them when they quote better, or before they support the hook. Only the pool on the trade page funds DNA; the engine lists every other one it finds there, with the share of volume they takeDNAHook._beforeInitialize
Who can play
18+. You decide whether the games are legal where you live