Wrapper and metadata
The wrapper is a display layer with one hard check: the netlist must hash to a registered drawing.
wrap(uint16 epoch, uint8 drawingId, address cpu, uint256 circuitId)
Before minting anything, the wrapper checks, in order:
processor[cpu]is true — the processor is accepted.wrapperOf[cpu][circuitId] == 0— this circuit is not already wrapped.ownerOf(circuitId) == msg.sender— you own the raw circuit.circuitInfo(circuitId).gates != 0— the circuit exists.keccak256(netlist(circuitId)) == drawings(epoch, drawingId).hash— the netlist is the registered drawing.
Then it pulls the original into the contract, increments nextId, writes the mapping in both directions, and mints the TFD.
Stored per token
struct Original {
address cpu; // processor that minted the circuit
uint32 circuitId; // id on that processor
uint32 gates; // burned gate count
uint16 edition; // number in the drawing
uint16 epoch; // series epoch
uint8 drawing; // drawing id
}
All of it is public: original(tfdId) and wrapperOf(cpu, circuitId).
tokenURI
Metadata is generated on chain and returned as a base64 data URI. No server, no IPFS.
{
"name": "TapeFoundry 4-bit Adder #7",
"description": "A circuit taped out on TapeOut, wrapped so its drawing,
gate count and edition travel with the token…",
"image": "data:image/svg+xml;base64,…",
"attributes": [
{"trait_type":"Drawing","value":"4-bit Adder"},
{"trait_type":"Gates","value":46},
{"trait_type":"Edition","value":"6 / 100"},
{"trait_type":"Series","value":1},
{"trait_type":"Processor","value":"0x5a4e…ba83"},
{"trait_type":"Source token","value":"7"}
]
}
The SVG is generated from the same fields: drawing label, gate count, edition, and the processor address in small type.
Edition display
If the circuit had no number at wrap time, the edition reads UNSTAMPED. refresh(id) re-reads the registry and updates the stored edition — useful when a card is wrapped before claiming.
Royalty
ERC-2981, 500 basis points (5%), receiver set at deployment and changeable by the owner. Marketplaces that support ERC-2981 pay it on secondary sales.
unwrap
Burns the TFD, deletes both mappings, and transfers the original back. Token ids are never reused, so the wrapper's numbering accumulates gaps — the count of TFDs ever minted is not the count that exists.