Problem
Learning to write a smart contract is learning what the machine does with it, and the machine is unusually easy to embed: the Ethereum virtual machine is small, deterministic and has a good open-source implementation in Rust. Yet the places people learn it make them connect a wallet, find a test network with a faucet, or install a toolchain and clone a repository before the first line runs. The casual learner, the one a training or a tutorial reaches, leaves at that step.
The platform already has the two halves of a better answer. It runs strangers' programs in a sandbox that does not trust them (RFC 0010), and it has a model service that can talk about a learner's mistake without sending their code anywhere (RFC 0001, 0011). What it does not have is a chain: no execution engine, no way to ask a public network a question, and no format for an assignment that a machine can grade.
This document decides those three things, and one more: what this is for. The owner's trainings (Go, Rust, networking, and blockchain) share one product, one set of accounts, one place people pay and one community server (RFC 0007, 0009). The EVM is that product's blockchain track, not a product of its own.
Proposal
One embedded machine, four pieces.
Solidity is a language of the sandbox. The sandbox already compiles and runs one file of Go or Rust in a throwaway container with no network (RFC 0010). Solidity joins it as a third row: the file is a contract, the compiler is
solc, and the "program" the sandbox runs afterwards is a harness of ours that compiles the learner's contract together with a hidden test contract, deploys them into an embedded EVM (revm, MIT-licensed, the engine under most Ethereum tooling), calls every test in turn from a fresh copy of the deployed state, and prints a report: each test's name, whether it passed, the gas it used, and, when it failed, the reason the contract gave. Every defence in RFC 0010's table applies unchanged; the only thing the harness adds is a compiler and an interpreter, both of which run inside the sandbox and never outside it. The hidden tests reach the harness the way a program's input does, on standard input, and only the platform's own service ever sends them.The
evmservice. A platform service like the others (RFC 0001's shape: it owns the contract, the caller, the bounds and the record), with:- networks as data. Each public network the platform knows is a row in the service's configuration: its name, its chain id, whether it is a test network, the public endpoints it is reached through (two providers, tried in order), and the list of methods the platform will forward to it. Adding a network is a reviewed line, not a release. A probe asks every network its chain id on a schedule and marks it up, down, or answering as a different chain than it claims, which is the registry's honesty check and the thing a learner sees first.
- a read-only way to ask a network. One call names a network, a method and its parameters; the service forwards it if the method is on that network's list and refuses it in words if not (which method, which network), rather than passing on whatever the endpoint would have said. Every caller has a daily allowance of these calls, and a call has a deadline and a size. What is asked and what came back are never logged; who asked which method of which network is.
- the assignment catalogue. An assignment is a folder in the service's configuration: a brief in both languages, a starter contract, a hidden test contract and a reference solution. The catalogue is read once at start; a folder that is missing a piece stops the service. A learner is given the brief and the starter, never the tests or the solution, and a test in the service proves that. Every assignment has two invariants checked before it ships: the reference solution passes every test, and the starter fails at least one.
- submitting. A signed-in person sends their source for an assignment; the service sends it to the sandbox with the hidden tests, as itself, reads the report, keeps the submission and its result under the person's account, and answers with the report. A person can read their own progress and erase all of their submissions in one call. The source never reaches a log, and a test fails if it ever does.
The playground. A page in this lab where the assignment list, the brief, an editor and the report sit together, and a panel with the networks and a small console for the read-only calls. Behind the sign-in from the first day: a submission is kept, so it needs an owner.
The trainings product. Accounts, entitlements and the community server's roles are decided in RFC 0007 and 0009 and shared by every track. Until the entitlement service exists, which assignments are free is a switch in the service's configuration and every shipped assignment is free; the gate is in the code from the first commit so that the entitlement, when it comes, plugs into one place. The model service gets a tutor later, as one more agent file (RFC 0011): it reads the report and the learner's code and hints, and never hands over the solution.
A diagram is drawn here in the RFCs product; this page does not show diagrams yet.
A diagram is drawn here in the RFCs product; this page does not show diagrams yet.
What this is not. It is not a transaction debugger, a trace viewer or a tool for explaining what happened in someone else's transaction on a live network; none of the calls above take a transaction hash, and none produce a trace. It is an engine for running a learner's own code against assertions, and a registry that says which public network can answer which question. Everything in it derives from public sources: the engine's own repository and book, the compiler's documentation, the Yellow Paper and the improvement proposals, and the public endpoints' documentation.
Bounds that hold everywhere. A test gets a fixed gas allowance, so a loop that never ends is a failed test, not a stuck sandbox; the sandbox's own deadlines and memory limit sit behind that. The report is bounded, the source is bounded, the hidden tests are bounded by the same input limit as any program's input. Every call is audited as the platform's rules require (who, what, how it ended) and never with content.
Alternatives considered
The engine inside the service, no sandbox. The interpreter is a library and could run in the service's own process. Rejected: the compiler in front of it takes a stranger's source and is native code with a history of crashes on hostile input, and a crash in the service is a crash for every caller. Inside the sandbox it costs one container and nothing else.
A second grader. RFC 0008 already has a kata format and an open-source grader. Rejected as the home for this: that grader launches a process, puts a fault proxy in front of it and grades it under load, because Go and Rust katas are servers. A Solidity assignment is one deterministic file with assertions; it is a language of the sandbox, not a kata, and shares the katas' catalogue, accounts and entitlements instead of their runner.
Foundry as the harness. The Solidity toolchain most people use has a test runner that does what the harness does and more. Rejected: it is a toolchain to keep inside a sandbox that fetches nothing, and a learner's assignment would inherit its conventions rather than the platform's. The harness is a few hundred lines on the same engine.
A hosted node or a wallet. Rejected; that is the step the learner leaves at, and the machine is easy to embed.
A trace or a step-by-step view of a run. Useful for teaching, and the engine offers it. Deferred on purpose: the report says which test failed, with the reason the contract gave and the gas it took, and that is what an assignment needs. Anything closer to a debugger is a decision of its own, taken later and in the open.
Decision
Open. Fixed so far: Solidity as a third language of RFC 0010's sandbox, with our own
harness on revm as its program; one evm service with networks as data, a read-only
forwarded call refused by name when a network does not support it, the assignment
catalogue as reviewed folders with two invariants, submissions under an account with
erasure in one call; the playground behind the sign-in; the track's accounts, prices
and community roles shared with RFC 0007 and 0009; none of the debugger's calls; the
tutor and the entitlement gate as follow-ups. Over MCP (RFC 0005) the read-only calls
are tools; submitting is not, until the tutor is the one doing it.
Publication
This lab appears in the Lab section with the playground as its way in. The privacy page gains a paragraph for the playground: what a submission stores, why, for how long and how to erase it. RFC 0010's language table gains a row and its study a measured line. The community server and the prices arrive with RFC 0007's launch, not with this.
Status log
- 2026-09-29: opened, after a prototype on another machine proved the harness (a reference solution passing and a starter failing on real compiled bytecode, with the contract's own revert message as the feedback) and the decision that this is the trainings' blockchain track and not a debugger.
- 2026-09-29: the sandbox speaks Solidity (RFC 0010's log has the row), and the service is built: the networks as data with the probe, the read-only call refused by name, the catalogue with its two invariants checked through the image, submissions kept and erased per person, the read-only calls as MCP tools. Three assignments ship: the dust of a division, a vault drained by re-entry, and a call brought under a gas budget.
- 2026-09-29: one call over a network's state. The machine runs a call against the public state of any registered network at a block, fetching what it touches through the same providers as a forwarded call, each read counted and capped; the answer is what the call would return, the gas, the events, and the reason when it fails. A question about state at a block; no hash goes in, no trace comes out.
- 2026-09-29: the tutor. A third agent of the model service (RFC 0011), one file: from a failed report the playground hands the brief, the learner's contract and the report to the workbench as a question, and the tutor answers with what the failing test means, where to look and the fact behind it, never the solution. It has no tools and no memory; the page pre-fills the question and the learner sends it.
- 2026-09-29: the workbench runs a contract. A Solidity block in an answer, or
/run soliditywith a contract under it, goes to the sandbox as a run with no tests: the harness compiles and deploys it and the card shows its report (RFC 0004's log). The playground stays the place with the tests. - 2026-10-07: Checked: the evm and playground deployments run with no recorded commit, so the running build is not verified. No PR in this repository names this RFC. Open: the decision lists what is fixed so far.