ACCRETION

A cross-chain living monument. Bitcoin remembers the piece; Ethereum lets it live.

Whitepaper v1By mdvbtc.ethBitcoin Ordinals × Ethereum
◆ Art + renderer inscribed on Bitcoin ◆ Ownership + mutation on Ethereum
Abstract ACCRETION is a collection of 3,333 3D monoliths whose entire renderer, textures, shaders and world logic are inscribed on Bitcoin as a single recursive Ordinal, while ownership and every mutable trait live on an Ethereum contract. Each token is a pure function of its URL: the Ethereum contract writes the piece's current state into the query string of the Bitcoin-inscribed engine, so the same on-chain artwork renders every token's live state everywhere it is embedded. Every monolith rises on the same age curve, so age alone never separates two pieces. What separates them is height: a holder locks pieces into orbit around one Core and they pour their own height into it, so the Core grows visibly taller and the donors grow visibly shorter. Height is the only score, the only currency, and it is conserved between pieces rather than issued. There is no token and no emission anywhere in the design. Every completed orbit also rolls for things that cannot be bought at any price: companion creatures, growth charges, and the grant-only Crown and Skull. Nothing renders off-chain; nothing is stored on a server.
01 The idea

Two chains, one object

Most on-chain art picks a side. Fully on-chain generative work usually lives on Ethereum, where storage is expensive and the art must stay tiny. Ordinals put rich art on Bitcoin, but Bitcoin has no expressive contract layer to give that art an evolving life. ACCRETION uses each chain for what it is best at.

Bitcoin is the permanence. The engine (a Three.js three/webgpu renderer with all of its textures, shaders and world data) is inscribed once as a recursive Ordinal. It is immutable, hostless, and will render for as long as the inscription exists.

Ethereum is the life. A contract holds ownership and every trait that can change: growth, color, companions, accreted height, and won status. It is the single source of truth for state, and it is where holders act.

The join between them is deliberately simple, and it is the core trick of the whole system.

02 The engine

animation_url = inscription + query string

The Ethereum contract's tokenURI sets a token's animation_url to the Bitcoin-inscribed engine plus a query string of that token's on-chain state:

The join

https://ordinals.com/content/<engine-inscription>?seed=…&biome=…&shape=…&tends=…&growths=…&hue=…&transfers=…&mintUnix=…&boostStart=…&dormant=…&crown=1&skull=1

The engine reads all of its state from that string and renders deterministically: same parameters in, same pixels out. There is no off-chain metadata and no server in the render path. Because the render is deterministic and seed-driven, a static thumbnail can be pre-computed and cached, and a headless render service produces the marketplace preview image from the same parameters. When state changes on Ethereum, the parameters change, and the same inscription renders the token's new state everywhere it is embedded.

