Skip to main content
Package core/types contains the consensus-layer data structures used throughout go-ethereum. You will interact with these types whenever you read from the chain or construct transactions.
import "github.com/ethereum/go-ethereum/core/types"

Block

Block is immutable after construction. Header data is returned as a copy to protect internal caches.
type Block struct { /* unexported */ }
Accessor methods:
func (b *Block) Number() *big.Int          // block number
func (b *Block) Hash() common.Hash         // keccak256 of the RLP-encoded header
func (b *Block) Time() uint64              // Unix timestamp
func (b *Block) GasLimit() uint64          // maximum gas per block
func (b *Block) GasUsed() uint64           // gas consumed by all transactions
func (b *Block) BaseFee() *big.Int         // EIP-1559 base fee (nil for pre-London blocks)
func (b *Block) Difficulty() *big.Int      // PoW difficulty (zero post-merge)
func (b *Block) Coinbase() common.Address  // fee recipient
func (b *Block) Root() common.Hash         // state trie root
func (b *Block) TxHash() common.Hash       // transactions trie root
func (b *Block) ReceiptHash() common.Hash  // receipts trie root
func (b *Block) ParentHash() common.Hash   // hash of the parent block
func (b *Block) Extra() []byte             // extra data field
func (b *Block) Transactions() Transactions // ordered list of transactions
func (b *Block) Uncles() []*Header         // uncle headers (PoW era)
func (b *Block) Withdrawals() Withdrawals  // EIP-4895 validator withdrawals
func (b *Block) Header() *Header           // copy of the header
func (b *Block) Body() *Body               // transactions, uncles, withdrawals
func (b *Block) NumberU64() uint64         // block number as uint64

Iterating transactions in a block

block, err := client.BlockByNumber(ctx, nil) // latest
for _, tx := range block.Transactions() {
    fmt.Printf("%s  gas=%d\n", tx.Hash().Hex(), tx.Gas())
}
Header holds all block metadata and is cheaper to fetch than a full Block.
type Header struct {
    ParentHash  common.Hash
    UncleHash   common.Hash
    Coinbase    common.Address
    Root        common.Hash    // state root
    TxHash      common.Hash    // transactions root
    ReceiptHash common.Hash    // receipts root
    Bloom       Bloom
    Difficulty  *big.Int
    Number      *big.Int
    GasLimit    uint64
    GasUsed     uint64
    Time        uint64
    Extra       []byte
    MixDigest   common.Hash
    Nonce       BlockNonce

    // EIP-1559 (London)
    BaseFee *big.Int

    // EIP-4895 (Shanghai)
    WithdrawalsHash *common.Hash

    // EIP-4844 (Cancun)
    BlobGasUsed   *uint64
    ExcessBlobGas *uint64

    // EIP-4788 (Cancun)
    ParentBeaconRoot *common.Hash

    // EIP-7685 (Prague)
    RequestsHash *common.Hash
}

func (h *Header) Hash() common.Hash

Transaction

Transaction types

ConstantType IDEIPDescription
LegacyTxType0x00pre-EIP-2718gasPrice-based
AccessListTxType0x01EIP-2930adds accessList
DynamicFeeTxType0x02EIP-1559maxFeePerGas + maxPriorityFeePerGas
BlobTxType0x03EIP-4844blob-carrying transactions
SetCodeTxType0x04EIP-7702code delegation

Creating transactions

Signing a transaction

func SignTx(tx *Transaction, s Signer, prv *ecdsa.PrivateKey) (*Transaction, error)
Use types.LatestSignerForChainID when you know the chain ID but not the specific fork:
signer := types.LatestSignerForChainID(chainID)
signedTx, err := types.SignTx(tx, signer, privateKey)
Or use types.MakeSigner when you have both the chain config and current block number.

Transaction accessor methods

