SkillAgentSearch skills...

Evm

A Symbolic Ethereum Virtual Machine (EVM) bytecode interpreter, parser and decompiler, along with several other utils for programmatically extracting information from EVM bytecode.

Install / Use

/learn @acuarica/Evm

README

<!-- markdownlint-disable no-inline-html -->

Symbolic EVM Bytecode Decompiler

splash preview

GitHub Workflow Status codecov npm npm GitHub install size Demo

A Symbolic Ethereum Virtual Machine (EVM) interpreter and decompiler, along with several other utils for programmatically extracting information from bytecode.

[!NOTE] Forked from MrLuit/evm. For more info, see Detached Fork.

Features

:construction: Under heavy development. Feel free to open an issue if something is not right. :construction:

  • Lightweight with no dependencies, ~65 kB minified ~17 kB minified & brotlied
  • Embedded functions and events signature database <small style="background: #f000b8; padding: 0.2em; border-radius: 3px">optional</small>
  • Convert bytecode to opcodes
  • Extract events or functions information from bytecode
  • Extract the IPFS or swarm hash (when present) from bytecode using cbor-js
  • Check whether an opcode exists and is reachable within bytecode execution
  • Detect whether contracts are compliant to certain ERCs

Install

Install using your package manager or Browser's script tag

<!-- tabs:start -->

yarn

yarn add sevm

npm

npm install sevm

Browser

<script src="https://cdn.jsdelivr.net/npm/sevm@0.6/dist/sevm.js"></script>
<!-- tabs:end -->

or if you're interested only in the CLI Tool, install globally in your system

npm install --global sevm

sevm supports both ESM import and Node's CommonJS require. Also it can be used in browsers, where all classes and functions can be found under the sevm global object.

<!-- tabs:start -->

ESM

import { Contract } from 'sevm';

// 00 opcode is STOP https://www.evm.codes/#00?fork=shanghai
const contract = new Contract('0x00');
console.log(contract.solidify());

CJS

const { Contract } = require('sevm');

// 00 opcode is STOP https://www.evm.codes/#00?fork=shanghai
const contract = new Contract('0x00');
console.log(contract.solidify());

script tag

<script src="https://cdn.jsdelivr.net/npm/sevm@0.6/dist/sevm.js"></script>

<script>
  console.log('sevm exported symbols', sevm);

  // 00 opcode is STOP https://www.evm.codes/#00?fork=shanghai
  const contract = new sevm.Contract('0x00');
  document.getElementById('code').innerHTML = contract.solidify();
</script>
<!-- tabs:end -->

API    TypeDoc

Main Methods and Properties

Usage

These examples use the import syntax and ethers.js is used to fetch bytecode from public EVM-based networks.

Decode Bytecode into Opcodes

import { JsonRpcProvider } from 'ethers';
import { Contract } from 'sevm';

const provider = new JsonRpcProvider('https://cloudflare-eth.com/');
// CryptoKitties Contract
// https://etherscan.io/address/0x06012c8cf97BEaD5deAe237070F9587f8E7A266d#code
const bytecode = await provider.getCode('0x06012c8cf97BEaD5deAe237070F9587f8E7A266d');
const contract = new Contract(bytecode);
const opcodes = contract.opcodes();
console.log(opcodes.map(opcode => opcode.format()));

Decompile a Contract

import { JsonRpcProvider } from 'ethers';
import { Contract } from 'sevm';
import 'sevm/4bytedb';

const provider = new JsonRpcProvider('https://cloudflare-eth.com/');
// WETH Contract
// https://etherscan.io/address/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
const bytecode = await provider.getCode('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2');

const contract = new Contract(bytecode).patchdb(); // Lookup for 4byte matches
console.log(contract.solidify()); // Decompile bytecode to Solidity

You can use the contract.yul() method to decompile the bytecode into Yul-like format.

Detect Functions, Events and ERC compliance

import { JsonRpcProvider } from 'ethers';
import { Contract } from 'sevm';
import 'sevm/4bytedb';

const provider = new JsonRpcProvider('https://cloudflare-eth.com/');
// CryptoKitties Contract
// https://etherscan.io/address/0x06012c8cf97BEaD5deAe237070F9587f8E7A266d#code
const bytecode = await provider.getCode('0x06012c8cf97BEaD5deAe237070F9587f8E7A266d');

const contract = new Contract(bytecode).patchdb();
console.log('functions', contract.getFunctions());
console.log('events', contract.getEvents());
console.log('isERC 165', contract.isERC('ERC165')); // Detect whether contract is ERC165-compliant

Extract Contract Metadata

import { JsonRpcProvider } from 'ethers';
import { Contract } from 'sevm';

// USDC Token Proxy on Avalanche Testnet
// https://testnet.snowtrace.io/address/0x5425890298aed601595a70AB815c96711a31Bc65#code
const provider = new JsonRpcProvider('https://api.avax-test.network/ext/bc/C/rpc');
const bytecode = await provider.getCode('0x5425890298aed601595a70AB815c96711a31Bc65');

const contract = new Contract(bytecode);
console.log(contract.metadata);

Advanced Usage

Hooks

import { EVM, London } from 'sevm';

// contract Test {
//     event Deposit(uint256);
//     fallback () external payable {
//         emit Deposit(tx.gasprice);
//     }
// }
const bytecode = '608060408190524581527f4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e3842690602090a16040805145815290517f4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e384269181900360200190a1604080513a815290517f4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e384269181900360200190a100';

const evm = new EVM(bytecode, new class extends London {
    /** @override */
    GASPRICE = (/** @type {import('sevm').Operand} */ state) => {
        super.GASPRICE(state);
        console.log('top', state.stack.top);
    };
}());

evm.start();

Advanced Hooks

A contract might embed another contract it creates and deploys. Using hooks you can extract the embedded contract.

import { Contract, type Opcode, Shanghai, type State } from 'sevm';
import type { DataCopy, Create } from 'sevm/ast';
import 'sevm/4bytedb';

// contract Token {
//     event Deposit(uint256 value);
//     fallback() external payable {
//         emit Deposit(3);
//     }
// }
// contract Test {
//     fallback() external payable {
//         new Token();
//     }
// }
const bytecode = '6080604052604051600e90602d565b604051809103906000f0801580156029573d6000803e3d6000fd5b5050005b60918061003a8339019056fe6080604052348015600f57600080fd5b50607480601d6000396000f3fe60806040527f4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e3842660036040518082815260200191505060405180910390a100fea2646970667358221220f03e9c56a5b70c1ba8fadf7d234cbca48d388951bfc7d402f0c92e4cb2afcd9f64736f6c63430007060033a264697066735822122053e5ffa19b83ac364f3adf6836d3758c98ae850b0fc9f5059124bf85d12c8d7264736f6c63430007060033';

let constructorContract: Contract, tokenContract: Contract;
const testContract = new Contract(bytecode, new class extends Shanghai {
    override CREATE = (state: State) => {
        super.CREATE(state);
        const bytecode = (state.stack.top as Create).bytecode!;

        constructorContract = new Contract(bytecode, new class 
View on GitHub
GitHub Stars109
CategoryDevelopment
Updated9d ago
Forks14

Languages

Solidity

Security Score

100/100

Audited on Mar 15, 2026

No findings