Search projects, hackathons, sponsors and tech

    ← All projects

    Ground State

    Ethereum as a place: every address a spot, contracts as buildings, ground you dig for with CREATE2

    Demo

    About

    Ground State is a black-and-white world you walk through in the browser, with other people, where the map is the Ethereum address space itself. An address is forty hex digits; each digit picks one cell of a 4×4 grid, forty times over, so every address has exactly one place and neighbours share a prefix. Nothing about the map was designed: it falls out of how Ethereum names things. Everything standing in the world is real and follows the chain's own rules. A contract stands as a building: size from the length of its code, shape from the code's hash, darkness from its balance. A wallet lies as a plate with a post for every token it holds, the post as tall as that holding's share of the total supply, the name and amount cut into it. The current block crosses the sky in real time, every transaction a ribbon from sender to receiver; reverted ones shake and are drawn back. No scenery, no mock data, and no content we author. What the chain says is what stands, and what happens. Empty ground cannot be bought. It is dug for. A plot is a contract deployed with CREATE2, so its address, and therefore its place, is fixed by a salt before the contract exists. Digging searches salts on every core of your machine; every attempt is a place, the closest is kept, and there is no threshold: stop whenever you like, and one transaction on Sepolia makes the closest place found your contract, forever. It rises out of the ground as a blueprint of the building it will be. A plot is a proxy its owner can act on: write into it (the words stand out of the wall as the drawing becomes a building), name it under groundstate.eth via ENSv2, point it at any contract they deployed so that code runs at this very address, seal the code for good, or hand the plot on. A subgraph on The Graph Network indexes every plot; The Graph's Token API shows which wallets hold it. Other people are here as figures: their digging is seen, their claims stand up on every screen within seconds, and all see a place seen by one. World ID's Selfie Check says who here is a person: a person's word about a place is kept at once, a stranger's when five agree. It weighs; it does not gate. The world is thirteen digits deep today, a metre being one cell of the thirteenth digit. A depth switch is next: the same chain at any level, and every level down makes standing this close sixteen times the work, so ground dug beside something today is worth more with every level. This is an early version: the world stands, the game around it is not written yet, and writing it is the first work after the hackathon. Live at gs.bwtoken.io, open source under MIT.

    How it's made

    Everything is written during the event: one contributor, 288 commits, 132 tests. Disclosed per the rules: the concept and plan predate it (they were the application), and the monochrome palette and mark are reused from bwtoken.io by the same author. The world is a WebGL2 engine of our own in TypeScript, no framework, no textures, no models, no asset pipeline. Geometry is generated from what an account is. Terrain is the address tree hashed: six depths of the tree are the octaves; the height of a cell is the keccak of its address prefix so that anyone can compute the hill under an address. There is no colour, so everything is said with light: one low sun, filmic tone mapping instead of clipping, ordered dithering only against banding. Buildings stand on foundations rather than flattening the ground. The onboarding tour drives the world through a Driver interface (look, walk, type, press) so the same code plays itself. Digging is CREATE2 salt mining in an AssemblyScript WebAssembly module, on every core via workers, about seven million attempts a second per thread. The first twenty bytes of the salt must be the claimant's address, which the factory checks: a salt seen in the mempool is worthless to anyone else, and the check costs nothing because it is one hash per attempt rather than two. Finds are kept in the browser, filed by chain, factory and owner. The Plot contract (Solidity 0.8.28, Foundry) is an EIP-1967 proxy: owner and implementation in the EIP-1967 slots, note and seal in a namespaced slot, so any implementation is written like an ordinary contract; seal() fixes the code for good. Verified on Sourcify and Blockscout. Two earlier factories stand as relics. The Graph: two products composed. A subgraph over three generations of the factory, every plot a dynamic data source, indexing owner, every inscription, implementation, seal, name and salt; the mapping decodes the address into 80-bit x/y coordinates and the metre cell and 256-metre tile, so "everything near here" is one query. Published to The Graph Network and read through the gateway. The Token API (Pinax) supplies what a mainnet wallet holds: every fungible token with its supply. Our live server (Node, ws) is the one asker for everybody, keeps the keys out of the browser, and streams holdings as ndjson, a line per token as each supply arrives, so a wallet's posts rise one by one. It pushes the whole world to every page over the socket on joining, then only what changed; Blockscout and the factory's logs are fallbacks. Subgraph Studio throttled the whole subgraph with 429s on day eight, which is why there is one asker and why the subgraph was published. ENSv2 on Sepolia, on its own terms. groundstate.eth is registered on the ENSv2 beta and points its subregistry at a PermissionedRegistry of ours, deployed through the VerifiableFactory. One contract, Names, holds the only ROLE_REGISTRAR and ROLE_UNREGISTER on it and is also the ENSIP-10 wildcard resolver for the whole subtree: addr is the plot, text(description) is what the owner wrote, text(url) opens the world there. Labels are registered with a role bitmap of zero, so a name's token cannot leave its place; about three hundred labels are reserved. The world resolves names through UniversalResolverV2 and travels by them. All ENS and chain calls are built by hand: a selector and a word, less code than a library. World ID Selfie Check, as a weight, not a gate. IDKit runs in a vanilla TypeScript page (no React); the RP signature is made on the live server with @worldcoin/idkit-server and the proof is verified against developer.world.org/api/v4/verify. The server keeps a token hash and its expiry for the credential's ninety days and nothing about anybody. A person stands in grey, a stranger in white; a person's word about a revealed place is kept at once, a stranger's counts a fifth. The first live check passed in production on 13 September. Our notes on the docs and the Developer Portal are in docs/world-id-feedback.md. Hacky and proud of it: the runes cut into posts and walls are a small stroke alphabet of our own, and the key is deliberately not documented; the walker turns into a spinning auger while digging, with ground chips whose rate is the hash rate; and the whole page turns over, black or white, world included.