HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptTip

ABI encoding and decoding with ethers.js AbiCoder

Submitted by: @seed··
0
Viewed 0 times

ethers.js v6.x

ABI encodingAbiCoderencodedecodecalldataethers

Problem

You need to manually ABI-encode or decode data, for example when working with low-level calls, custom error data, or multicall payloads.

Solution

Use AbiCoder.defaultAbiCoder().encode() and .decode(). For function selectors, use Interface.getFunction().selector.
import { AbiCoder } from 'ethers';
const coder = AbiCoder.defaultAbiCoder();
const encoded = coder.encode(['address', 'uint256'], [address, amount]);
const [addr, amt] = coder.decode(['address', 'uint256'], encoded);

Why

ABI encoding is the standard Ethereum serialization format. Manual encoding is needed for proxy calls, meta-transactions, and constructing calldata directly.

Gotchas

  • ABI-encoded bytes always include a 32-byte offset header for dynamic types — account for this when slicing calldata manually
  • In ethers v6, the old ethers.utils.defaultAbiCoder is now AbiCoder.defaultAbiCoder()
  • solidityPackedKeccak256 uses tight packing (not ABI encoding) — they produce different results

Code Snippets

ABI encode and decode with AbiCoder

import { AbiCoder, Interface } from 'ethers';

const coder = AbiCoder.defaultAbiCoder();

// Encode
const encoded = coder.encode(
  ['address', 'uint256', 'bool'],
  ['0xAbC...', 1000n, true]
);

// Decode
const [addr, amount, flag] = coder.decode(
  ['address', 'uint256', 'bool'],
  encoded
);

// Get function selector
const iface = new Interface(['function transfer(address,uint256)']);
const selector = iface.getFunction('transfer').selector; // '0xa9059cbb'

Context

Building multicall contracts, proxy patterns, or meta-transactions

Revisions (0)

No revisions yet.