npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

evmdecoder

v0.0.65

Published

Library to decode EVM contract data.

Downloads

672

Readme

EvmDecoder

A library to fetch and decode smart contract related bytecode data from an EVM node.

EvmDecoder can determine if an address is a contract and (for supported types) return information about and/or properties of the contract. It can also decode transaction input data when provided with the respective (or matching) ABIs.

All feature requests and contributions will be considered!

Contract Identification

EvmDecoder aims to identify common types of smart contracts by matching unique function signatures in the deployed bytecode of contracts. When a contract is identified as a type of proxy, the decoder will attempt to determine the contract address and type behind the proxy recusively and classify the final contract in the proxy chain.

Types of contracts that can be identified:

How to use

yarn add evmdecoder or npm install evmdecoder to install.

Decode function call

import { EvmDecoder } from 'evmdecoder'

const evmDecoder = new EvmDecoder({
  eth: {
    url: 'http://localhost:8545'
  },
  abi: {
    directory: './abis'
  }
})
await evmDecoder.initialize()

// ethereum tx hash: 0xd698c9191a88c253a926ef1d7eecf22bea9370a0d8dc7fb9e819bad0ae0f1d9e
const input =
  '0xe63d38ed000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000083d50977190c592bb9f03054500b1fd81b53dd49000000000000000000000000dc7cd9b725726f5dcd646d3a2c768e4636a89578000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000002c68af0bb14000000000000000000000000000000000000000000000000000002c68af0bb140000'
const functionCall = await evmDecoder.decodeFunctionCall({ input })
console.log(JSON.stringify(functionCall))

Output:

{
  "name": "disperseEther",
  "signature": "disperseEther(address[],uint256[])",
  "params": [
    {
      "name": "recipients",
      "type": "address[]",
      "value": ["0x83D50977190c592BB9F03054500B1fd81B53Dd49", "0xDC7cD9b725726F5Dcd646D3A2C768E4636a89578"]
    },
    {
      "name": "values",
      "type": "uint256[]",
      "value": ["200000000000000000", "200000000000000000"]
    }
  ],
  "args": {
    "recipients": ["0x83D50977190c592BB9F03054500B1fd81B53Dd49", "0xDC7cD9b725726F5Dcd646D3A2C768E4636a89578"],
    "values": ["200000000000000000", "200000000000000000"]
  }
}

Decode NFT transfer

import { EvmDecoder } from 'evmdecoder'

const evmDecoder = new EvmDecoder({
  eth: {
    url: 'http://localhost:8545'
  },
  abi: {
    directory: './abis'
  }
})
await evmDecoder.initialize()

const input =
  '0x23b872dd000000000000000000000000e809e745ebd8e37d2ed783b48d328b2b77b7dd2c0000000000000000000000006a60114b678b04be3fa094eb5abdc2d4ecd80769000000000000000000000000000000000000000000000000000000000000005c'
const address = '0x78d61C684A992b0289Bbfe58Aaa2659F667907f8'
const functionCall = await evmDecoder.decodeFunctionCall({ input, address })
console.log(JSON.stringify(functionCall))

Output:

{
  "name": "transferFrom",
  "signature": "transferFrom(address,address,uint256)",
  "params": [
    {
      "name": "_from",
      "type": "address",
      "value": "0xE809E745EbD8E37d2ed783b48d328B2b77B7dD2C"
    },
    {
      "name": "_to",
      "type": "address",
      "value": "0x6a60114B678b04Be3FA094eB5aBdC2d4ecD80769"
    },
    {
      "name": "_value",
      "type": "uint256",
      "value": 92
    }
  ],
  "args": {
    "_from": "0xE809E745EbD8E37d2ed783b48d328B2b77B7dD2C",
    "_to": "0x6a60114B678b04Be3FA094eB5aBdC2d4ecD80769",
    "_value": 92
  },
  "extra": {
    "tokenUri": "ipfs://QmUAxNgx55CdusaUAxEF1ua3PNmGaUHbas1vGX6qBr1awz/76.json"
  }
}

Identify contract

ERC20:

import { EvmDecoder } from 'evmdecoder'

const evmDecoder = new EvmDecoder({
  eth: {
    url: 'http://localhost:8545'
  }
})
await evmDecoder.initialize()

// USDC
const address = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
const info = await evmDecoder.contractInfo({ address })
console.log(JSON.stringify(info))

Output:

{
  "isContract": true,
  "fingerprint": "5157940bcbc1f14cc9cd9b04787267e55a3cb6455b14d6eb8fdb2d7f1057a3aa",
  "contractName": "ERC20_Proxy",
  "contractType": {
    "name": "Token",
    "proxies": [
      {
        "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        "standard": "ERC897",
        "target": "0xa2327a938febf5fec13bacfb16ae10ecbc4cbdcf"
      }
    ],
    "standards": ["ERC20"]
  },
  "properties": {
    "name": "USD Coin",
    "symbol": "USDC",
    "decimals": "6"
  }
}

NFT:

import { EvmDecoder } from 'evmdecoder'

const evmDecoder = new EvmDecoder({
  eth: {
    url: 'http://localhost:8545'
  }
})
await evmDecoder.initialize()

// SUPERGUCCI
const address = '0x78d61C684A992b0289Bbfe58Aaa2659F667907f8'
const info = await evmDecoder.contractInfo({ address })
console.log(JSON.stringify(info))

Output:

{
  "isContract": true,
  "fingerprint": "188e6dbcca2606630ad5b1ac09ae26f317820d1e230b5be637a06ff69436dc86",
  "contractType": {
    "name": "NFT",
    "metadata": true,
    "baseUri": false,
    "enumeration": true,
    "receive": ["ERC721"],
    "standards": ["ERC721"]
  },
  "properties": {
    "name": "SUPERPLASTIC: SUPERGUCCI",
    "symbol": "SPGCI",
    "totalSupply": "500"
  }
}

Config options

Defaults shown

{
  eth: {
    http: {
      timeout: 60_000,
      validateCertificate: false,
      requestKeepAlive: true,
      maxSockets: 256
    },
    client: {
      maxBatchSize: 100,
      maxBatchTime: 0,
      individualReceipts: true,
      maxRetryTime: 10_000
    }
  },
  abi: {
    abiFileExtension: '.json',
    directory: './abis',
    searchRecursive: true,
    fingerprintContracts: true,
    requireContractMatch: false,
    decodeAnonymous: true,
    reconcileStructShapeFromTuples: true
  },
  contractInfo: {
    maxCacheEntries: 25_000
  }
}

Dev Setup

Prerequisites

  1. Clone Repo
  2. Install dependencies
yarn install
  1. Build
yarn build

before committing, run yarn format and re-add anything updated.