viem-goviem-go

simulateContract

Simulates/validates a contract interaction

This is useful for retrieving return data and revert reasons of contract write functions. This function does not require gas to execute and does not change the state of the blockchain. It is almost identical to ReadContract, but also supports contract write functions.

Import

Import the public actions package so you can call this action.

import "github.com/ChefBingbong/viem-go/actions/public"

Usage

An example showing how to simulate a token transfer without sending a real transaction.

import (
"context"
"log"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ChefBingbong/viem-go/actions/public"
"github.com/ChefBingbong/viem-go/abi"
"github.com/ChefBingbong/viem-go/client"
"github.com/ChefBingbong/viem-go/client/transport"
"github.com/ChefBingbong/viem-go/chain/definitions"
)
ctx := context.Background()
publicClient, err := client.CreatePublicClient(client.PublicClientConfig{
Chain: definitions.Mainnet,
Transport: transport.HTTP("https://eth.llamarpc.com"),
})
if err != nil {
log.Fatal(err)
}
defer func() { _ = publicClient.Close() }()
// Parse ERC20 ABI
erc20ABI, err := abi.ParseABI(`[{"inputs":[{"name":"to","type":"address"},{"name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"type":"bool"}],"type":"function"}]`)
if err != nil {
log.Fatal(err)
}
tokenAddr := common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")
senderAddr := common.HexToAddress("0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266")
recipientAddr := common.HexToAddress("0x70997970c51812dc3a010c7d01b50e0d17dc79c8")
result, err := public.SimulateContract(ctx, publicClient, public.SimulateContractParameters{
Account: &senderAddr,
Address: tokenAddr,
ABI: erc20ABI,
FunctionName: "transfer",
Args: []any{recipientAddr, big.NewInt(1000000)},
})
if err != nil {
log.Fatal(err)
}
if result.Result.(bool) {
log.Println("Simulation successful!")
}

Returns

*SimulateContractReturnType

An object containing:

  • Result any - The decoded return value from the contract call
  • Request SimulateContractRequest - The request data that can be used for writeContract

Parameters

Configuration options accepted by this action.

Address

  • Type: common.Address
  • Required

The contract address.

import (
"github.com/ethereum/go-ethereum/common"
"github.com/ChefBingbong/viem-go/actions/public"
)
tokenAddr := common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")
result, err := public.SimulateContract(ctx, publicClient, public.SimulateContractParameters{
Address: tokenAddr,
ABI: erc20ABI,
FunctionName: "transfer",
Args: []any{recipientAddr, big.NewInt(1000000)},
})

ABI

  • Type: *abi.ABI
  • Required

The contract ABI.

import "github.com/ChefBingbong/viem-go/abi"
erc20ABI, err := abi.ParseABI(`[{"inputs":[...],"name":"transfer",...}]`)
result, err := public.SimulateContract(ctx, publicClient, public.SimulateContractParameters{
Address: tokenAddr,
ABI: erc20ABI,
FunctionName: "transfer",
Args: []any{recipientAddr, big.NewInt(1000000)},
})

FunctionName

  • Type: string
  • Required

The name of the function to call.

result, err := public.SimulateContract(ctx, publicClient, public.SimulateContractParameters{
Address: tokenAddr,
ABI: erc20ABI,
FunctionName: "transfer",
Args: []any{recipientAddr, big.NewInt(1000000)},
})

Args

  • Type: []any
  • Optional

The function arguments.

import "math/big"
result, err := public.SimulateContract(ctx, publicClient, public.SimulateContractParameters{
Address: tokenAddr,
ABI: erc20ABI,
FunctionName: "transfer",
Args: []any{recipientAddr, big.NewInt(1000000)},
})

Account

  • Type: *common.Address
  • Optional

The account attached to the call (msg.sender).

senderAddr := common.HexToAddress("0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266")
result, err := public.SimulateContract(ctx, publicClient, public.SimulateContractParameters{
Account: &senderAddr,
Address: tokenAddr,
ABI: erc20ABI,
FunctionName: "transfer",
Args: []any{recipientAddr, big.NewInt(1000000)},
})

Value

  • Type: *big.Int
  • Optional

The amount of wei to send with the call.

import "math/big"
result, err := public.SimulateContract(ctx, publicClient, public.SimulateContractParameters{
Address: tokenAddr,
ABI: erc20ABI,
FunctionName: "transfer",
Args: []any{recipientAddr, big.NewInt(1000000)},
Value: big.NewInt(1000000000000000000), // 1 ETH
})

BlockNumber

  • Type: *uint64
  • Optional

The block number to simulate at.

blockNum := uint64(12345)
result, err := public.SimulateContract(ctx, publicClient, public.SimulateContractParameters{
Address: tokenAddr,
ABI: erc20ABI,
FunctionName: "transfer",
Args: []any{recipientAddr, big.NewInt(1000000)},
BlockNumber: &blockNum,
})

BlockTag

  • Type: BlockTag
  • Optional

The block tag to simulate at (e.g., "latest", "pending").

result, err := public.SimulateContract(ctx, publicClient, public.SimulateContractParameters{
Address: tokenAddr,
ABI: erc20ABI,
FunctionName: "transfer",
Args: []any{recipientAddr, big.NewInt(1000000)},
BlockTag: public.BlockTagSafe,
})

StateOverride

  • Type: types.StateOverride
  • Optional

State overrides for the call.

BlockOverrides

  • Type: *types.BlockOverrides
  • Optional

Block-level overrides.

DataSuffix

  • Type: []byte
  • Optional

Optional data to append to the calldata. Useful for adding a "domain" tag.

JSON-RPC Method

Underlying JSON-RPC method used by this action.

Uses eth_call with ABI-encoded data.