The engine is one HTML file: an importmap that remaps three/* to on-chain recursive inscriptions, then one module. It runs on WebGPU with materials driven by TSL node graphs, a full post-processing stack (bloom, ambient occlusion, cinematic grade, day and night lighting tied to Bitcoin block time), and a strict content-security policy: on the inscription host it can fetch nothing off-chain, so the art is genuinely self-contained.

03 DNA

Birth traits, derived from a seed

Every token's birth DNA is derived deterministically on-chain from a per-token seed (keccak256(id, chainId, contract)), not stored, so it is immutable and free. The descriptor turns those numeric trait ids into names, render parameters, and the OpenSea attributes list.

12 biomes
Biome
The material world: glacier, basalt, malachite, umber, bismuth and more. Sets palette, water, weather and fauna.
7 shapes
Shape
The monolith form: obelisk, spire, ziggurat, leaning, shattered, twisted, cairn. Drives silhouette, taper and lean.
reef
Species
The native coral form every piece is born with: its first growth, before anything is tended.
sky
Sky & Terrain
Clear, nebula or aurora above (some clear skies carry drifting voxel clouds that thicken when Bitcoin blocks fill); scattered, grid or organic ground below. Under that, the seed shapes the land itself (isles, highlands, mesas, atoll, caldera, karst or river valleys), so no two pieces share a coastline. Sky is scored into rarity.
~5%
Secret
A rare floating, glowing crystal near the monolith. Guaranteed and gold on the legendary biome.
~2%
Visage
A rare voxel face carved into the stone. A binary yes / no rarity filter.

Shape, sky, secret and visage each contribute rarity points that resolve to a Tier (Common through Legendary). Four independent post-filter treatments (aberration, anamorphic, woodcut, CRT) roll at roughly two percent each and stack, purely cosmetic and never scored. Note that Crown and Skull are not birth traits: they are won, never rolled (see section 07).

04 What a holder controls

One thing you set, everything else you play for

Ownership on Ethereum is what makes the Bitcoin art evolve. Each action is an on-chain write that changes the token's state, so the descriptor emits new render parameters and the piece is different everywhere it renders. Every mutation emits ERC-4906 so marketplaces re-pull the changed metadata.

The line between what is set and what is earned is deliberate and absolute. One cosmetic is yours to set at will, from your own wallet, for gas:

Nothing else has a price. Growths and companions are not purchasable in any quantity of ETH: the only source for either is the roll that ends an orbit (section 07). A won growth arrives as a charge, which the holder spends later choosing the coral form for each, so a grown piece still looks like its owner's decisions rather than a slot machine's output. Every piece is born with one growth already, its native Species coral, and can reach fifteen in total.

The holder-facing surface for all of it is the Evolve app, which reads and writes the same contracts the tokenURI reads.

05 Time & lineage

It grows with the chain, and remembers its passage

A monolith is never static. Its natural height is a function of age: it accretes stone quickly when young, eases off past a knee point, then keeps growing forever but log-slowly, so even a century-old piece is still rising. Age is measured against the token's Ethereum mint timestamp, its native clock.

Lineage leaves marks. Every transfer is counted on-chain and carved into the piece as an impact crater, so a monolith that has changed hands many times wears that history in its stone. The result is that two pieces with identical birth DNA diverge over time into visibly different objects, shaped by how they were held and played.

06 Orbit & Core

Lock worlds together to grow one taller

Orbit looks like staking and is deliberately not staking: nothing is deposited, nothing is issued, and the reward comes out of another piece rather than out of thin air. It is non-custodial. A holder chooses one piece as a Core and locks other pieces into orbit around it as donors. Orbiting pieces never leave the wallet; they simply cannot be transferred while the orbit runs, enforced through ERC-5192 (minimal soulbound): the token exposes locked(tokenId) and emits Locked, which is what marketplaces read to show the lock. Each lock is an expiry set to the exact end of the orbit window, so pieces unlock on their own the moment the orbit completes, and no lock can ever last longer than 31 days.

The lock lives in the token itself, because only the token can refuse its own transfer. The orbit bookkeeping and the height it moves live in a separate, swappable satellite. While an orbit runs, the donors pour height into the Core; when the window elapses every piece unlocks by itself, and anyone can release the orbit to fold the height in for good.

Height is spent, not printed

This is the part that makes it a game rather than a yield. A donor does not lend height, it gives it: the Core rises by exactly what the donors fall, so the collection's total height is unchanged by any orbit. A tall Core is not merely early, it has consumed other worlds' stature to get there, and the donors wear that in their silhouettes.

One rule keeps the economy closed: you can only give away what you grew yourself. A piece's pouring budget is measured against the shared age curve alone and never against height it received, so the same growth can never circulate twice. No piece can be poured below a floor set just under the birth height, which also means a piece born today has a small budget immediately and can play on day one.

A lone piece can orbit itself: it pours its own height and takes nothing back, so its tower genuinely shortens. This is how a single-piece holder takes part in the height economy at all, and it is honest to say what it is not. A solo orbit spends one piece's height, so it buys one piece's worth of odds, and one piece's worth of odds is small. It is participation and a long shot, not a route to accumulating prizes. Orbiting is a game of pooled stature, and pooling is what it rewards.

On the piece

The Core renders small donor worlds orbiting it, each streaming a thread of lightning-like energy into its accretion seam in that donor's own hue. A donor, meanwhile, renders dormant: desaturated toward its biome tone, its light siphoned down into a sink at its foot. The mechanic is legible directly in the art.

Locking the Core too means it cannot be sold out from under its orbiters, and there is one active orbit per Core at a time. The height actually spent, donors multiplied by rate multiplied by duration, is the input to the roll in section 07: odds are priced per metre consumed, so nothing is won without something being spent.

07 The roll

Everything that cannot be bought comes from here

When an orbit completes, the Core draws for four separate outcomes. Nothing in this list has a purchase path at any price, which is the entire point of it.

Crown and Skull are grant-only: they can never come from a seed roll, only from winning here, which makes them an unfakeable status signal. A single roll can pay more than one of the four, and a piece accumulates them over separate orbits.

Odds are priced in height, per metre spent

The chance scales with the height the orbit actually consumed, not with how long it ran or how many wallets were involved. Twenty donors for a fortnight buys twenty donors' worth of spent stature and no more, so there is no way to farm the roll without genuinely shortening towers. A long shot is cheap, a real chance is expensive, and both cost exactly what they look like they cost.

No odds the contract will accept can reach a cap for any orbit the Orbit contract will accept. That is enforced in code rather than promised, because a binding cap would quietly make splitting one long orbit into several short ones the better play, and the design should never reward gaming its own shape.

Fair randomness without an oracle

Ethereum cannot read Bitcoin block data trustlessly, so the roll uses native Ethereum entropy through a commit-reveal on a fixed future block. Releasing an orbit (which anyone may do) credits its Core with an unrolled roll. Only the Core's current holder can roll it, which seals the draw to a near-future block, so nobody else can start the clock on your roll; a permissionless reveal then rolls from that block's hash. Because the block is committed before its hash is known, roll timing cannot be ground for a favourable draw. Miss the block-hash window and the roll is simply forfeit, so the height spent stays the real cost per attempt and there is no free re-roll. A Core finishes its last roll before it can orbit again, so a new credit can never overwrite an unrolled one. This is the one part of the system that mints value from chance, so it is kept small, isolated, and confined to a satellite the token does not depend on.

08 Seasons

Standings that reset, so arriving late is not arriving too late

A season runs one Bitcoin difficulty epoch, roughly two weeks. One biome carries a growth boost for its season, rotating so every part of the collection gets its turn. At the boundary the standings are struck and the leaders take something that keeps: a mark on the tower, a seasonal companion, or both.

Crucially, a season scores height moved during that season, poured out or taken in, not lifetime total. A Core that snowballed in season one starts season four level with everyone else, which is what stops the leaderboard from ossifying into a permanent ranking of whoever showed up first. Moved rather than gained is what keeps the smallest holder in the contest: pouring is per piece, so a donor inside a twenty-piece orbit gives exactly as much as a lone piece orbiting itself, and the two score the same. Cores still rank highest, which is right, since a Core consumed other worlds to get there. Seasonal companion species are winnable only while their season is open, and kept forever once won.

09 Architecture

An immutable token, swappable everything else

The contracts follow a strict split so the token can stay permanent while the collection keeps growing new features.

The token is an ERC721SeaDrop subclass, so minting, allowlists, phases and pricing are handled by OpenSea's shared SeaDrop protocol and configured in OpenSea Studio. Because the token carries an on-chain tokenURI, it onboards as a native OpenSea Scheduled Drop. Royalties are enforced through ERC-2981 and the ERC-721C transfer-validator so they hold on compliant markets.

10 On-chain functions

The moving parts

A reference to the public surface a holder or integrator touches. view reads state; write mutates; gated is restricted to an authorized caller.

Token ERC721A + SeaDrop, immutable
traits(uint256) → AccretionTraitsview
Seed-derived birth DNA: biome, shape, species, terrain, sky, secret, visage, post-filter mask, tier. Recomputed on read, never stored.
tokenURI(uint256) → stringview
Routes to the swappable descriptor, which returns the full base64 JSON with the image and animation_url. Before the reveal every piece returns the same sealed placeholder: its animation_url is the engine in prereveal mode, one fixed gray world with no traits.
attune(uint256 id, uint16 newHue)write
Set the piece's hue. Recolors coral and accents. The only thing a holder sets directly.
kindle(uint256 id)write
Light the summit beacon. Still on the token and callable, but no longer offered in the Evolve app, so nothing drives it. Documented because the function exists, not because it is part of the holder surface.
locked(uint256) → boolview
ERC-5192 soulbound flag. True until the lock expires; transfers revert meanwhile.
syncLock(uint256)   syncLocks(uint256[])write
Re-announce a piece's CURRENT lock state as ERC-5192 Locked / Unlocked. Permissionless and stateless: it can only emit what locked() already returns, so it cannot lie and grants nobody anything. It exists because orbit locks EXPIRE rather than being released, so without it nothing would ever emit Unlocked and an indexer would keep a freed piece soulbound forever. Measured on OpenSea: a metadata refresh alone does not clear the flag.
setOrbitLock(uint256, uint64 until)   pokeMetadata(uint256)gated
Lock a piece until a timestamp (at most 31 days out; the later expiry wins, nothing unlocks early) and emit ERC-4906. Callable only by authorized satellites.
AccretionOrbit satellite: lock + Core-height sink
enterOrbit(uint256 coreId, uint256[] donorIds, uint32 durationSecs)write
Lock the Core and each donor for the window. One active orbit per Core; donors cannot double-orbit; every donor's pour is checked against its budget up front, so a release can never fail on an unaffordable pour. Pass an empty donor list to orbit a lone piece around itself. The height rate is snapshotted at entry, so a later tuning change can neither erase nor inflate a pour already committed to.
release(uint256 coreId)write
After the window (when the locks have already expired), move the poured height from the donors into the Core for good, re-announce every piece's unlocked state, and credit the Core a roll. Permissionless: it can't start anyone's reveal clock, and a faulty prize satellite can never block it.
availableMilli(uint256)   givenMilli(uint256)   naturalMilli()view
What a piece can still pour, what it has poured away, and the natural height every piece shares at this moment. Budget is measured against the age curve alone and never against height received, which is what keeps the same growth from circulating twice.
orbitersOf(uint256)   orbitingCore(uint256)   settledBonusMilli(uint256)view
The donors around a Core, the Core a donor orbits, and a Core's settled accreted height. Read by the descriptor into render params.
AccretionPrizes satellite: companions, growth charges, Crown / Skull
credit(uint256 coreId, uint256 heightSpentMilli)gated
Record an unrolled roll for a completed orbit, priced by the height it consumed. Callable only by the Orbit; commits no block.
roll(uint256 coreId)holder
Seal the credited roll to a near-future block. Only the Core's current holder, so nobody else can start the clock on your roll.
reveal(uint256 coreId)write
Draw off the committed block's hash and grant whatever landed, which may be more than one of the four. Permissionless; forfeit if the block-hash window is missed, so the height spent stays the real cost per attempt and there is no free re-roll.
plant(uint256 id, uint8[] forms)holder
Spend accumulated growth charges, choosing a coral form for each, all in one transaction. You cannot plant what you have not won.
hasCrown(uint256)   hasSkull(uint256)   eligibleCreatures(uint256)   odds(uint256 spendMilli)view
Won bits per piece, which companions a piece could still win right now (core roster minus what it holds, plus whatever season is open), and the four per-outcome odds a given height spend would draw, for the Evolve preview.
AccretionDescriptor swappable presentation
renderParams(uint256)   imageParams(uint256) → stringview
The live animation query string and the birth-state image query string. Thumbnails age in steps (day 0, 1, 2, 4, 7, 14, 21, 30, 45, 60, 90, 180) so each image stays cacheable while still growing with the piece. Both fold in the satellites' state (accreted height, dormant flag, crown and skull, orbiter hues).