0.0.11 • Published 1 year ago

@acuarica/evm v0.0.11

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

EVM Bytecode Decompiler

GitHub Workflow Status nycrc config on GitHub npm (scoped) npm GitHub Demo

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

Forked from MrLuit/evm. For more info, see Detached Fork.

Install

Install using your package manager or Browser's script tag

yarn

yarn add @acuarica/evm

npm

npm install @acuarica/evm

Browser WIP

<script src="https://cdn.jsdelivr.net/gh/acuarica/evm@f88b20a/lib/EVM.js"></script>

Features

  • Convert bytecode to opcodes
  • Read information like events or functions from either bytecode or TX data
  • Extract the IPFS or swarm hash (when present) from bytecode
  • Check whether an opcode exists and is reachable within bytecode execution
  • Detect whether contracts are compliant to certain ERCs

API    TypeDoc

Main Methods and Properties

Usage

Converting Bytecode to Opcodes

Node.js

const { EVM } = require('evm');
const Web3 = require('web3');
const web3 = new Web3(new Web3.providers.HttpProvider('https://api.mycryptoapi.com/eth'));

web3.eth.getCode('0x06012c8cf97BEaD5deAe237070F9587f8E7A266d').then(code => {
  /* CryptoKitties contract */
  const evm = new EVM(code);
  console.log(evm.getOpcodes()); /* Get opcodes */
});

Browser

const { EVM } = window.EVM_Utils;
const web3 = new Web3(window.web3.currentProvider);
web3.eth.getCode('0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359', function (err, code) {
  /* DAI contract */ if (err) throw err;
  const evm = new EVM(code);
  console.log(evm.getOpcodes()); /* Get opcodes */
});

Decompiling a Contract

Node.js

const { EVM } = require('evm');
const Web3 = require('web3');
const web3 = new Web3(new Web3.providers.HttpProvider('https://api.mycryptoapi.com/eth'));

web3.eth.getCode('0x06012c8cf97BEaD5deAe237070F9587f8E7A266d').then(code => {
  /* CryptoKitties contract */
  const evm = new EVM(code);
  console.log(evm.getFunctions()); /* Get functions */
  console.log(evm.getEvents()); /* Get events */
  console.log(evm.decompile()); /* Decompile bytecode */
  console.log(
    evm.containsOpcode('SELFDESTRUCT')
  ); /* Check whether contract contains a SELFDESTRUCT */
  console.log(evm.isERC165()); /* Detect whether contract is ERC165-compliant */
});

Browser

const { EVM } = window.EVM;
const web3 = new Web3(window.web3.currentProvider);
web3.eth.getCode('0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359', function (err, code) {
  /* DAI contract */ if (err) throw err;
  const evm = new EVM(code);
  console.log(evm.getFunctions()); /* Get functions */
  console.log(evm.getEvents()); /* Get events */
  console.log(evm.decompile()); /* Decompile bytecode */
  console.log(
    evm.containsOpcode('SELFDESTRUCT')
  ); /* Check whether contract contains a SELFDESTRUCT */
  console.log(evm.isERC165()); /* Detect whether contract is ERC165-compliant */
});

Extracting data from transaction WIP

Node.js

const { Transaction } = require('evm');
const Web3 = require('web3');
const web3 = new Web3(new Web3.providers.HttpProvider('https://api.mycryptoapi.com/eth'));

web3.eth
  .getTransaction('0xd20a8d888a3f29471ea41ea77cc2d95ccd79ade1eaad059e83524e72b9adf962')
  .then(transactionData => {
    const transaction = new Transaction();
    transaction.setInput(transactionData.input);
    console.log(transaction.getFunction()); /* Get function */
  });

Browser

const { Transaction } = window.EVM;
const web3 = new Web3(window.web3.currentProvider);
web3.eth.getTransaction(
  '0xd20a8d888a3f29471ea41ea77cc2d95ccd79ade1eaad059e83524e72b9adf962',
  function (err, transactionData) {
    if (err) throw err;
    const transaction = new Transaction();
    transaction.setInput(transactionData.input);
    console.log(transaction.getFunction()); /* Get function */
  }
);

Detached Fork

This GitHub repo was originally a fork of https://github.com/MrLuit/evm. It served as a great starting point for this project. The fact that it is lightweight and written in TypeScript, make it ideal for embedding in other applications.

However, as we started to support and decompile newer contracts, we realize it was quite outdated. Besides not being able to process newer smart contracts, for some, the bytecode analysis algorithm did not terminate. That's the reason we forked that repo.

We did a major overhaul of the codebase, adding new features, refactoring the whole project and adding both testing and documentation. As we added changes, we realized it did not make sense to keep it a forked repo. Moreover, when sending new PRs, the default base repo is the upstream repo, which is not what we want in our case. This behavior is both error prone and annoying. That's why, as of Apr 17, 2023, this project is no longer a fork of MrLuit/evm.