Documentation Index
Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
Use this file to discover all available pages before exploring further.
Skill — Copyable reference implementation. Use as-is or customize. See Skills Philosophy.
Ethers-style Interface
A copyable reference implementation that follows ethers v6 Interface patterns, built on Voltaire primitives.
Overview
This Skill provides:
- Interface: Main ABI abstraction with ethers v6 API
- Fragment classes: FunctionFragment, EventFragment, ErrorFragment
- Encoding/Decoding: Function data, event logs, error results
- Parsing: Parse transactions, logs, and errors from raw data
Quick Start
import { Interface } from './examples/ethers-interface/index.js';
const abi = [
{
type: 'function',
name: 'transfer',
inputs: [
{ type: 'address', name: 'to' },
{ type: 'uint256', name: 'amount' },
],
outputs: [{ type: 'bool', name: '' }],
stateMutability: 'nonpayable',
},
{
type: 'event',
name: 'Transfer',
inputs: [
{ type: 'address', name: 'from', indexed: true },
{ type: 'address', name: 'to', indexed: true },
{ type: 'uint256', name: 'value', indexed: false },
],
},
{
type: 'error',
name: 'InsufficientBalance',
inputs: [
{ type: 'uint256', name: 'available' },
{ type: 'uint256', name: 'required' },
],
},
];
const iface = new Interface(abi);
Encoding Function Calls
Encode function call data for transaction data field:
// Encode transfer(address,uint256)
const data = iface.encodeFunctionData('transfer', [
'0x742d35Cc6634C0532925a3b844Bc9e7595f251e3',
1000000n,
]);
// 0xa9059cbb000000000000000000000000742d35cc6634c0532925a3b844bc9e7595f251e3...
// Get function by selector
const fn = iface.getFunction('0xa9059cbb');
console.log(fn?.name); // "transfer"
Decoding Function Data
Decode function call data back to arguments:
// Decode transaction data
const decoded = iface.decodeFunctionData('transfer', data);
console.log(decoded[0]); // "0x742d35cc6634c0532925a3b844bc9e7595f251e3"
console.log(decoded[1]); // 1000000n
// Decode function result (return values)
const result = iface.decodeFunctionResult('transfer', returnData);
console.log(result[0]); // true
Event Encoding/Decoding
Encode event logs for testing or mocking:
// Encode event log
const { data, topics } = iface.encodeEventLog('Transfer', [
'0x742d35Cc6634C0532925a3b844Bc9e7595f251e3',
'0x1234567890123456789012345678901234567890',
1000n,
]);
// Decode event log from raw data
const decoded = iface.decodeEventLog('Transfer', data, topics);
console.log(decoded[0]); // from address
console.log(decoded[1]); // to address
console.log(decoded[2]); // 1000n
Error Encoding/Decoding
Handle custom error reverts:
// Encode error for testing
const errorData = iface.encodeErrorResult('InsufficientBalance', [100n, 200n]);
// Decode error from revert data
const decoded = iface.decodeErrorResult('InsufficientBalance', errorData);
console.log(decoded[0]); // 100n (available)
console.log(decoded[1]); // 200n (required)
// Built-in Error and Panic
const standardError = iface.encodeErrorResult('Error', ['Something went wrong']);
const panicError = iface.encodeErrorResult('Panic', [0x11n]); // Arithmetic overflow
Parsing Raw Data
Parse unknown data to discover its type:
// Parse transaction
const txDescription = iface.parseTransaction({ data, value: 0n });
if (txDescription) {
console.log(txDescription.name); // "transfer"
console.log(txDescription.args); // [address, amount]
console.log(txDescription.selector); // "0xa9059cbb"
}
// Parse log
const logDescription = iface.parseLog({ topics, data });
if (logDescription) {
console.log(logDescription.name); // "Transfer"
console.log(logDescription.args); // [from, to, value]
console.log(logDescription.topic); // topic hash
}
// Parse error
const errorDescription = iface.parseError(revertData);
if (errorDescription) {
console.log(errorDescription.name); // "InsufficientBalance"
console.log(errorDescription.args); // [available, required]
}
Fragment Inspection
Inspect ABI fragments:
// Get all functions
iface.forEachFunction((fn, index) => {
console.log(fn.name, fn.selector, fn.stateMutability);
});
// Get all events
iface.forEachEvent((ev, index) => {
console.log(ev.name, ev.topicHash, ev.anonymous);
});
// Check existence
console.log(iface.hasFunction('transfer')); // true
console.log(iface.hasEvent('Transfer')); // true
// Get by name or selector
const fn = iface.getFunction('transfer');
const ev = iface.getEvent('Transfer');
const err = iface.getError('InsufficientBalance');
Convert ABI to human-readable format:
// Full format with names
const full = iface.format(false);
// ["function transfer(address to, uint256 amount) returns (bool)", ...]
// Minimal format without names
const minimal = iface.format(true);
// ["function transfer(address,uint256) returns (bool)", ...]
// JSON format
const json = iface.formatJson();
// '[{"type":"function","name":"transfer",...}]'
Constructor Encoding
Encode constructor arguments for deployment:
const constructorAbi = [
{
type: 'constructor',
inputs: [
{ type: 'string', name: 'name' },
{ type: 'string', name: 'symbol' },
],
},
];
const iface = new Interface(constructorAbi);
const deployData = iface.encodeDeploy(['My Token', 'MTK']);
// Append to bytecode for deployment
Filter Topics
Create filter topics for eth_getLogs:
// Filter for specific sender
const topics = iface.encodeFilterTopics('Transfer', [
'0x742d35Cc6634C0532925a3b844Bc9e7595f251e3',
null, // any recipient
]);
// Filter for multiple possible values
const multiTopics = iface.encodeFilterTopics('Transfer', [
['0xaddr1', '0xaddr2'], // from either address
null,
]);
Fragment Classes
Work with fragments directly:
import {
FunctionFragment,
EventFragment,
ErrorFragment,
ParamType
} from './examples/ethers-interface/index.js';
// Create fragments from ABI items
const fn = FunctionFragment.from({
type: 'function',
name: 'test',
inputs: [{ type: 'uint256', name: 'x' }],
outputs: [{ type: 'bool' }],
stateMutability: 'view',
});
console.log(fn.selector); // "0x29e99f07"
console.log(fn.format()); // "test(uint256)"
console.log(fn.constant); // true (view function)
// Compute selectors directly
const selector = FunctionFragment.getSelector('transfer', ['address', 'uint256']);
const topicHash = EventFragment.getTopicHash('Transfer', ['address', 'address', 'uint256']);
ParamType
Inspect parameter types:
const param = ParamType.from({
type: 'tuple',
name: 'data',
components: [
{ type: 'uint256', name: 'id' },
{ type: 'string', name: 'name' },
],
});
console.log(param.type); // "tuple"
console.log(param.isTuple()); // true
console.log(param.isArray()); // false
console.log(param.components); // [ParamType, ParamType]
// Format in different modes
console.log(param.format('sighash')); // "(uint256,string)"
console.log(param.format('full')); // "(uint256 id, string name) data"
Source Code
Full implementation available at:
examples/ethers-interface/Interface.js - Main Interface class
examples/ethers-interface/Fragment.js - Fragment classes
examples/ethers-interface/errors.ts - Error classes
examples/ethers-interface/EthersInterfaceTypes.ts - TypeScript types
examples/ethers-interface/EthersInterface.test.ts - Comprehensive tests
API Reference
Interface
| Method | Description |
|---|
encodeFunctionData(name, values?) | Encode function call data |
decodeFunctionData(name, data) | Decode function call params |
decodeFunctionResult(name, data) | Decode function return data |
encodeFunctionResult(name, values?) | Encode function return data |
encodeEventLog(name, values) | Encode event log |
decodeEventLog(name, data, topics?) | Decode event log |
encodeFilterTopics(name, values) | Encode filter topics |
encodeErrorResult(name, values?) | Encode error data |
decodeErrorResult(name, data) | Decode error data |
encodeDeploy(values?) | Encode constructor args |
parseTransaction(tx) | Parse transaction data |
parseLog(log) | Parse event log |
parseError(data) | Parse error data |
getFunction(key, values?) | Get function fragment |
getEvent(key, values?) | Get event fragment |
getError(key, values?) | Get error fragment |
forEachFunction(cb) | Iterate functions |
forEachEvent(cb) | Iterate events |
forEachError(cb) | Iterate errors |
format(minimal?) | Human-readable ABI |
formatJson() | JSON ABI string |
FunctionFragment
| Property | Description |
|---|
name | Function name |
selector | 4-byte selector (hex) |
inputs | Input parameters |
outputs | Output parameters |
stateMutability | pure/view/nonpayable/payable |
constant | Is view/pure |
payable | Can receive ether |
EventFragment
| Property | Description |
|---|
name | Event name |
topicHash | 32-byte topic hash |
inputs | Event parameters |
anonymous | Is anonymous event |
ErrorFragment
| Property | Description |
|---|
name | Error name |
selector | 4-byte selector |
inputs | Error parameters |