DOOMON ARCSEALED · OWNERLESS

DOOM is a
contract now

The whole 1993 shareware game lives in the bytecode of 92 contracts on Arc, with a 93th holding the code that starts it. Your browser reads all of it from the chain and runs it. No server of ours holds the game — this page is a folder of static files, and every byte of DOOM comes from a node you can point elsewhere.

Contract address
0x4a8ad56B4F925C39D4F891faBAeA93F7Dbf7C62c
See on Argus
2,241,676bytes, on chain, in state
92contracts holding the game
11,487,933gas for the chain to check it
0servers of ours between you and E1M1

Arc allows 24,576-byte contracts, the same as Ethereum. Nothing here needed a special chain — it needed 92 of them.

Pull it from the chain

Every byte comes out of contract bytecode, one eth_getCode at a time. Slower than a CDN. That is the point.

Check it yourself
—shards read
0%of the game
—registry
  • Checked against a digest compiled into this page and published before this chain existed. No endpoint can fake these.
  • the bytes are the DOOM build published before this chain existed — not checked yet
  • the boot code, the only JavaScript that runs, is the published build — not checked yet
  • Computed here, but self-consistency only — the endpoint supplies both sides.
  • every shard sits at the address its own bytes derive — not checked yet
  • the bytes match the hash it declares for them — not checked yet
  • Taken from the endpoint. True if it is honest.
  • it reports Arc (5042) — not checked yet
  • it reports the registry as sealed — not checked yet
  • it reports no owner — not checked yet
  • its own on-chain verify returned true — not checked yet

Reading from Any Arc node will do. The checks do not change.

Anyone can put a file on a blockchain.

We made the blockchain check it.

This one hands you a transaction in which the EVM itself reassembled all 2,241,676 bytes, hashed them, and agreed. Don’t trust us — you can’t, really, and that’s the feature. Three ways to check. The first is the one a hostile node cannot get past; the other two show you how it fits together.

1

Hash it yourself

Pull each shard with eth_getCode, drop the first byte of every one — the STOP that keeps a shard from ever executing — concatenate the rest, and SHA-256 it. It matches the hash the registry declares, and the digest this page was built with — published before this chain held a single byte of the game. The second comparison is the one that matters: a registry that declares the hash of whatever it happens to hold agrees with itself perfectly.

python3 tools/verify-onchain.py 0x18a7f628b707682b9699d39a40e3b01e293dc61e --rpc https://rpc.mainnet.arc.io

No dependencies, no web3 library, its own keccak-256. It also refuses a registry that is unsealed, still owned, or missing the game.

2

The address is the hash

Every shard was deployed through the canonical CREATE2 proxy at a fixed zero salt, so its address is derived from its own bytecode. Recompute it from the bytes you were served and it matches where they came from. Flip one byte and the address moves, so nothing can sit at a shard’s address but that shard’s exact bytes. This one is self-consistency, not identity: the address list and the bytecode come from the same node, so a dishonest one can satisfy it by picking addresses that derive from its own bytes. It is level 1 that stops that, and level 1 is where the argument actually rests.

Read shard 0 from Arc and derive its address here, in this tab, from the bytes alone.

the derivation, in full
initCode = 0x600b5981380380925939f300…  (prefix ‖ STOP ‖ payload)
address  = keccak256(0xff ‖ 0x4e59…4956C ‖ 0x00…00 ‖ keccak256(initCode))[12:]
3

The chain already did it

attest() re-runs the whole reassembly and hash as a transaction, inside the EVM, and leaves a receipt in the log. Measured: 11,400,356 gas, roughly two dollars. It is permissionless, so you can make another one whenever you like — and verify() is the same check as a free call, at 11,487,933 gas.

The registry on the Arc explorer — read verify there yourself, or send attest and leave your own receipt.

Putting a file in transaction history gets you the first one and neither of the others. Nothing on chain can read transaction history from inside a contract, so nothing on chain can check it. Runtime code can be read, which is the whole reason the game is stored as code.

Bytes as bytecode

A contract’s runtime code is just bytes in the state trie. Put a STOP at the front — call it and it halts before reaching your data — and the rest is storage that every full node carries, that costs no rent, and that another contract can read with EXTCODECOPY.

EIP-170 caps that at 24,576 bytes, on Arc as on Ethereum, so 2.24 MB takes 92 contracts. Each one deploys in a single transaction, and the reassembly of all 92 is re-hashed inside one more — under EIP-7825’s 16,777,216 gas ceiling, with room to spare but not much.

The registry is sealed and ownerless. Sealing is not a formality: it only succeeds if the EVM reassembles every asset from chain state and gets the declared hash, so a sealed registry is a statement the chain checked rather than one we made. There is no upgrade function, because a DOOM you could swap out later would not be worth looking at.

Questions

Is this actually DOOM?
It’s linuxdoom-1.10 compiled to WebAssembly with the shareware WAD linked in. Episode 1, Knee-Deep in the Dead. Nine levels, including the one with the invisible pinkies.
Why is loading slow?
Because it is reading 2.2 MB out of contract bytecode instead of a CDN, one eth_getCode at a time. We could cache it in your browser and we deliberately don’t: every load should cost what the claim costs, or the claim means nothing.
Can you take it down?
No. The registry has no owner; sealing cleared it. We can turn this website off. The game stays.
What if this website disappears?
The bytes don’t. The verification script has no dependencies and implements its own keccak — it is one file, and it will still work. That is the whole point of writing it down.
Did you pay id Software?
The shareware episode has been freely redistributable since 1993. That was the deal then and it is the deal now.
Is there a token?
Not yet. If there is one, it will do nothing to the game: the game won’t know it exists and the contracts won’t reference it. That’s the honest way round, and it is also the arrangement that survives a token going to zero.