viem-goviem-go

ABI Decoding

Decode function calldata, return data, event logs, and errors for contract calls in viem-go

Decode function calldata (with selector), function return data, event logs, and revert errors using a parsed ABI. For standalone parameter decoding without a contract ABI, see Decode Parameters.

Import

import (
"encoding/hex"
"github.com/ethereum/go-ethereum/common"
"github.com/ChefBingbong/viem-go/abi"
)

DecodeFunctionData

Decode full calldata (selector + args) using a parsed ABI. Identifies the function by selector and returns name and arguments.

import "github.com/ChefBingbong/viem-go/abi"
// parsed is *abi.ABI from abi.Parse(...)
// calldata is tx input data (selector + ABI-encoded args)
decoded, err := parsed.DecodeFunctionData(calldata)
if err != nil {
log.Fatal(err)
}
fmt.Println(decoded.FunctionName) // e.g. "transfer"
fmt.Println(decoded.Args...) // decoded arguments
fmt.Println(decoded.Selector) // [4]byte
  • Signature: (a *ABI) DecodeFunctionData(data []byte) (*DecodedFunctionData, error)
  • DecodedFunctionData has FunctionName, Args ([]any), Selector ([4]byte).
  • Returns an error if the selector does not match any function on the ABI.

DecodeFunctionDataByName

Decode calldata when you already know the function name (still expects selector + args):

args, err := parsed.DecodeFunctionDataByName("transfer", calldata)
// args is []any

DecodeFunctionArgsFromData

Decode only the arguments (no selector). Use when data is only the ABI-encoded arguments (e.g. constructor args):

args, err := parsed.DecodeFunctionArgsFromData("transfer", dataWithoutSelector)

DecodeFunctionResult

Decode return data from a contract call using the function’s output definition. Use a parsed ABI and the function name.

import (
"math/big"
"github.com/ChefBingbong/viem-go/abi"
)
// returnData is the raw bytes from eth_call
values, err := parsed.DecodeFunctionResult("balanceOf", returnData)
if err != nil {
log.Fatal(err)
}
// For balanceOf(address) returns (uint256): values[0] is *big.Int or int64
  • Signature: (a *ABI) DecodeFunctionResult(functionName string, data []byte) ([]any, error)
  • Returns a slice of values in the order of the function’s outputs.

DecodeFunctionResultInto

Decode return data into a struct (or slice of pointers). Field names are matched case-insensitively to ABI output names, or by position.

type ReservesResult struct {
    Reserve0       *big.Int
    Reserve1       *big.Int
    BlockTimestamp uint32
}
var result ReservesResult
err := parsed.DecodeFunctionResultInto("getReserves", returnData, &result)
  • Signature: (a *ABI) DecodeFunctionResultInto(functionName string, data []byte, output any) error

DecodeEventLog

Decode event log topics and data using a parsed ABI. Identifies the event by the first topic (event signature hash) and decodes indexed and non-indexed parameters.

import (
"github.com/ethereum/go-ethereum/common"
"github.com/ChefBingbong/viem-go/abi"
)
// log.Topics and log.Data from eth_getLogs / FilterLogs
decoded, err := parsed.DecodeEventLog(log.Topics, log.Data)
if err != nil {
log.Fatal(err)
}
fmt.Println(decoded.EventName) // e.g. "Transfer"
fmt.Println(decoded.Args) // map[string]any: "from", "to", "value"
fmt.Println(decoded.Topics) // []common.Hash
fmt.Println(decoded.Data) // raw data bytes
  • Signature: (a *ABI) DecodeEventLog(topics []common.Hash, data []byte) (*DecodedEventLog, error)
  • DecodedEventLog has EventName, Args (map[string]any), Topics, Data.
  • topics[0] must be the event signature (for non-anonymous events).

DecodeEventLogByName

Decode when you already know the event name:

decoded, err := parsed.DecodeEventLogByName("Transfer", log.Topics, log.Data)

DecodeErrorResult

Decode revert data: standard Error(string) and Panic(uint256) plus custom errors defined on the ABI.

import "github.com/ChefBingbong/viem-go/abi"
// errorData is the revert payload from a failed call
decoded, err := parsed.DecodeErrorResult(errorData)
if err != nil {
log.Fatal(err)
}
fmt.Println(decoded.ErrorName) // e.g. "InsufficientBalance" or "Error" or "Panic"
fmt.Println(decoded.Args) // []any
fmt.Println(decoded.Selector) // [4]byte
// decoded.AbiItem is *Error for custom errors, nil for Error(string)/Panic(uint256)
  • Signature: (a *ABI) DecodeErrorResult(data []byte) (*DecodedErrorResult, error)
  • DecodedErrorResult has ErrorName, Args ([]any), Selector ([4]byte), AbiItem (*Error or nil).
  • DecodeErrorResultWithoutABI(data []byte) decodes only Error(string) and Panic(uint256) without a parsed ABI.

Error handling

Always check decoding errors. Invalid data, wrong length, or mismatched ABI will return descriptive errors (e.g. "function with selector ... not found", "data too short").

decoded, err := parsed.DecodeFunctionData(calldata)
if err != nil {
    log.Printf("decode error: %v", err)
    return
}

Go notes

  • DecodeFunctionData and DecodeEventLog require the ABI to contain the function/event; otherwise they return "not found" errors.
  • Event topics are []common.Hash; convert from RPC hex strings if needed (e.g. common.HexToHash).
  • Decoded integers may be int64 or *big.Int depending on size; see ABI Types.

See also