evm.codes: an interactive opcode reference that actually executes what you paste into it
Source for evm.codes an Ethereum Virtual Machine Opcodes Interactive Reference
At a glance
- What is it?
- evm.codes is the Dune project that documents the Ethereum Virtual Machine opcodes by running them, using EthereumJS for execution and SolcJS for compilation in the browser. Running it locally needs Node 24, pnpm and a webpack build step, and the contract viewer needs an Etherscan key.
- Who is it for?
- evm.codes fits a Solidity developer who wants to see what a piece of bytecode or Solidity actually does, step by step, without setting up a node or a debugger. It does not fit someone who needs to run the EVM as part of a production system, and it is not a substitute for a spec.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 30 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A reference that executes the code instead of describing it
evm.codes is an interactive reference to Ethereum Virtual Machine opcodes, and the word interactive is doing the real work. The site is not a table of mnemonics and stack effects. You give it code and it runs the code, showing you what the machine does.
The repository is the source for the evm.codes web application, and the README says it is brought to you by Dune, powered by open-source projects such as EthereumJS and SolcJS. The dependency list makes the architecture concrete: the @ethereumjs packages for block, common, evm, tx, util and vm at version 10.1.0 provide the EVM itself, solc-js provides the Solidity compiler, and @solidity-parser/parser handles Solidity source.
The two audiences are slightly different. A reader who lands on the site wants to understand an opcode, and the fastest way to understand an opcode is to watch it execute in a stack machine. A developer who wants to reproduce the behaviour locally can clone the repository and run the same code path.
There is a third group the project explicitly wants: contributors. The README asks for help to fix bugs, add new features and improvements, or to update the EVM reference docs, and the whole repository is set up for that, which is the subject of the sections below.
Cloning and running: Node 24, pnpm, and one environment variable
The requirements are short. The application needs NodeJS 24 or newer and pnpm, and the local development path is four steps.
Clone the repository:
git clone [email protected]:duneanalytics/evm.codes.gitInstall the dependencies:
pnpm installIf you want to run the contract viewer, the environment variables go in .env.local, and there is one that matters:
APIKEY_ETHERSCAN=Then start the app:
pnpm devThe result is the application at http://localhost:3000.
The Etherscan key is worth a note. It exists because the contract viewer resolves contract addresses, which means the app talks to an external service, and the reference is therefore only as good as that dependency at the moment you use it. The example environment file in the repository carries two entries, NEXT_PUBLIC_VERCEL_URL and APIKEY_ETHERSCAN, which is a reasonable summary of what the app expects from its environment.
Deployment is not something you configure. The README says deployments are handled automatically by Vercel as soon as a pull request is merged to main, so the production path is the merge path.
The dev script compiles a SolcJS worker before Next even starts
The package.json is where the unusual build shape shows up, and the interesting line is the dev script:
"build": "next build --webpack",
"build:solcjs-worker": "browserify -x debug -t babelify ./babel/solcWorker2.js > ./public/solcWorker.js",
"dev": "pnpm run build:solcjs-worker && next dev --webpack",Two things are worth noticing. The dev script does not just run the dev server, it first bundles the SolcJS worker with browserify and babelify, and the result is written into the public directory as solcWorker.js. The compiler therefore runs as a separate browser worker, which is how a site can compile Solidity without a server doing it.
The second is the --webpack flag on both the build and the dev commands. The project is on Next 16 and is explicitly using the webpack path rather than the default, which is a deliberate choice rather than an oversight, and it comes with a cost: webpack has to bundle a compiler.
The rest of the scripts are conventional. There is a format script running prettier with a cache, a serve script that builds and then runs next start, a lint script running eslint over js, jsx, ts and tsx, a typecheck that runs next typegen and then tsc with pretty output, a lint:package that sorts the package.json with sort-package-json, and a prepare script that runs husky to install the git hooks.
The repository layout matches a Next.js application with a lot of local content: pages/ for the routes, components/ and context/ for the UI, lib/ and util/ for helpers, types/, styles/ with a Tailwind configuration, a webpack/ directory, a babel/ directory, and two data files at the root, opcodes.json and precompiled.json.
Opcode data is a JSON file, and the reference docs live in their own directory
The contents of the reference are data, and that data is in the repository rather than in a database. Two JSON files sit at the root of the tree, opcodes.json and precompiled.json, alongside bytecode.js and mnemonic.js, which are the parts of the code that know what the instructions and the built-in contracts are.
That structure has a consequence for contributors. A new opcode or a change to the specification is a data update, and the README points contributors at the EVM reference docs under docs/opcodes for exactly that task. The docs directory also holds an architecture document, docs/ARCHITECTURE.md, which the README asks you to read before contributing so you understand the code structure and how the app is built.
The documentation itself is rendered by the application rather than pulled from an external site. The dependency list shows @mdx-js/react, @mdx-js/loader, next-mdx-remote and gray-matter, which is the standard set for writing documentation as MDX files that are compiled at build time, and a components.json at the root suggests a component library convention for the UI.
For a reader of the site, the practical effect is that the reference and the documentation are versioned together with the code. When a fork changes, the reference changes with it, and there is no separate service to keep in sync.
Conventions are enforced by tooling, and pull requests need a prefix
The contributing section is short and specific, which is a sign of a project that has had the same conversations many times.
Before a pull request, check whether a GitHub issue already exists. If not, create one first to discuss the approach and get feedback from the team. That is a stronger requirement than it sounds, because it means an issue is the unit of work.
When the pull request is about to be submitted, its name has to be prefixed with chore: for small improvements and regular maintenance, fix: for bugs and hot fixes, or feat: for new features, and the stated reason is that it helps the team look up the type of the issue from the Git history.
The project is pre-configured with ESLint, TypeScript and Prettier, and the README gives the three commands to check your work: pnpm lint --fix to find and fix linting issues, pnpm typecheck to check for TypeScript issues, and pnpm lint:package to sort the package.json. The husky prepare script installs the hooks, so the same checks run on commit rather than only in review.
There is also a note about the small team maintaining the project. It explains why the issue-first rule exists and why the prefixes are worth the effort: the review bandwidth is the constraint, not the code.
The dependency list is the map of what the app does
Reading package.json is the fastest way to understand the application, because the dependencies are unusually revealing.
The @ethereumjs family, block, common, evm, tx, util and vm, is the virtual machine and the transaction types around it, and it is what makes the site an interpreter rather than a document. ethereumjs-abi and ethereumjs-util handle encoding. @solidity-parser/parser and highlightjs-solidity with highlight.js handle reading and colouring Solidity, and Monaco, through monaco-editor and @monaco-editor/react, is the editor the code goes into.
The UI is MUI: @mui/material for components and @mui/x-tree-view for the tree view. @emotion/react and @emotion/styled do the styling, Tailwind handles utility classes, and kbar is the command palette, which is a common choice for a search-first interface. lodash.debounce is there to keep keystrokes from turning into re-renders.
Two smaller entries explain a lot. @kunigi/string-compression is a string compression library, and given the compress_threshold style behaviour elsewhere in the Ethereum ecosystem it is likely there to shrink data that has to travel in a transaction. crypto-js is a cryptography library.
The practical note for a contributor is that this is a browser application doing real compilation and real EVM execution in the page, which means bundle size and worker performance are genuine constraints rather than hypothetical ones.
Where evm.codes is the wrong tool
The first wrong fit is a production system. If you need to run the EVM as part of a service, a backend or a node, this application is the wrong shape. The @ethereumjs/vm library in the dependency list is the thing to use directly, and you get programmatic execution in your own process rather than a page with a code editor. The difference in approach is exactly that: a browser reference that shows its work to a human, versus a library you call.
The second wrong fit is treating it as a specification. evm.codes is a reference implementation and a teaching tool maintained by a small team, and the authoritative text for what an opcode must do is the EVM specification and the reference docs in docs/opcodes, which this project contributes to. If your compliance argument depends on the behaviour of an opcode, read the spec.
The third is an offline or restricted environment. The app compiles Solidity in the browser and can reach an Etherscan endpoint for the contract viewer. On a machine with no outbound network, the compile and view paths degrade, and the dependency on a third party key is a standing operational condition rather than a setup detail.
The fourth is expecting a maintained release channel. The repository has no GitHub releases, the version in package.json is 0.1.0, and the last push was on 2026-09-24 with the repository not archived. The site is deployed continuously from main through Vercel, so there is no versioned artefact to pin. For a reference you use while writing Solidity that is fine, because you are reading the live site. For anything you want to reproduce later, take a copy rather than depending on the deployment.
The licence is MIT with the LICENSE file at the root of the repository, so the code and the opcode data can be reused, for instance in your own tooling. Read the file for the terms that apply, and this is not legal advice.
Editorial conclusion
evm.codes fits a Solidity developer who wants to see what a piece of bytecode or Solidity actually does, step by step, without setting up a node or a debugger. It does not fit someone who needs to run the EVM as part of a production system, and it is not a substitute for a spec. Before contributing, read docs/ARCHITECTURE.md, and if you intend to use the contract viewer, expect to supply an Etherscan API key in .env.local.
Frequently asked questions
What is evm.codes?
It is an interactive reference to Ethereum Virtual Machine opcodes, brought to you by Dune. It runs the code you give it rather than only describing it, using EthereumJS for the EVM and SolcJS for compiling Solidity in the browser.
How do I run evm.codes locally?
Clone the repository, run pnpm install, optionally add APIKEY_ETHERSCAN to .env.local for the contract viewer, then run pnpm dev and open http://localhost:3000. The app needs NodeJS 24 or newer and pnpm.
What does the dev script do before starting the dev server?
The dev script first runs the build:solcjs-worker script, which bundles babel/solcWorker2.js with browserify and babelify into public/solcWorker.js, and only then starts next dev --webpack.
How are new opcodes added to evm.codes?
The opcode data is kept in opcodes.json and precompiled.json in the repository root, and the README asks contributors to update the EVM reference docs under docs/opcodes. The architecture document at docs/ARCHITECTURE.md explains how the app is built.
What licence is evm.codes released under?
It is MIT licensed, with the LICENSE file at the root of the repository, and the site is deployed to Vercel automatically when a pull request is merged to main.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/duneanalytics-evm-codes)Was this useful?