Skip to content

On-chain storage

contracts/src/Sonoglyph.sol is an ERC-721 with fully on-chain rendering. Each token preserves the complete record of one descent in contract storage; nothing about the visible artifact lives in external metadata or off-chain JSON.

FieldTypeSource
glyphstringThe 32×16 ASCII art from Kimi
journalstringThe 3-paragraph field journal
audioCidstringIPFS CIDv1 of the WebM recording
sessionCodestring6-char descent code
creatoraddressAddress that completed the descent
mintedAtuint256Block timestamp at mint

Only the audio CID is an off-chain pointer, and even that pointer resolves to a file pinned by us (Pinata) with its CID embedded in the on-chain animation_url so any IPFS gateway can serve it.

Returns a base64-encoded JSON data URI containing two rendered media:

data:image/svg+xml;base64,... — the glyph drawn as monospace text on a black background. This is what marketplaces use for grid previews. It’s a static SVG, no animation, no JavaScript. It’s constructed string-by-string from the on-chain glyph field at tokenURI call time.

data:text/html;base64,... — a self-contained page that renders the glyph plus an <audio> element fetching the recording from an IPFS gateway. One click on a marketplace listing → the user sees the glyph and hears the descent simultaneously.

The HTML is also constructed at tokenURI time. Contract storage holds the raw fields; the renderer composes them on read. This means we can update the visual style by deploying a renderer contract upgrade in future without re-minting tokens (the constructor takes a renderer address; storage is preserved across renderer upgrades).

Three reasons.

1. The glyph is the artifact. We don’t want it to be an IPFS link that could rot. The 32×16 string is ~520 bytes per token; storage cost on Monad mainnet is far below the scale where this becomes a concern.

2. Marketplaces should “just work”. Any marketplace that supports the ERC-721 metadata standard already understands tokenURI returning a data URI. No custom rendering server, no IPFS dependency at the metadata layer.

3. The audio + glyph belong together. Embedding the audio player in animation_url means a marketplace listing is the experience — you don’t need to leave the listing page to hear the descent. The visual and the sound co-arrive.

Only the contract owner (the bridge’s signing wallet) can mint, and it mints to the player’s chosen address.

function mintDescent(
address to,
string calldata glyph,
string calldata journal,
string calldata audioCid,
string calldata sessionCode
) external onlyOwner returns (uint256 tokenId)

We trade trustlessness for curation — every minted token came from a real completed descent the bridge witnessed end-to-end. If the bridge wallet is ever compromised the worst case is junk tokens, not stolen ones.

Sonoglyph is a finite series, hard-capped at the contract level.

RuleWhere it livesWhat it means
MAX_SUPPLY = 250Solidity constantThe 251st mintDescent call reverts with "max supply". There is no setter, not even owner-only — the cap is part of the deployed bytecode for the lifetime of the contract.
One mint per addressmapping(address => bool) hasMintedThe same address can ever receive at most one Sonoglyph. The 2nd call to mintDescent(sameAddress, …) reverts with "already minted".
Lifetime flaghasMinted[to] = true (irreversible)Transferring the token away does not reset eligibility. Once an address is in hasMinted, it stays there forever, even with a zero-balance after transfer.

Together these turn the on-chain set into a small, distributed record: 250 distinct descents, 250 distinct holders. A single collector cannot accumulate the series via a recipient-wallet farm — they would need 250 unique signing wallets to receive the series, and even then the bridge wallet would have to mint to each of them on completed descents the bridge witnessed.

Reads:

uint256 public constant MAX_SUPPLY; // 250
mapping(address => bool) public hasMinted; // recipient → has ever received
uint256 public lastTokenId; // 1-indexed; tokens left = MAX_SUPPLY - lastTokenId

Per mint on Monad mainnet, with current gas levels, a Sonoglyph mint costs a small fraction of a cent. The on-chain string storage dominates the gas; the actual ERC-721 logic is standard OpenZeppelin plus the renderer dispatch.