MorphTx Developer Guide
Abstract
Morph is designed as a payment settlement layer — a high-performance L2 blockchain purpose-built for real-world payment and commerce use cases. To bridge the gap between on-chain transactions and off-chain payment systems, Morph introduces MorphTx (0x7F), a custom EIP-2718 typed transaction that extends the standard EIP-1559 DynamicFeeTx with two key capabilities. MorphTx consolidates and extends the AltFeeTx transaction type introduced in the Emerald upgrade, evolving it into a unified transaction primitive with broader functionality:
Alternative Fee Transaction enables users to pay gas fees using on-chain registered ERC-20 tokens (e.g., USDT, USDC) instead of ETH. This removes a critical barrier for payment adoption — merchants and end users no longer need to hold native ETH to interact with the chain. Fee conversion happens at the protocol level using an on-chain oracle, eliminating any dependency on Paymaster contracts or external bundlers.
Reference Key introduces a 32-byte merchant-controlled index field embedded natively in the transaction structure. This field is designed to meet three requirements for production payment integration:
- Indexed query support — a dedicated on-chain index keyed by Reference allows off-chain systems to efficiently retrieve all transactions associated with a given order, batch, or session, without full chain scanning.
- Zero performance impact — the index is maintained asynchronously during block insertion and uses a prefix-ordered key layout, adding negligible overhead to the critical execution path.
- Merchant-friendly generation — a Reference can be any deterministic 32-byte value: a keccak256 hash of an order ID, a UUID, or a composite business key. No smart contract interaction is required to register or use a Reference.
Together, these features make MorphTx the foundational transaction primitive for payment settlement on Morph: token-denominated fees reduce friction for merchants and users, while Reference-based indexing provides the traceability and reconciliation primitives that payment systems require.
1. New Transaction Type
MorphTx is a custom EIP-2718 typed transaction for Morph L2, with type ID 0x7F (127). It extends the standard DynamicFeeTx (EIP-1559) with the following capabilities:
| Feature | Description |
|---|---|
| Alt Fee (Alternative Token Gas Fee) | Pay gas fees with on-chain registered ERC-20 tokens instead of ETH |
| Reference | 32-byte transaction reference key for on-chain indexing and querying |
| Memo | Up to 64-byte transaction note |
1.1 Version System
MorphTx uses a multi-version encoding format for backward compatibility:
| Version | Constant | Status | Description |
|---|---|---|---|
| V0 | MorphTxVersion0 = 0 | Available after Emerald fork | Legacy format, compatible with original AltFeeTx. Supports Alt Fee only — no Version/Reference/Memo fields. FeeTokenID must be > 0 |
| V1 | MorphTxVersion1 = 1 | Available after Jade fork | New format. Supports Alt Fee + Reference + Memo. All Morph extension fields are optional. FeeTokenID can be 0 (pay with ETH) |
1.2 Key Characteristics
- Gas pricing model: Fully compatible with EIP-1559 — uses
maxFeePerGas+maxPriorityFeePerGas - Signing algorithm: Standard secp256k1 ECDSA, V value is
{0, 1}(same as DynamicFeeTx) - Chain ID binding: ChainID is included in the signing hash to prevent cross-chain replay
2. Data Structures
2.1 Core Struct — MorphTx
Source: core/types/morph_tx.go
type MorphTx struct {
// ===== Same base fields as DynamicFeeTx =====
ChainID *big.Int
Nonce uint64
GasTipCap *big.Int // maxPriorityFeePerGas
GasFeeCap *big.Int // maxFeePerGas
Gas uint64
To *common.Address // nil = contract creation
Value *big.Int
Data []byte
AccessList AccessList
// ===== Morph extension fields =====
Version uint8 // Version (0=V0, 1=V1)
FeeTokenID uint16 // ERC-20 token ID (0=ETH)
FeeLimit *big.Int // Token fee cap
Reference *common.Reference // 32-byte reference key (V1 only)
Memo *[]byte // Note (V1 only, ≤ 64 bytes)
// ===== Signature values =====
V *big.Int
R *big.Int
S *big.Int
}
2.2 Dependent Types
| Type | Defined in | Description |
|---|---|---|
common.Reference | common/types.go | [32]byte fixed-length array, supports Hex/JSON/GraphQL serialization |
common.ReferenceLength | common/types.go | Constant 32 |
common.MaxMemoLength | common/types.go | Constant 64 |
AccessList | core/types/access_list_tx.go | []AccessTuple, EIP-2930 access list |
2.3 Version Validation Rules
Source: core/types/transaction.go → ValidateMorphTxVersion()
| Version | FeeTokenID | FeeLimit | Reference | Memo | Valid? |
|---|---|---|---|---|---|
| V0 | Must be > 0 | Optional | Must be nil/empty | Must be nil/empty | ✅ |
| V0 | = 0 | - | - | - | ❌ ErrMorphTxV0IllegalExtraParams |
| V0 | > 0 | - | Non-empty | - | ❌ ErrMorphTxV0IllegalExtraParams |
| V1 | Any | Any | Any | ≤ 64B | ✅ |
| V1 | = 0 | > 0 | - | - | ❌ ErrMorphTxV1IllegalExtraParams |
| V1 | - | - | - | > 64B | ❌ ErrMemoTooLong |
| Other | - | - | - | - | ❌ ErrMorphTxUnsupportedVersion |
Core constraints:
- V0 is designed specifically for Alt Fee —
FeeTokenIDmust be non-zero - V1 is general-purpose — all extension fields are optional. But if
FeeTokenID == 0(using ETH),FeeLimitmust be zero/nil (no need to cap ETH fees) - Memo max 64 bytes applies to all versions
2.4 Error Types
| Error | Meaning |
|---|---|
ErrMorphTxV0IllegalExtraParams | V0 params invalid (FeeTokenID=0, or Reference/Memo set) |
ErrMorphTxV1IllegalExtraParams | V1 params invalid (FeeTokenID=0 but FeeLimit>0) |
ErrMorphTxUnsupportedVersion | Unsupported version number |
ErrMorphTxV1NotYetActive | V1 tx submitted before Jade fork activation |
ErrMemoTooLong | Memo exceeds 64 bytes |
3. Fork Timeline & Compatibility
MorphTx requires two forks to fully enable:
Timeline ──────────────────────────────────────────────────────────►
│ │ │
│ Emerald │ Jade │
│ Fork │ Fork │
▼ ▼ │
────┼───────────────┼────────────────┼──
│ │ │
│ MorphTxType │ MorphTx V1 │
│ signer │ enabled │
│ enabled │ (V0 + V1) │
│ (V0 only) │ │
│ │ │
3.1 Emerald Fork
Source: core/types/transaction_signing.go → newModernSigner()
Config: params/config.go → EmeraldTime
After Emerald fork activation:
MorphTxType(0x7F) is registered inmodernSigner's supported type listMakeSigner()returns a signer that accepts MorphTx- Only V0 is available (V1 is rejected by tx pool and block validator)
Before Emerald fork:
- MorphTx is rejected at the tx pool level (
ErrTxTypeNotSupported) - EIP-1559 must already be active (MorphTx depends on the
eip1559flag)
3.2 Jade Fork
Source: core/tx_pool.go, core/block_validator.go
Config: params/config.go → JadeForkTime
After Jade fork activation:
- V1 transactions are accepted by the tx pool
- Block validation allows V1 transactions
- Reference index system becomes active
Before Jade fork:
- Tx pool rejects V1:
!pool.jade && tx.IsMorphTx() && tx.Version() == MorphTxVersion1 - Block validation rejects V1:
!isJadeFork && tx.IsMorphTx() && tx.Version() == MorphTxVersion1 - RPC
setDefaultsrejects V1 fields (Reference/Memo) and explicit V1 version
On Jade fork rollback (reorg):
- Tx pool actively removes all V1 transactions (
removeMorphTxV1())
3.3 Fork Configuration Example (Mainnet)
{
"emeraldTime": 1766988000,
"jadeForkTime": 1774418400
}
4. Encoding/Decoding (Wire Format)
4.1 Full Wire Format
MorphTx follows the EIP-2718 envelope format: type byte + inner payload
┌─────────────────────────────────────────────────────────┐
│ Full wire format (MarshalBinary output) │
├──────┬──────────────────────── ──────────────────────────┤
│ 0x7F │ inner payload (generated by encode()) │
│txType│ │
├──────┴──────────────────────────────────────────────────┤
│ │
│ V0 inner payload: │
│ ┌─────────────────────────────────────────────┐ │
│ │ RLP([chainID, nonce, gasTipCap, gasFeeCap, │ │
│ │ gas, to, value, data, accessList, │ │
│ │ feeTokenID, feeLimit, v, r, s]) │ │
│ │ First byte >= 0xC0 (RLP list prefix) │ │
│ │ 14 fields total │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ V1 inner payload: │
│ ┌────┬────────────────────────────────────────┐ │
│ │0x01│ RLP([chainID, nonce, gasTipCap, │ │
│ │ver │ gasFeeCap, gas, to, value, data, │ │
│ │ │ accessList, feeTokenID, feeLimit, │ │
│ │ │ reference, memo, v, r, s]) │ │
│ │ │ 16 fields total │ │
│ └────┴────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
4.2 V0 Encoding
Format: 0x7F || RLP([14 fields])
Field order (inside RLP list):
0. chainID (*big.Int)
1. nonce (uint64)
2. gasTipCap (*big.Int)
3. gasFeeCap (*big.Int)
4. gas (uint64)
5. to (*common.Address, nil=contract creation)
6. value (*big.Int)
7. data ([]byte)
8. accessList (AccessList)
9. feeTokenID (uint16)
10. feeLimit (*big.Int)
11. v (*big.Int)
12. r (*big.Int)
13. s (*big.Int)
Constraint: feeTokenID must be non-zero.
4.3 V1 Encoding
Format: 0x7F || 0x01 || RLP([16 fields])
Field order (inside RLP list):
0. chainID (*big.Int)
1. nonce (uint64)
2. gasTipCap (*big.Int)
3. gasFeeCap (*big.Int)
4. gas (uint64)
5. to (*common.Address, nil=contract creation)
6. value (*big.Int)
7. data ([]byte)
8. accessList (AccessList)
9. feeTokenID (uint16)
10. feeLimit (*big.Int)
11. reference ([]byte, length 0 or 32)
12. memo ([]byte, length 0~64)
13. v (*big.Int)
14. r (*big.Int)
15. s (*big.Int)
Key details:
- The version byte (0x01) is NOT inside the RLP list — it's a prefix byte
referenceandmemouse[]bytetype in RLP (not[32]byte); empty values encode as RLP empty string (0x80)- V1 adds
referenceandmemocompared to V0's 14 fields (16 total)
4.4 Version Detection Algorithm
When decoding inner payload, the first byte determines the version:
firstByte = inner_payload[0]
if firstByte >= 0xC0 or firstByte == 0x00:
→ V0 format (first byte is RLP list prefix)
→ Decode entire payload as RLP list
elif firstByte == 0x01:
→ V1 format (first byte is version)
→ Skip 1 byte, decode remainder as RLP list
else:
→ Unsupported version
Design rationale: V0's RLP list first byte is always >= 0xC0 (RLP list encoding prefix), while V1's first byte is 0x01. They naturally don't overlap in byte space — no extra metadata needed to distinguish them.
4.5 Encoding Paths
Two encoding paths exist, both producing identical byte output:
Path 1: Transaction.MarshalBinary()
└→ Transaction.encodeTyped(buf)
├→ buf.WriteByte(0x7F) // txType prefix
└→ MorphTx.encode(buf) // internal encoding (V0 or V1)
Path 2: rlp.Encode(w, morphTx)
└→ MorphTx.EncodeRLP(w) // custom rlp.Encoder
└→ MorphTx.encode(buf) // same function as Path 1
EncodeRLP ensures that Transaction.Hash() (which internally calls rlp.Encode) produces output consistent with MarshalBinary.
4.6 Decoding Paths
Path 1: Transaction.UnmarshalBinary(bytes)
└→ Transaction.decodeTyped(bytes)
├→ Check bytes[0] == 0x7F
├→ inner = new(MorphTx)
└→ inner.decode(bytes[1:]) // version detection + decode
Path 2: rlp.Decode(reader, &morphTx)
└→ MorphTx.DecodeRLP(stream) // custom rlp.Decoder
├→ stream.Kind() == List → V0
└→ stream.Uint8() + stream.Raw() → V1
Why DecodeRLP is necessary: Go struct field order ([...AccessList, Version, FeeTokenID, ...]) doesn't match V0 wire format ([...AccessList, FeeTokenID, ...]). Reflection-based decoding would cause type overflow errors.
4.7 Transaction Hash
V0: keccak256(0x7F || rlp.Encode(morphTx))
= keccak256(0x7F || RLP([14 fields including signature]))
V1: keccak256(0x7F || rlp.Encode(morphTx))
= keccak256(0x7F || 0x01 || RLP([16 fields including signature]))
Note:
rlp.Encode(morphTx)calls the customEncodeRLP, so V1 output includes the 0x01 prefix.
5. Signing Mechanism
5.1 Signer Requirements
MorphTx must be signed with an Emerald or higher-level signer:
// Recommended
signer := types.NewEmeraldSigner(chainID)
// Or auto-selected by protocol (Emerald must be active)
signer := types.MakeSigner(config, blockNumber, blockTime)
// LatestSignerForChainID returns NewEmeraldSigner
signer := types.LatestSignerForChainID(chainID)
5.2 Signing Hash Calculation
The signing hash is the digest used for signing/verification — it does NOT include V/R/S signature values.
V0 signing hash (11 fields):
sigHash = keccak256(0x7F || rlp([
chainID, nonce, gasTipCap, gasFeeCap, gas, to, value, data,
accessList, feeTokenID, feeLimit
]))
V1 signing hash (14 fields):
sigHash = keccak256(0x7F || rlp([
chainID, nonce, gasTipCap, gasFeeCap, gas, to, value, data,
accessList, feeTokenID, feeLimit, version, reference, memo
]))
V1 adds version, reference, and memo compared to V0.
5.3 Signing Flow
// 1. Construct unsigned transaction
tx := types.NewTx(&types.MorphTx{
ChainID: chainID,
Nonce: nonce,
GasTipCap: gasTipCap,
GasFeeCap: gasFeeCap,
Gas: gasLimit,
To: &toAddr,
Value: value,
Data: data,
FeeTokenID: 1,
FeeLimit: feeLimit,
Version: types.MorphTxVersion0,
})
// 2. Sign
signer := types.NewEmeraldSigner(chainID)
signedTx, err := types.SignTx(tx, signer, privateKey)
Internal flow:
types.SignTx(tx, signer, privateKey)
├→ h = signer.Hash(tx) // modernSigner.Hash
│ └→ tx.inner.sigHash(signer.chainID) // MorphTx.sigHash
│ └→ v0SigHash or v1SigHash // prefixedRlpHash(0x7F, [...])
├→ sig = crypto.Sign(h[:], privateKey) // 65-byte signature
└→ tx.WithSignature(signer, sig)
└→ signer.SignatureValues(tx, sig)
├→ R = sig[0:32]
├→ S = sig[32:64]
└→ V = sig[64] (0 or 1)
5.4 V/R/S Specification
- V value: 0 or 1 (recovery identifier), same as DynamicFeeTx and other modern tx types
- Sender recovery: V + 27 to convert to Homestead format, then call
ecrecover - Signature encoding: Standard 65 bytes:
R (32 bytes) || S (32 bytes) || V (1 byte)
6. RPC Interfaces
6.1 Standard eth Namespace
eth_sendTransaction
Constructs MorphTx via TransactionArgs. Supported Morph-specific fields:
{
"from": "0x...",
"to": "0x...",
"maxFeePerGas": "0x...",
"maxPriorityFeePerGas": "0x...",
"gas": "0x...",
"value": "0x...",
"data": "0x...",
"feeTokenID": "0x1",
"feeLimit": "0x...",
"version": "0x1",
"reference": "0x1234...cdef",
"memo": "0x68656c6c6f"
}
Type auto-detection: The transaction is identified as MorphTx when ANY of these fields are set:
feeTokenID > 0versionis explicitly specifiedreferenceis non-empty and non-zeromemois non-empty
Version auto-inference (setDefaults):
- If
versionis explicitly specified → use it and validate params - If V1-only fields exist (
reference/memo) → auto-set to V1 - Otherwise → default to V0
If you set both gasPrice AND MorphTx fields (e.g., feeTokenID), gasPrice will override the type detection and produce a LegacyTx instead of MorphTx, silently discarding all Morph fields. Always use maxFeePerGas/maxPriorityFeePerGas with MorphTx.
eth_sendRawTransaction
Accepts a signed transaction in RLP-encoded type envelope format:
0x7F || inner_payload
The node automatically decodes via UnmarshalBinary → decodeTyped → MorphTx.decode.
eth_getTransactionByHash / eth_getTransactionByBlockHashAndIndex
Returns RPCTransaction with MorphTx fields:
{
"type": "0x7f",
"chainId": "0xb02",
"nonce": "0x1",
"maxFeePerGas": "0x...",
"maxPriorityFeePerGas": "0x...",
"gas": "0x...",
"to": "0x...",
"value": "0x...",
"input": "0x...",
"accessList": [],
"feeTokenID": "0x1",
"feeLimit": "0x...",
"version": "0x1",
"reference": "0x1234...cdef",
"memo": "0x68656c6c6f",
"v": "0x0",
"r": "0x...",
"s": "0x..."
}
Note:
version,reference,memofields only appear for V1+ transactions (omitempty). V0 transactions only returnfeeTokenIDandfeeLimit.
eth_getTransactionReceipt
Morph extension fields in the receipt:
{
"feeTokenID": "0x1",
"feeLimit": "0x...",
"feeRate": "0x...",
"tokenScale": "0x...",
"version": "0x0",
"reference": null,
"memo": null,
"l1Fee": "0x..."
}
eth_estimateGas
Gas estimation for MorphTx additionally considers:
- Alt Fee token balance and FeeLimit constraint
- L1 Data Fee conversion to token units
- Whether the token is in active state
eth_call
Supports passing Morph fields in CallMsg for simulated execution.
6.2 morph Namespace (Public)
morph_getTransactionHashesByReference
Query transactions associated with a Reference, with pagination support.
Parameters:
{
"reference": "0x1234...cdef",
"offset": "0x0",
"limit": "0x64"
}
Constraints:
limit: max 100offset: max 10000 (prevents linear scan DoS)
Returns: sorted by blockTimestamp + txIndex ascending:
[
{
"transactionHash": "0x...",
"blockNumber": "0x123",
"blockTimestamp": "0x...",
"transactionIndex": "0x0"
}
]
6.3 morph Namespace (Private/Internal)
morph_estimateL1DataFee
Estimates L1 data fee for a transaction. Input is TransactionArgs — Morph fields affect the serialized transaction size and thus the L1 fee.
7. Go SDK Development Guide
7.1 Using ethclient
client, _ := ethclient.Dial("http://localhost:8545")
// Query transactions by Reference
results, err := client.GetTransactionHashesByReference(ctx,
common.HexToReference("0x1234..."),
nil, // offset, default 0
nil, // limit, default 100
)
7.2 Using Contract Bindings (accounts/abi/bind)
Source: accounts/abi/bind/base.go
Morph fields in TransactOpts:
type TransactOpts struct {
// ... standard fields ...
FeeTokenID uint16
FeeLimit *big.Int
Version *uint8 // nil = auto-detect
Reference *common.Reference
Memo *[]byte
}
Usage example:
auth, _ := bind.NewKeyedTransactorWithChainID(key, chainID)
auth.FeeTokenID = 1
auth.FeeLimit = big.NewInt(1000000)
// V1 transaction (with Reference and Memo)
v1 := types.MorphTxVersion1
auth.Version = &v1
ref := common.HexToReference("0x1234...")
auth.Reference = &ref
memo := []byte("payment for order #123")
auth.Memo = &memo
Auto-detect logic (morphTxVersion):
if Version == nil:
if Reference or Memo exists → V1
else → V0
else:
Use specified version and validate parameter compatibility
Transaction type auto-selection: When FeeTokenID != 0 or Version != nil or Reference/Memo exists, BoundContract.transact() calls createMorphTx() instead of createDynamicTx().
7.3 Direct Transaction Construction
// V0 Example: Pay gas with token ID=1
tx := types.NewTx(&types.MorphTx{
ChainID: big.NewInt(2818),
Nonce: 1,
GasTipCap: big.NewInt(1e9),
GasFeeCap: big.NewInt(2e9),
Gas: 21000,
To: &toAddr,
Value: big.NewInt(1e18),
FeeTokenID: 1,
FeeLimit: big.NewInt(5e17),
Version: types.MorphTxVersion0,
})
// V1 Example: Pay with ETH + attach Reference and Memo
ref := common.HexToReference("0xabcd...")
memo := []byte("hello morph")
tx := types.NewTx(&types.MorphTx{
ChainID: big.NewInt(2818),
Nonce: 1,
GasTipCap: big.NewInt(1e9),
GasFeeCap: big.NewInt(2e9),
Gas: 21000,
To: &toAddr,
Value: big.NewInt(1e18),
FeeTokenID: 0, // ETH
Version: types.MorphTxVersion1,
Reference: &ref,
Memo: &memo,
})
// Sign
signer := types.NewEmeraldSigner(big.NewInt(2818))
signedTx, _ := types.SignTx(tx, signer, privateKey)
// Serialize (for sending raw transaction)
rawBytes, _ := signedTx.MarshalBinary()
7.4 Using CallMsg
msg := ethereum.CallMsg{
From: fromAddr,
To: &toAddr,
Gas: 0,
GasFeeCap: big.NewInt(2e9),
GasTipCap: big.NewInt(1e9),
Value: big.NewInt(0),
Data: calldata,
FeeTokenID: 1,
FeeLimit: big.NewInt(5e17),
Version: types.MorphTxVersion0,
}
8. Other Language SDK Guide
8.1 Transaction Type Identifier
- EIP-2718 type byte:
0x7F(127) - This is a typed transaction following the standard envelope format
8.2 Encoding Implementation
V0 Encoding
raw_bytes = [0x7F] + rlp_encode([
chain_id, # big integer
nonce, # uint64
max_priority_fee, # big integer (gasTipCap)
max_fee, # big integer (gasFeeCap)
gas_limit, # uint64
to, # 20 bytes or empty (contract creation)
value, # big integer
data, # bytes
access_list, # [[address, [storage_keys]], ...]
fee_token_id, # uint16 (MUST be > 0)
fee_limit, # big integer
v, # big integer (0 or 1)
r, # big integer
s, # big integer
])
V1 Encoding
raw_bytes = [0x7F, 0x01] + rlp_encode([
chain_id,
nonce,
max_priority_fee,
max_fee,
gas_limit,
to,
value,
data,
access_list,
fee_token_id, # uint16 (can be 0)
fee_limit, # big integer
reference, # bytes (0 or 32 bytes)
memo, # bytes (0~64 bytes)
v,
r,
s,
])
8.3 Signing Implementation
V0 Signing Hash
sig_hash = keccak256(
[0x7F] + rlp_encode([
chain_id, nonce, max_priority_fee, max_fee, gas_limit,
to, value, data, access_list, fee_token_id, fee_limit
])
)
V1 Signing Hash
sig_hash = keccak256(
[0x7F] + rlp_encode([
chain_id, nonce, max_priority_fee, max_fee, gas_limit,
to, value, data, access_list, fee_token_id, fee_limit,
version, reference, memo
])
)
Key differences:
- V0 signing hash does not include
version/reference/memo - V1 signing hash includes
version(value=1),reference(pointer may be nil),memo(pointer may be nil) - In Go, nil pointers encode as RLP empty string (
0x80) — other language SDKs must handle this correctly
Signing & Recovery
- Use standard secp256k1 ECDSA to sign the
sig_hash - V value is the recovery identifier: 0 or 1 (NOT 27/28)
- To recover the sender address, add 27 to V and use
ecrecover
8.4 Decoding Implementation
# Pseudocode
def decode_morph_tx(raw_bytes):
assert raw_bytes[0] == 0x7F # type byte
payload = raw_bytes[1:]
first_byte = payload[0]
if first_byte >= 0xC0 or first_byte == 0x00:
# V0: direct RLP decode
fields = rlp_decode(payload) # 14 fields
assert fields[9] > 0 # feeTokenID must be non-zero
return MorphTxV0(fields)
elif first_byte == 0x01:
# V1: skip version byte
fields = rlp_decode(payload[1:]) # 16 fields
reference = fields[11] # 0 or 32 bytes
memo = fields[12] # 0~64 bytes
return MorphTxV1(fields)
else:
raise Error("unsupported version")
8.5 JSON-RPC Field Mapping
| Go Field | JSON Field | Type | Description |
|---|---|---|---|
GasTipCap | maxPriorityFeePerGas | hex big int | EIP-1559 priority fee |
GasFeeCap | maxFeePerGas | hex big int | EIP-1559 fee cap |
FeeTokenID | feeTokenID | hex uint16 | Token ID |
FeeLimit | feeLimit | hex big int | Token fee cap |
Version | version | hex uint64 | Version (V1+ only) |
Reference | reference | hex bytes32 | Reference key (V1+ only) |
Memo | memo | hex bytes | Memo (V1+ only) |
Note on type differences:
TransactionArgs(sending):versionishexutil.Uint16RPCTransaction(querying):versionishexutil.Uint64txJSON(JSON serialization):versionishexutil.Uint64