func (tx *Transaction) Hash() common.Hash     // transaction hash
func (tx *Transaction) Type() uint8           // LegacyTxType, DynamicFeeTxType, etc.
func (tx *Transaction) To() *common.Address   // nil for contract-creation transactions
func (tx *Transaction) Value() *big.Int       // wei amount
func (tx *Transaction) Gas() uint64           // gas limit
func (tx *Transaction) GasPrice() *big.Int    // legacy gas price
func (tx *Transaction) GasFeeCap() *big.Int   // EIP-1559 maxFeePerGas
func (tx *Transaction) GasTipCap() *big.Int   // EIP-1559 maxPriorityFeePerGas
func (tx *Transaction) Data() []byte          // input data / calldata
func (tx *Transaction) Nonce() uint64         // sender nonce
func (tx *Transaction) ChainId() *big.Int     // EIP-155 chain ID
func (tx *Transaction) AccessList() AccessList
func (tx *Transaction) Cost() *big.Int        // gas*gasPrice + blobGas*blobGasPrice + value

Receipt

A receipt is created after a transaction is mined and records its outcome.
type Receipt struct {
    // Consensus fields
    Type              uint8   // transaction type
    PostState         []byte  // pre-Byzantium: state root after the tx
    Status            uint64  // 1 = success, 0 = failure (post-Byzantium)
    CumulativeGasUsed uint64  // gas used up to and including this tx in the block
    Bloom             Bloom   // logs bloom filter
    Logs              []*Log  // events emitted by this transaction

    // Implementation fields (added by the node)
    TxHash            common.Hash    // transaction hash
    ContractAddress   common.Address // non-zero for contract-creation transactions
    GasUsed           uint64         // gas used by this transaction alone
    EffectiveGasPrice *big.Int       // actual gas price paid
    BlobGasUsed       uint64         // EIP-4844
    BlobGasPrice      *big.Int       // EIP-4844

    // Inclusion metadata
    BlockHash        common.Hash
    BlockNumber      *big.Int
    TransactionIndex uint
}

const (
    ReceiptStatusFailed     = uint64(0)
    ReceiptStatusSuccessful = uint64(1)
)
receipt, err := client.TransactionReceipt(ctx, txHash)
if err != nil {
    log.Fatal(err)
}
if receipt.Status == types.ReceiptStatusSuccessful {
    fmt.Println("transaction succeeded, gas used:", receipt.GasUsed)
} else {
    fmt.Println("transaction reverted")
}
// Contract address (if this was a deployment)
if receipt.ContractAddress != (common.Address{}) {
    fmt.Println("deployed to:", receipt.ContractAddress.Hex())
}

Log

Logs are produced by the EVM LOG opcode (Solidity emit).
type Log struct {
    // Consensus fields
    Address common.Address // contract that emitted the log
    Topics  []common.Hash  // indexed parameters (first topic = event ID)
    Data    []byte         // ABI-encoded non-indexed parameters

    // Derived fields (not part of consensus)
    BlockNumber    uint64
    TxHash         common.Hash
    TxIndex        uint
    BlockHash      common.Hash
    BlockTimestamp uint64
    Index          uint  // log index within the block

    // Removed is true when the log was part of a re-orged-out block
    Removed bool
}
Always check log.Removed when receiving logs via a subscription. A true value means the log was reverted by a chain reorganisation and should be treated as if it never happened.

Reading logs

query := ethereum.FilterQuery{
    Addresses: []common.Address{contractAddress},
    Topics: [][]common.Hash{
        {transferEventID}, // first topic = event selector
    },
    FromBlock: big.NewInt(20_000_000),
    ToBlock:   nil, // latest
}

logs, err := client.FilterLogs(ctx, query)
for _, l := range logs {
    if l.Removed {
        continue
    }
    fmt.Printf("block %d  tx %s  topics: %v\n",
        l.BlockNumber, l.TxHash.Hex(), l.Topics)
}

Build docs developers (and LLMs) love