STEPPER Home

Docs

STEPPER is an 8-bit processor built out of NAND gates, one at a time, by a program in a public repository. It runs in a browser, in a terminal, and inside a contract on Robinhood Chain, and all three walk the same gate table.

Everything on this page is a number you can check. Where a figure comes from a build, it says so; where it comes from the chain, the address is printed beside it. If a claim here cannot be checked, it is a bug in this page.

The fastest way to start. npx stepper-cli runs the processor in your terminal. No wallet, no account, no clone, no dependencies. It prints one line per clock edge.

The processor

ST-8 is described structurally: tools/netlist/st8.js composes an ALU, a register file, a decoder and a program counter out of a single primitive, nand(a, b). There is no Verilog, no synthesiser and no imported netlist.

NAND gates placed2,425
Removed by the optimiser264
Shipped2,161
Flip-flops167
Registers16, eight bits each
RAM256 bytes
ROM1,024 words, 25 bits each

Eleven per cent of the die turned out to be doing no work, and the only way to find that out was to build it first. The build refuses to write a netlist unless every check passes: 1,052,672 exhaustive ALU vectors, then the whole processor against an independent model written deliberately in + and & so that it can disagree.

The instruction set

Thirty-two instructions, and all thirty-two are used, because the opcode field is five bits wide and thirty-two is what five bits addresses. The full table is on the front page, live, lighting up as the processor executes.

The instruction set is what falls out of the gates rather than a specification the gates were built to satisfy. That is the whole difference between this and an emulator.

The clock

function step(uint256 inValue) external;

No owner check. No keeper. No schedule. Whoever pays the gas takes the step, and the event records them as that cycle's sponsor. A chip runs exactly as fast as somebody is willing to pay for and stalls when nobody thinks the next cycle is worth it.

That is not a limitation being worked around. It is a price signal on a machine whose clock belongs to nobody.

The contracts

Robinhood Chain, id 4663. Every one of these is ownerless.

Gate array·
Chip factory·
Card renderer·
Token·

The gate array is pure, stateless and has no constructor argument, so it is deployed once and every chip that will ever exist points at that one address. It is the expensive half of a launch and nobody pays for it twice.

Read them back yourself. spec() on the gate array returns the gate count, the flip-flop count and every field offset. If it does not say 2,161 and 167, something other than this project is at that address.

Launching a chip

One transaction on the launchpad does four things: it deploys a processor carrying your program, launches a token against it on the venue's curve, mints you an ERC-721 deed, and records each in the other.

Venue fee0.0005 ETH
Gas, measuredabout 5,050,000
All in, at the price when this was writtenabout 0.0013 ETH
Your opening buyoptional, spent in the same transaction

What you choose:

Everything else belongs to the venue and is quoted rather than promised: the supply is a billion, the curve holds all of it, and none of that is ours to set.

The fee recipient is yours. The factory always names the sender as the token's creator. It never names itself, and there is a test that asserts it from the venue's side rather than from the factory's, because the venue reads a zero as "whoever called me" and that would have been us.

The card

Each chip's ERC-721 carries an image drawn on chain by ChipRenderer, a pure function with no storage and no owner. It takes the chip's address and returns an SVG. There is no server to keep paying for, so the picture disappears when the chain does and not before.

The lattice is the chip's address, three bits per cell. No two cards are alike, and nobody can change one after a mint, including us.

The launchpad shows the card before you pay, and it is not a mock-up: the factory deploys with CREATE, so the address is keccak(factory, nonce) and the nonce is public. If somebody mints first the nonce moves and so does the address, which the page says under the picture.

The CLI

npx stepper-cli
Packagestepper-cli
Size30 kB, ten files
Dependenciesnone, at all
RequiresNode 20 or newer
stepper                          forty cycles of the default program
stepper --prog selftest          the self-test, to its halt
stepper my.asm --in 42           your own program, your own input byte
stepper my.asm --cycles 500 -q

The netlist in that package is the netlist this repository verified, and the assembler is the one the browser uses. It runs the processor locally and does nothing else: it does not read a deployed chip and does not talk to a chain.

The token

NameStepper CPU
SymbolSTEP
Decimals18
Total supply1,000,000,000, fixed at creation
Contract·

There is no team allocation, no presale, no vesting schedule and no mint function. Those are not promises: the curve holds the entire supply from the moment the launch is created, so there is nothing to allocate and nothing to unlock.

STEP does not pay a dividend and there is no mechanism by which it could. Nothing about holding it entitles the holder to a payment of any kind. What it is for is the clock: a processor with no oscillator needs somebody to want the next edge enough to buy it.

Where the fees go

Four mechanisms, at three different stages. The stage is part of the description here, not a footnote: a contract that is written and a contract that is deployed are different claims, and this table says which is which so nobody has to guess.

Launch fee 0.0005 ETH per chip, to the venue. The factory keeps none of it. Live.
Creator fee 2% of trades, credited to an escrow and claimed from it. Live, and unclaimed.
Fee router Splits what it collects 70 development / 30 cycle reserve, along shares fixed at construction. Written, not deployed. 25 checks in a real EVM, and no withdrawal path anywhere in its ABI.
Cycle rebate Pays whoever advances a chip a clock edge, out of a reserve. Written, not deployed. One non-view function in the whole contract, no owner, and the rate is immutable once set.

The rebate pays for work, never for holding

A chip advances when somebody pays for the next edge. step() is not payable, the chip holds no balance, and there is no withdrawal path in it — a chip cannot fund its own next cycle, and nothing in the design is heading there. The rebate is a reserve that makes wanting the next edge cheaper.

The only way to be paid by it is to make a chip take a cycle. Holding the token does nothing in that contract and there is no function that would let it. That is the difference between an incentive and a distribution, and it is not a wording choice: a reserve that pays for work is one thing, and a reserve that pays for holding is a different instrument with a different regulator.

The reserve is funded from supply this project bought on the open market, under the venue's cap of 5% held per wallet, on the same curve as everybody else. It is a purchase, not an allocation. There is still no team allocation and nothing unlocks into it.

One cost, stated here rather than discovered later: a chip records msg.sender as its sponsor, so an edge bought through the rebate records the rebate contract in the chip's log, not you. A cycle you want your own address against is one to buy from the chip directly, and that path is open to everybody and always will be.

There is no automatic buyback, and there cannot be

The venue supports a buyback that spends part of the fee buying a token back. For STEP it is off, it was set that way in the launch transaction, and it is fixed: buybackEnabled() reads false and there is no call that changes it. Anybody can check that in one request, which is why it is written here rather than left unsaid.

A chip launched through the launchpad can turn it on — the choice belongs to whoever launches it, and the design panel shows the consequence either way. For STEP itself that decision was made once and cannot be remade.

Checking any of it

Four ways, in increasing order of effort:

  1. npx stepper-cli, and watch the gate count switch.
  2. The workbench, which runs the same netlist in a browser tab with nothing installed.
  3. Clone the repository and run npm run silicon. If it writes a netlist that differs from the committed one, that is a finding.
  4. Call spec() and program() on any chip and replay every cycle it has taken from its own logs.
The point of all four. None of them requires trusting this page. That is deliberate, and it is why the numbers here are small and specific rather than large and round.