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.
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 placed | 2,425 |
| Removed by the optimiser | 264 |
| Shipped | 2,161 |
| Flip-flops | 167 |
| Registers | 16, eight bits each |
| RAM | 256 bytes |
| ROM | 1,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.
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 fee | 0.0005 ETH |
| Gas, measured | about 5,050,000 |
| All in, at the price when this was written | about 0.0013 ETH |
| Your opening buy | optional, spent in the same transaction |
What you choose:
- the program, which is written into ROM at construction and can never change;
- the name and ticker;
- five social links, in the venue's own order;
- an optional creator tax, capped by the venue at ten per cent;
- what the token trades against;
- how much of the opening supply you buy.
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 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
| Package | stepper-cli |
| Size | 30 kB, ten files |
| Dependencies | none, at all |
| Requires | Node 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
| Name | Stepper CPU |
| Symbol | STEP |
| Decimals | 18 |
| Total supply | 1,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:
npx stepper-cli, and watch the gate count switch.- The workbench, which runs the same netlist in a browser tab with nothing installed.
- Clone the repository and run
npm run silicon. If it writes a netlist that differs from the committed one, that is a finding. - Call
spec()andprogram()on any chip and replay every cycle it has taken from its own logs.