Copy
Ask AI
import { Abi } from '@tevm/voltaire/Abi';
import { Hex } from '@tevm/voltaire/Hex';
import { Address } from '@tevm/voltaire/Address';
// ERC-20 view functions
const erc20Abi = Abi([
{
type: "function",
name: "balanceOf",
stateMutability: "view",
inputs: [{ type: "address", name: "account" }],
outputs: [{ type: "uint256", name: "" }]
},
{
type: "function",
name: "name",
stateMutability: "view",
inputs: [],
outputs: [{ type: "string", name: "" }]
},
{
type: "function",
name: "symbol",
stateMutability: "view",
inputs: [],
outputs: [{ type: "string", name: "" }]
},
{
type: "function",
name: "decimals",
stateMutability: "view",
inputs: [],
outputs: [{ type: "uint8", name: "" }]
}
]);
// Encode balanceOf(address) call
const account = "0x742d35cc6634c0532925a3b844bc9e7595f251e3";
const calldata = erc20Abi.encode("balanceOf", [account]);
// Make eth_call (pseudo-code for RPC)
// const result = await provider.call({
// to: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
// data: Hex.fromBytes(calldata)
// });
// Decode the return value
const returnData = Hex.toBytes(
"0x00000000000000000000000000000000000000000000000000000000000f4240"
);
const [balance] = erc20Abi.decode("balanceOf", returnData);
// balance = 1000000n (1 USDC with 6 decimals)
Read Token Metadata
Copy
Ask AI
// Encode name() call (no arguments)
const nameCalldata = erc20Abi.encode("name", []);
// Decode string return value
const nameReturnData = Hex.toBytes(
"0x0000000000000000000000000000000000000000000000000000000000000020" +
"0000000000000000000000000000000000000000000000000000000000000008" +
"5553442054657468657200000000000000000000000000000000000000000000"
);
const [name] = erc20Abi.decode("name", nameReturnData);
// name = "USD Tether"
// Encode decimals() call
const decimalsCalldata = erc20Abi.encode("decimals", []);
// Decode uint8 return value
const decimalsReturnData = Hex.toBytes(
"0x0000000000000000000000000000000000000000000000000000000000000006"
);
const [decimals] = erc20Abi.decode("decimals", decimalsReturnData);
// decimals = 6n
Low-Level Encoding
UseAbi.Function for more control:
Copy
Ask AI
// Get function from ABI
const balanceOfFn = erc20Abi.getFunction("balanceOf");
// Get function selector (first 4 bytes of keccak256 hash)
const selector = Abi.Function.getSelector(balanceOfFn);
// 0x70a08231 = keccak256("balanceOf(address)")[0:4]
// Encode just the parameters (without selector)
const params = Abi.Function.encodeParams(balanceOfFn, [account]);
// Decode return value
const result = Abi.Function.decodeResult(balanceOfFn, returnData);
// [1000000n]
Batch Multiple Calls
Encode multiple view calls for multicall:Copy
Ask AI
const calls = [
{ fn: "name", args: [] },
{ fn: "symbol", args: [] },
{ fn: "decimals", args: [] },
{ fn: "balanceOf", args: [account] }
];
const encodedCalls = calls.map(({ fn, args }) => ({
target: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
callData: Hex.fromBytes(erc20Abi.encode(fn, args))
}));
// Use with Multicall3 contract for batched reads
This is a fully executable example. View the complete source with test assertions at
examples/contracts/read-contract.ts.
