Skip to main content

Purpose and Scope

This document describes the data structures, type hierarchy, and encoding formats of transactions used in StableNet.
It covers the six supported transaction types, the role of each type, encoding formats (RLP, binary, JSON), as well as signing and hash calculation rules.
Related documents:

Transaction Type Hierarchy

StableNet supports six transaction types through a polymorphic type hierarchy.
All transaction types implement the TxData interface and are wrapped by the top-level Transaction structure.

Supported Types

TypeConstantValueDescription
LegacyLegacyTxType0x00Pre–EIP-2718 legacy format
Access ListAccessListTxType0x01EIP-2930 access list transaction
Dynamic FeeDynamicFeeTxType0x02EIP-1559 dynamic fee transaction
BlobBlobTxType0x03EIP-4844 data availability transaction
Set CodeSetCodeTxType0x04EIP-7702 code delegation
Fee DelegatedFeeDelegateDynamicFeeTxType0x16 (22)StableNet fee-delegated transaction

TxData Interface

All transaction types implement the TxData interface (core/types/transaction.go), which defines the following responsibilities:
  • Type identification: txType() byte
  • Field accessors: chainID(), nonce(), gas(), gasPrice(), gasTipCap(), gasFeeCap(), value(), to(), data(), accessList()
  • Signature handling: rawSignatureValues(), setSignatureValues()
  • Fee delegation extension: feePayer(), rawFeePayerSignatureValues()
  • Gas calculation: effectiveGasPrice(baseFee, gasTip)
  • Encoding/decoding: encode(*bytes.Buffer), decode([]byte)

Transaction Wrapper

The Transaction structure acts as a common wrapper for all transaction types and provides:
  • Type-agnostic interface: Holds an internal TxData implementation
  • First-seen timestamp: Records when the transaction was first observed locally
  • Cached computations: Hash, size, sender, and fee payer addresses cached via atomic.Value
  • Immutability: Transactions are immutable after creation; modifications require creating a new instance

Individual Transaction Types

Legacy Transaction (Type 0x00)

The basic transaction format used prior to EIP-2718, with the simplest structure.
FieldTypeDescription
Nonceuint64Account nonce
GasPrice*big.IntGas price in Wei
Gasuint64Gas limit
To*common.AddressRecipient address (nil for contract creation)
Value*big.IntTransferred value
Data[]byteCall data
V, R, S*big.IntECDSA signature values

Access List Transaction (Type 0x01)

Introduced by EIP-2930, this transaction pre-declares addresses and storage keys accessed during execution. Additional characteristics:
  • Includes ChainID: Prevents replay attacks
  • Includes AccessList: Address and storage slot list
  • Simplified signature format: Uses yParity (0 or 1)

Dynamic Fee Transaction (Type 0x02)

An EIP-1559-based transaction that separates base fee and priority fee.
FieldDescription
GasTipCapMaximum priority fee
GasFeeCapMaximum total gas cost
The effective gas price is calculated as: min(GasTipCap + BaseFee, GasFeeCap) In StableNet, governance policy may restrict GasTipCap to a block-header-defined value.

Blob Transaction (Type 0x03)

A data availability transaction introduced by EIP-4844. Additional fields:
  • BlobFeeCap: Maximum fee per blob gas
  • BlobHashes: Versioned blob commitment hashes
  • Sidecar: Actual blob data
Constraints:
  • Contract creation is not allowed
  • Sidecar data is excluded from hash calculation
  • Blob-related values use uint256.Int

Set Code Transaction (Type 0x04)

An EIP-7702-based transaction that allows an EOA to delegate execution code. Additional field:
  • AuthList: Authorization list for code delegation
Constraints:
  • Contract creation is not allowed
  • AuthList must not be empty
  • Delegations already processed are not rolled back even if execution fails

Fee-Delegated Transaction (Type 0x16)

A StableNet-specific extension where a third party pays the gas fee. Additional fields:
  • FeePayer: Fee-paying address
  • FV, FR, FS: Fee payer signature values
Two signatures are required:
  1. Sender signature: Approves the transaction contents
  2. Fee payer signature: Approves payment of gas fees
During state transition, only the fee payer’s balance is used to pay gas costs.

Encoding Formats

RLP Encoding

RLP is the primary format used for network transmission and storage. Legacy transactions:
RLP([Nonce, GasPrice, Gas, To, Value, Data, V, R, S])
Typed transactions:
type_byte || RLP([field1, field2, ...])
The first byte distinguishes legacy and typed transactions.

Binary Encoding

MarshalBinary() / UnmarshalBinary() provide the canonical EIP-2718 binary encoding.
This encoding is used for hash and signature calculation.

JSON Encoding

A human-readable format used by RPC interfaces.
  • All numeric values are hex-encoded strings
  • Typed transactions include yParity
  • v and yParity must be consistent

Transaction Signing

Signer Selection Logic

The signer is selected based on chain configuration and block state.
if IsCancun(blockNumber, blockTime):    → CancunSigner
else if AnzeonEnabled():                → AnzeonSigner
else if IsLondon(blockNumber):          → LondonSigner
else if IsBerlin(blockNumber):          → EIP2930Signer
else if IsEIP155(blockNumber):          → EIP155Signer
else if IsHomestead(blockNumber):       → HomesteadSigner
else:                                   → FrontierSigner
AnzeonSigner handles StableNet extensions, including Set Code transactions.

Signing and Recovery

  • Signatures are generated over the hash excluding signature fields
  • The sender address is recovered via Sender()
  • For fee-delegated transactions, the fee payer address is recovered separately via FeePayer()

Transaction Hashing

Hash Calculation Rules

Legacy transactions:
keccak256(rlp([...]))
Typed transactions:
keccak256(type_byte || rlp([...]))
Hashes are cached after the first computation.

Blob Transaction Special Case

Blob transaction hashes do not include sidecar data.
The hash remains identical regardless of whether the sidecar is present.

Integration with State Transitions

Before execution, a transaction is converted into a Message structure via TransactionToMessage().
  • Extract sender and fee payer addresses
  • Compute gas pricing
  • Apply fee delegation information
  • Include flags to skip signature checks for RPC calls
This ensures that transactions follow a unified execution path for both block execution and RPC simulation.