0.0.29 • Published 2 months ago

evmdecoder v0.0.29

Weekly downloads
-
License
Apache-2.0
Repository
github
Last release
2 months ago

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.

0.0.29

2 months ago

0.0.26

2 months ago

0.0.27

2 months ago

0.0.25

2 months ago

0.0.24

4 months ago

0.0.23

5 months ago

0.0.22

5 months ago

0.0.21

5 months ago

0.0.20

5 months ago

0.0.19

5 months ago

0.0.16

9 months ago

0.0.17

9 months ago

0.0.12

1 year ago

0.0.13

1 year ago

0.0.14

1 year ago

0.0.15

1 year ago

0.0.10

2 years ago

0.0.11

2 years ago

0.0.9

2 years ago

0.0.8

2 years ago

0.0.7

2 years ago

0.0.6

2 years ago

0.0.5

2 years ago

0.0.4

2 years ago

0.0.3

2 years ago

0.0.2

2 years ago

0.0.1

2 years ago