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.
Try it Live
Run ABI examples in the interactive playground
Usage Patterns
Practical patterns for working with ABI encoding and decoding in production code.Contract Interaction
Function Call Encoding
import { Function, Abi } from 'tevm';
// Define function
const transferFn = {
type: "function",
name: "transfer",
stateMutability: "nonpayable",
inputs: [
{ type: "address", name: "to" },
{ type: "uint256", name: "amount" }
],
outputs: [{ type: "bool" }]
};
// Encode function call
const calldata = Function.encodeParams(transferFn, [
"0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e",
1000n
]);
// Get selector
const selector = Function.getSelector(transferFn); // 4 bytes
// Full calldata = selector + encoded params
const fullCalldata = new Uint8Array([...selector, ...calldata]);
// Send transaction
await provider.sendTransaction({
to: contractAddress,
data: fullCalldata
});
Return Value Decoding
// Execute call and decode result
const returnData = await provider.call({
to: contractAddress,
data: fullCalldata
});
// Decode return value
const [success] = Function.decodeResult(transferFn, returnData);
console.log(`Transfer ${success ? 'succeeded' : 'failed'}`);
Multi-call Pattern
interface Call {
target: string;
callData: Uint8Array;
decoder: (data: Uint8Array) => any;
}
// Prepare multiple calls
const calls: Call[] = [
{
target: token1,
callData: Function.encodeParams(balanceOfFn, [userAddress]),
decoder: (data) => Function.decodeResult(balanceOfFn, data)
},
{
target: token2,
callData: Function.encodeParams(balanceOfFn, [userAddress]),
decoder: (data) => Function.decodeResult(balanceOfFn, data)
}
];
// Execute multicall
const results = await Promise.all(
calls.map(call =>
provider.call({ to: call.target, data: call.callData })
)
);
// Decode results
const balances = results.map((data, i) => calls[i].decoder(data));
Event Processing
Log Parsing
import { Event } from 'tevm';
// Define Transfer event
const transferEvent = {
type: "event",
name: "Transfer",
inputs: [
{ type: "address", name: "from", indexed: true },
{ type: "address", name: "to", indexed: true },
{ type: "uint256", name: "value", indexed: false }
]
};
// Get logs from provider
const logs = await provider.getLogs({
address: tokenAddress,
fromBlock: startBlock,
toBlock: endBlock,
topics: [Event.getSelector(transferEvent)]
});
// Parse all logs
const transfers = logs.map(log =>
Event.decodeLog(transferEvent, log.data, log.topics)
);
// Process transfers
transfers.forEach(({ from, to, value }) => {
console.log(`${from} → ${to}: ${value}`);
});
Event Filtering
// Filter by specific sender
const senderTopic = Event.encodeIndexed(
{ type: "address" },
senderAddress
);
const logs = await provider.getLogs({
address: tokenAddress,
topics: [
Event.getSelector(transferEvent),
senderTopic // Filter by 'from' address
]
});
Multi-event Parsing
const eventDefinitions = {
Transfer: transferEvent,
Approval: approvalEvent,
Mint: mintEvent
};
// Get topic0 → event mapping
const topicMap = new Map(
Object.entries(eventDefinitions).map(([name, def]) => [
Event.getSelector(def).toString(),
{ name, definition: def }
])
);
// Parse mixed event logs
const parsed = logs.map(log => {
const topic0 = log.topics[0];
const event = topicMap.get(topic0.toString());
if (!event) return null;
return {
name: event.name,
args: Event.decodeLog(event.definition, log.data, log.topics)
};
}).filter(Boolean);
Error Handling
Custom Error Decoding
import { AbiError } from 'tevm';
// Define custom errors
const errors = {
InsufficientBalance: {
type: "error",
name: "InsufficientBalance",
inputs: [
{ type: "uint256", name: "balance" },
{ type: "uint256", name: "required" }
]
},
InvalidRecipient: {
type: "error",
name: "InvalidRecipient",
inputs: [{ type: "address", name: "recipient" }]
}
};
// Try transaction, catch revert
try {
await contract.transfer(recipient, amount);
} catch (err: any) {
const revertData = err.data;
// Try to decode with each error definition
for (const [name, errorDef] of Object.entries(errors)) {
const selector = AbiError.getSelector(errorDef);
if (revertData.startsWith(selector)) {
const args = AbiError.decodeParams(errorDef, revertData.slice(4));
console.error(`${name}:`, args);
break;
}
}
}
Error Encoding
// Encode custom error for testing
const errorData = AbiError.encodeParams(
errors.InsufficientBalance,
[100n, 1000n]
);
// Simulate revert in tests
const fullError = new Uint8Array([
...AbiError.getSelector(errors.InsufficientBalance),
...errorData
]);
Type-safe ABI Loading
From JSON
import { Abi } from 'tevm';
// Load ABI from contract artifact
const artifact = require('./artifacts/Token.json');
const abi = Abi(artifact.abi);
// Get specific items
const transferFn = abi.getFunction("transfer");
const transferEvent = abi.getEvent("Transfer");
const balanceError = abi.getError("InsufficientBalance");
Dynamic ABI Construction
// Build ABI programmatically
const items = [
{
type: "function",
name: "transfer",
inputs: [
{ type: "address", name: "to" },
{ type: "uint256", name: "amount" }
],
outputs: [{ type: "bool" }]
},
{
type: "event",
name: "Transfer",
inputs: [
{ type: "address", name: "from", indexed: true },
{ type: "address", name: "to", indexed: true },
{ type: "uint256", name: "value" }
]
}
];
const abi = Abi(items);
Complex Type Handling
Struct Encoding
// Define struct as tuple
const positionType = {
type: "tuple",
components: [
{ type: "uint256", name: "amount" },
{ type: "uint256", name: "shares" },
{ type: "uint256", name: "timestamp" }
]
};
// Encode struct
const encoded = Abi.encode([positionType], [[1000n, 500n, 1234567890n]]);
Array Handling
// Dynamic array
const dynamicArrayType = { type: "uint256[]" };
const values = [1n, 2n, 3n, 4n, 5n];
const encoded = Abi.encode([dynamicArrayType], [values]);
// Fixed array
const fixedArrayType = { type: "uint256[5]" };
const encoded = Abi.encode([fixedArrayType], [values]);
// Multi-dimensional
const matrixType = { type: "uint256[][]" };
const matrix = [[1n, 2n], [3n, 4n]];
const encoded = Abi.encode([matrixType], [matrix]);
String and Bytes
// String
const stringType = { type: "string" };
const encoded = Abi.encode([stringType], ["Hello, Ethereum!"]);
// Dynamic bytes
const bytesType = { type: "bytes" };
const data = new Uint8Array([1, 2, 3, 4]);
const encoded = Abi.encode([bytesType], [data]);
// Fixed bytes
const bytes32Type = { type: "bytes32" };
const hash = Bytes32();
const encoded = Abi.encode([bytes32Type], [hash]);
Optimization Patterns
Selector Caching
// Cache selectors for frequent use
const selectorCache = new Map<string, Uint8Array>();
function getCachedSelector(fn: Function): Uint8Array {
const key = `${fn.name}(${fn.inputs.map(i => i.type).join(',')})`;
if (!selectorCache.has(key)) {
selectorCache.set(key, Function.getSelector(fn));
}
return selectorCache.get(key)!;
}
Reusable Encoders
class ContractInterface {
constructor(private abi: Abi) {}
// Pre-bind common functions
private transfer = this.abi.getFunction("transfer");
private balanceOf = this.abi.getFunction("balanceOf");
encodeTransfer(to: string, amount: bigint): Uint8Array {
return Function.encodeParams(this.transfer, [to, amount]);
}
encodeBalanceOf(account: string): Uint8Array {
return Function.encodeParams(this.balanceOf, [account]);
}
decodeBalance(data: Uint8Array): bigint {
const [balance] = Function.decodeResult(this.balanceOf, data);
return balance;
}
}
Testing Patterns
Mock Contract Responses
// Encode expected return values
function mockBalanceOf(balance: bigint): Uint8Array {
return Abi.encode([{ type: "uint256" }], [balance]);
}
// Use in tests
test("handles zero balance", async () => {
mock.returns(mockBalanceOf(0n));
const balance = await contract.balanceOf(user);
expect(balance).toBe(0n);
});
Event Testing
// Encode expected event
function mockTransferEvent(from: string, to: string, value: bigint) {
return {
topics: [
Event.getSelector(transferEvent),
Event.encodeIndexed({ type: "address" }, from),
Event.encodeIndexed({ type: "address" }, to)
],
data: Abi.encode([{ type: "uint256" }], [value])
};
}
Related
- Decode - ABI decoding
- Encode - ABI encoding
- Parse Logs - Event log parsing
- Fundamentals - ABI basics

