THE CHAMBER · WHAT IS ON CHAIN
What is on chain
What a stranger can read, run and rely on, without asking us. First what the two contracts let anyone do; then every public function of both, from the verified ABI.
THE TESTA thing is not open if using it needs private code, privileged authority, undocumented state or a server. Every read below needs a node and nothing else; each write says who may call it.
At a glance
Two contracts, one shape: almost everything is a read, and each write says who may send it.
Perception Chamber Canary
0x6f54E1aAE0E9A679A52e5E733645cB11e0cE6127
- functions
- 40 public, 34 of them reads
- writes to the work
- 1:
saveMind, the token's holder, and no operator or approval - the standard
- 12 ERC-721 functions: transfers and approvals, which move the token and nothing else
- tokens
- 1, deployed 2026-09-17
- the surface
- the mind 6 · the learner, as a service 3 · the program 2 · the work 4 · the one write 1 · the pointers and constants 12
The Chamber
0x75FD5A9c4440c38561A0099B216F825b7C6db924
- functions
- 36 public, 29 of them reads
- writes to the work
- 2, both spent:
mint,lock - the standard
- 12 ERC-721 functions: transfers and approvals, which move the token and nothing else
- tokens
- 64, deployed 2026-09-08, locked
- the surface
- the program 3 · the work 6 · the table 6 · the words 1 · the pointers and constants 6 · writes, both spent 2
What anyone can do
The reference below is organised by the nouns the contracts keep. This is the same surface by what you can do with it; every name links to its row. Then four of those things, as commands against any node.
READ
what is there
- brainPERCEPTION
- headPERCEPTION
- educationPERCEPTION
- revisionPERCEPTION
- attributesTHE CHAMBER
- characterSentenceTHE CHAMBER
RUN
make it compute, on the chain or off it
- replayPERCEPTION
- prgPERCEPTION
- prgWithBrainPERCEPTION
- prgTHE CHAMBER
- pagePERCEPTION
VERIFY
check a claim against the rules
- canonicalHashOfPERCEPTION
- requireAdmissiblePERCEPTION
- revisionIdOfPERCEPTION
- tableRowTHE CHAMBER
- seedOfTHE CHAMBER
Four ways to use it
Read a mindPERCEPTION
The head brain of the canary, 834 bytes, from any node.
cast call 0x6f54E1aAE0E9A679A52e5E733645cB11e0cE6127 'brain(uint256)(bytes)' 1 --rpc-url $RPCPull a program out and run it off the chainTHE CHAMBER
Any Chamber token's program, stamped with the block you pulled it at. Save the hex as a file and it is an ordinary C64 program; a browser emulator will boot it.
cast call 0x75FD5A9c4440c38561A0099B216F825b7C6db924 'prg(uint256)(bytes)' 55 --rpc-url $RPC | python3 -c "import sys;open('chamber-55.prg','wb').write(bytes.fromhex(sys.stdin.read().strip()[2:]))"Train a brain without owning a tokenPERCEPTION
The same replay the contract uses to judge a save, as a free call: hand it any admissible 834-byte parent and any lesson stream, get the child back.
cast call 0x6f54E1aAE0E9A679A52e5E733645cB11e0cE6127 'replay(bytes,bytes)(bytes,uint16)' $PARENT_HEX $LESSONS_HEX --rpc-url $RPCPin a revision for everPERCEPTION
Every revision's brain is its own data contract. Read the record, take the blob's address, and read the bytes straight from it - skipping the first byte, which is a STOP.
cast call 0x6f54E1aAE0E9A679A52e5E733645cB11e0cE6127 'revision(uint256,uint32)' 1 3 --rpc-url $RPC # the first word is the brain blob's address
cast code $BLOB --rpc-url $RPC # 0x00 then the 834 bytesWho can change what
Open is a claim about authority before it is a claim about functions. The two contracts answer it differently, and both answers are checkable from the ABI and the chain.
Perception Chamber Canary
No owner, no admin and no upgrade path: the ABI has no function that could add one. The program, the page, the image and the words are four immutable pointers, set at construction and checked against commitments there. One write changes the work's state, saveMind, and only the token's holder may send it; an approved operator cannot, because the holder check is ownerOf itself. The standard's writes move the token and nothing else.
- the only write outside the ERC-721 standard is saveMind. derived from the ABI by the exporter, which refuses to run if that changes
- the holder, and no operator or approval. in the verified source, _holderOf is ownerOf; the four pointers and totalSupply are declared immutable
The Chamber
Two writes, both spent. mint could be called by the minter until the lock, once per id, with that id's row of the table; lock could be called once, only after all sixty-four existed, and it set the minter to the zero address. Since then nothing an address can change remains, and the base program, the image and the renderer were immutable from construction.
- the only writes outside the ERC-721 standard are mint and lock. derived from the ABI by the exporter, which refuses to run if that changes
- the lock, done. locked() true and minter() the zero address since block 25,929,620, 8 September 2026 · tx 0x10118db3… block 25,929,620
Not exposed
Where the surface stops. Each of these is a decision, recorded, not an oversight.
- asking a mind what it would do
- the forward pass and argmax are internal to the learner library, inlined into the token; they run on every lesson of every save and are not callable on their own. For now you run the learner yourself. A decision for the 64-token release.
- the retina table as a view
- the 240-byte vocabulary is a parameter of the interpreter in the code and pinned in the deployed replay; a different world needs a later contract.
- who taught
- no contract can say.
savedByis the address that committed a save, not who held the joystick. - the contract source on GitHub
- the source is public as verified code on Etherscan; a public repository is a parked decision.
Contract reference
Every public function of both contracts, from the verified ABI, grouped by what the contract keeps. Nothing in this section is hand-maintained: a wrong line is fixed at the export and the page is rebuilt.
A line with the mark is the contract’s own @notice, from the verified source. The rest are ours. READ and PURE are the ABI’s own words for a call that costs nothing; PURE reads no chain state at all.
Perception Chamber Canary
0x6f54E1aAE0E9A679A52e5E733645cB11e0cE6127 · deployed 2026-09-17 from 74e9963 · 40 functions, 34 of them reads
the mind
brain(uint256 id)→ bytes | the head brain's 834 bytes, from its blob | READ anyone |
head(uint256 tokenId)→ uint32 | the head revision index of an existing token: 0 at genesis, n after n saves | READ anyone |
revision(uint256 tokenId, uint32 r)→ (address brain, uint32 parent, uint16 lessons, uint16 educationCount, uint8 learner, address education, uint64 savedAtBlock, bytes32 canonicalHash, address savedBy) | revision r of an existing token; 0 is the implicit genesis record | READ anyone |
education(uint256 id, uint32 r)→ bytes | the ordered accepted lesson stream of revision r, from its blob (empty for genesis) | READ anyone |
educationHashOf(uint256 tokenId, uint32 r)→ bytes32 | the education blob's bytes hashed: derived, never stored (zero for genesis) | READ anyone |
revisionIdOf(uint256 tokenId, uint32 r)→ bytes32 | the global, domain-separated name of a revision; derivable by anyone from the record | READ anyone |
the learner, as a service
replay(bytes parent, bytes lessons)→ bytes child, uint16 educationCount | the same replay saveMind runs, as a view, so a save can be checked before it is sent | PURE anyone |
canonicalHashOf(bytes slot)→ bytes32 | sha256 of a slot: the canonical content identity | PURE anyone |
requireAdmissible(bytes slot) | reverts with the reason if slot is not an admissible BRAIN025 slot; returns otherwise | PURE anyone |
the program
prg()→ bytes | the frozen program | READ anyone |
prgWithBrain(uint256 id)→ bytes p | the program with the head brain written at the slot's file offset: a derived file, stamped nowhere, the same thing a holder can make by hand from prg() and brain(id) | READ anyone |
the work
tokenURI(uint256 id)→ string | the token's metadata as a data URI, entirely on chain: the JSON, the image and the page inside it | READ anyone |
json(uint256 id)→ bytes | the JSON before base64, for readers and tests | READ anyone |
page(uint256 id)→ string | the page before base64 | READ anyone |
lineageJSON(uint256 id)→ bytes | the state the page embeds: the head, and at most LINEAGE_WINDOW recent revisions, oldest first. Bounded on purpose, so tokenURI does not grow with the history; every revision stays readable from revision(id, r). | READ anyone |
the one write
saveMind(uint256 tokenId, uint32 expectedParentRevision, bytes32 expectedParentHash, bytes lessons, bytes32 claimedChildHash)→ uint32 revisionIndex, address brain, address education | advance the canonical history of tokenId by one revision | WRITE HOLDER ONLY the token's holder, and no operator or approval |
the pointers and constants
program()→ address | the frozen program's contract, pinned at deploy | READ anyone |
launcher()→ address | the page's contract, pinned at deploy | READ anyone |
image()→ address | the image's contract, pinned at deploy | READ anyone |
metadata()→ address | the words' contract, pinned at deploy | READ anyone |
MAX_BATCH()→ uint16 | the most lessons one saveMind accepts; set at construction, never changed | READ anyone |
LINEAGE_WINDOW()→ uint32 | how many recent revisions the page embeds; the whole history stays readable from revision() | READ anyone |
SUPPLY_CAP()→ uint16 | the collection's ceiling; a deployment mints 1..SUPPLY_CAP tokens in its constructor and never more | READ anyone |
totalSupply()→ uint256 | how many tokens exist | READ anyone |
GENESIS_BRAIN()→ address | the genesis brain's blob: STOP || the blank slot, persisted once by this contract, shared by all | READ anyone |
GENESIS_HASH()→ bytes32 | the blank slot's canonical hash | READ anyone |
LEARNER_BRAIN025()→ uint8 | the learner's identifier, recorded in every revision | READ anyone |
REVISION_DOMAIN()→ bytes32 | the domain separator that names revisions | READ anyone |
And the ERC-721 standard set, for wallets and marketplaces: approve, balanceOf, getApproved, isApprovedForAll, name, ownerOf, safeTransferFrom, safeTransferFrom, setApprovalForAll, supportsInterface, symbol, transferFrom.
The Chamber
0x75FD5A9c4440c38561A0099B216F825b7C6db924 · deployed 2026-09-08 from 4124590 · 36 functions, 29 of them reads
the program
prg(uint256 id)→ bytes | The program this token runs right now: the base with the 42-byte parameter block written. Save it as a .prg and it runs on a real C64; the copy is stamped with the block you took it at. | READ anyone |
renderBlock()→ bytes32 h, uint256 n | The seed and floor number a render uses: the previous block's hash, or a substitute when a client returns zero for it, and that block's number, which is what the floor carves. | READ anyone |
seedOf(uint256 id)→ bytes32 | The 32 seed bytes this token gets at this block: the block hash mixed with the token id, with the three room-class values forced in. Bytes 3, 15, 20 and 28 are the dice's and are left to the hash. | READ anyone |
the work
tokenURI(uint256 id)→ string | the token's metadata as a data URI, entirely on chain | READ anyone |
json(uint256 id)→ bytes | The metadata before base64, for readers and tests. | READ anyone |
attributes(uint8 beh, uint8 col, uint8 wall, uint8 bats, uint8 candle, bytes32 base)→ bytes | the traits, as marketplace attributes | PURE anyone |
description(uint256 id)→ bytes | The description as it reads right now, at this block. | READ anyone |
description(uint256 id, uint256 renderedFrom)→ bytes | The description: what this buddy does, the room he was born into, what moves, the block this render came from in full (the floor carries only its last eight digits), how to take the program, and the credits. | PURE anyone |
image()→ address | the image: the character alone in his colour, an animated SVG built in the contract | READ anyone |
the table
characterName(uint8 beh)→ string | the character a behaviour number names | PURE anyone |
characterSentence(uint8 beh)→ string | the one sentence the description carries for a behaviour | PURE anyone |
wallName(uint8 wall)→ string | a wall code as a word | PURE anyone |
batsName(uint8 bats)→ string | a bats code as a word | PURE anyone |
colourName(uint8 c)→ string | a colour number as a word | PURE anyone |
tableRow(uint256 id)→ uint8 behaviour, uint8 colour, uint8 wall, uint8 bats, uint8 candle | The table row, decoded, for anyone checking the collection's promise. | PURE anyone |
the words
README()→ string | The whole story, one click away on any contract explorer. | PURE anyone |
the pointers and constants
renderer()→ address | One program and one page for all sixty-four, set once here and never again: there is no setter, and the collection cannot be made to mix. | READ anyone |
base()→ address | the base program's data contract | READ anyone |
SUPPLY()→ uint256 | sixty-four | READ anyone |
totalSupply()→ uint256 | how many tokens exist | READ anyone |
locked()→ bool | true since 8 September 2026 | READ anyone |
minter()→ address | the zero address: nobody | READ anyone |
writes, both spent
mint(address to, uint256[] ids) | Mint token ids from the table, in any order, in any number of transactions, until lock(). Each id exists once. | WRITE SPENT nobody: the minter is zero |
lock() | Renounce minting. Only once every one of the sixty-four exists: a lock on an incomplete collection would be permanent, so the contract refuses it rather than trusting a script to check first. After this there is no privileged caller. | WRITE SPENT nobody: already done |
And the ERC-721 standard set, for wallets and marketplaces: approve, balanceOf, getApproved, isApprovedForAll, name, ownerOf, safeTransferFrom, safeTransferFrom, setApprovalForAll, supportsInterface, symbol, transferFrom.
About this page
Generated, never hand-edited: from the pinned compile of the verified sources (forge 1.5.1, solc 0.8.30, evm cancun, bytecode_hash ipfs), exported at 23b47f5 on 2026-09-22 by scripts/export-surface.py. The rows are the ABI’s. The groups, the verbs, the summaries, the gaps and the recipes are ours, and the build is held to the same file, so this page cannot describe a function the contracts do not have. To check it, compile the verified source from Etherscan with the toolchain above and compare the ABI.