Ethereum learning path · 06.02

一笔交易,
究竟写了什么?交易字段 · 从钱包表单到协议字节

钱包说“发送 0.1 ETH”,协议看到的却是一组有顺序、有单位、 有签名域的字节。读懂这些字段,你才真正知道自己授权了什么。

  • 06 · 02 交易与 Gas
  • 76 MIN 阅读与实验
  • 0 → 深入 无需编程基础

The thesis

交易不是一句自然语言命令,而是 一组被精确编码、共同签名、由协议逐项验证的状态转换参数。

00 · Orientation

先不要背字段。先分清四层对象

钱包、原始交易、收据和区块浏览器展示的并不是同一份数据。

第六章第二课 · 主线讨论以太坊执行层交易字段

以太坊交易是由外部账户发起、带有密码学授权、希望改变网络状态的指令。 你在钱包里看到的是人类界面;节点接收的是规范编码后的已签名字节。 交易被执行以后,网络才会产生收据,并把它放进某个区块上下文。[1]

一句精确定义

本课所说的“交易字段”,首先指被编码进原始交易并受签名保护的字段; from、交易哈希、执行状态、实际 Gas、区块高度等虽然常与交易一起显示, 但它们的来源并不相同。

同一个浏览器页面,可能混合四种来源

SIGNED

交易本体

noncetovaluedata、Gas 与费用上限、类型扩展字段、签名。

DERIVED

节点派生

from 由签名恢复;hash 由规范已签名交易编码计算。二者都不是签名交易本体里单独写入的字段。

EXECUTED

执行收据

statusgasUsedlogs 和合约创建地址要等执行之后才知道。

CONTEXT

区块上下文

blockNumbertransactionIndex、区块时间和当块 baseFee 由入块位置决定。

01 · Anatomy

把一笔交易放上解剖台

先看最常见的 Type 2,再切换四种真实用途,观察哪些字段会改变。

下面默认展示一笔 EIP-1559 Type 2 代币调用。点击任一字段,会看到它由谁提供、 节点如何解释、常见误区是什么。所有地址和数值都是固定教学数据,不连接钱包,也不会广播。

Transaction specimen

选择一个交易样本

TYPE 2 · 0x02 ERC-20 transfer 调用代币合约,把 25 枚示例代币记给另一地址
0x02
1 · Ethereum mainnet
42
1.5 gwei
35 gwei
65,000 gas
0x2222…2222 · token contract
0 wei
0xa9059cbb…017d7840
[]
yParity · r · s
这笔交易真正授权的是 主网账户 nonce 42 的候选交易:调用 0x2222…2222,发送 0 ETH,并提交一段代币 transfer calldata。
不是 raw 字段

from

钱包请求对象需要它来选择签名账户;节点则从签名恢复发送者,不把 from 再编码一遍。

不是 raw 字段

transactionHash

签完以后,对完整已签名字节做 Keccak-256 得到;所以签名前还没有最终交易哈希。

不是预先知道

status / gasUsed

只有执行过才知道,属于收据;钱包可以模拟估计,但估计值不是最终事实。

02 · Order

nonce:账户顺序号为什么不能跳?

它是发送账户的顺序闸门,不是时间戳,也不是全网流水号。

对普通 EOA 交易,账户状态里保存“下一笔应使用的 nonce”。如果当前值是 42, 节点只会把 nonce 42 当作下一笔可执行交易;nonce 43 即使先到,也要等待缺口补上。 同一发送账户、同一 nonce 最终只能执行一笔。[2]

40已执行
41已执行
42可执行
43等待
44未来

nonce 42 与账户下一值一致。交易若通过其他有效性检查,就可以进入执行;纳入后账户 nonce 前进到 43。

01

防止重复执行

旧的已签交易再次广播时,发送账户 nonce 已前进,节点不会把它当作一笔新授权再执行。

02

约束账户内顺序

nonce 不是全网顺序;不同账户都可以同时有 nonce 42。它只排列同一发送账户的交易。

03

允许候选替换

用户可用同一 nonce 广播另一个候选,钱包常称“加速”或“取消”;是否接受替换属于交易池策略。

04

回滚也会消耗

交易若已上链但 EVM 执行 revert,状态操作回滚,发送者 nonce 与已花 Gas 不回滚。

四种同名 nonce,职责完全不同

不要把交易 nonce 与其他 nonce 混用
名称 存在位置 作用 本课关系
交易 nonce 发送账户状态 + 交易字段 账户内排序、防止同一授权重复执行 本节主角
ECDSA 临时值 k 签名器内部 生成安全签名,绝不能复用或泄露 不是交易字段
区块 nonce 历史执行层区块头 PoW 时代挖矿字段;PoS 后不再承担挖矿搜索 不是账户顺序
授权 nonce Permit、EIP-7702 等授权结构 约束另一份授权的重放 可能嵌套在扩展字段里

03 · Action

tovalue:先到哪里,带多少 ETH

顶层目的地不一定是资产最终受益人;value 也永远不是代币数量。

两个字段,两种职责

to 是顶层执行首先抵达的 20 字节地址,或在合约创建时为空; value 是随这次顶层执行发送的原生 ETH 数量,以 wei 计。 零地址是一个真实的 20 字节地址,不等于“空 to”。

看起来都像“转账”,字段位置却不同
用户意图 to value data
给 Bob 0.1 ETH Bob 的地址 10¹⁷ wei 0x
给 Bob 25 枚 ERC-20 代币合约地址 0 wei Bob 地址与 25 枚的原始单位
向质押合约存入 32 ETH 存款合约地址 32 × 10¹⁸ wei 验证者公钥等参数
部署新合约 空字节串 / RPC null 可为 0,也可随部署发送 ETH initcode + 构造参数

04 · Payload

calldata:让合约做什么

协议只看到字节;“转账”“授权”“交换”是 ABI、合约代码与界面共同给出的解释。

交易格式把这段字节称为 data;JSON-RPC 常称 input; 当它进入合约的顶层消息调用时,EVM 把它暴露为 calldata。三种名字经常指向同一段原始字节, 但所处语境不同。

ABI microscope

拆解 transfer(address,uint256)

固定教学样本 · 不连接链上

FUNCTION SELECTOR

0xa9059cbb

按常见 ERC-20 ABI,它是 keccak256("transfer(address,uint256)") 的前 4 字节。协议本身不保证这四字节一定代表该函数;仍需结合目标合约代码与 ABI。

PLAIN ETH

data = 0x

最简单 ETH 转账通常没有额外数据;意图主要由 tovalue 表达。

CONTRACT CALL

selector + 参数槽

Solidity ABI 通常以 4 字节函数选择器开头,再用 32 字节槽位编码参数。动态类型还会用偏移量。

CONTRACT CREATE

initcode + 构造参数

to 时,这段字节会作为初始化代码执行;其返回值才成为合约的运行时代码。

PROTOCOL VIEW

只是不透明字节

ABI 是生态约定,不是交易层强制语义;任意合约都可以按自己的方式解释输入。

05 · Resource bound

gasLimit:允许这次执行最多做多少工作

它是 Gas 单位上限,不是费用金额,也不是预测出来的最终 gasUsed。

资源边界

gasUsedgasLimit

若执行需要超过上限,会 Out of Gas;顶层状态变更回滚,但已消耗 Gas 与 nonce 不退回。
UNIT

Gas 是工作量单位

每条 EVM 操作、calldata 字节、状态访问等有协议规定的成本;Gas 不是 ETH,也没有市场价格本身。

LIMIT

上限保护发送者与网络

它给单次执行设硬边界;过低会 Out of Gas,过高不等于一定花完,只会提高最大资金预留。

ESTIMATE

估算不是承诺

eth_estimateGas 在某个状态上模拟。状态、分支或并发条件变化,实际路径可能不同。

RPC NAME

gas 常指 gasLimit

JSON-RPC 交易对象里常写 gas;区块浏览器界面常写 Gas Limit。不要与 gasUsed 混淆。

06 · Price caps

费用字段:给每单位 Gas 设价格边界

Type 2 写的是两个上限;当块 base fee 和执行后的实际费用并不是预先签下的常数。

交易字段

maxFeePerGas

每单位 Gas 愿意支付的总价格上限,包含 base fee 与 priority fee。

区块条件

baseFeePerGas

由区块规则决定,不是 Type 2 交易字段;若高于 max fee,这笔交易当下不能被纳入。

交易字段

maxPriorityFeePerGas

愿意给区块提议者的每 Gas 小费上限;实际小费还受 max fee 剩余空间约束。

Type 2 effective price

effectiveGasPrice = min(maxFeePerGas, baseFeePerGas + maxPriorityFeePerGas)

actual execution fee = gasUsed × effectiveGasPrice

At this block

有效每 Gas 价格21.5 gwei
实际执行费0.00111460 ETH
按 65,000 Gas 的最大费用预算0.00227500 ETH

max fee 覆盖当前 base fee,这笔交易在费用条件上具备入块资格。

字段、区块条件与执行结果不要混成一列
何时确定 属于哪里
gasLimit签名前交易字段 · Gas 单位上限
maxFeePerGas签名前Type 2/3/4 交易字段 · 总单价上限
baseFeePerGas由入块区块确定区块字段 · 不是交易字段
gasUsed执行后RPC 收据上下文 · 实际 Gas
effectiveGasPrice入块并执行后RPC 收据字段 · 实际每 Gas 价格

07 · Domain & proof

chainId、签名摘要、发送者与交易哈希

四个经常被叫作“hash”的东西,必须按生成顺序分开。

签名不是只盖在金额上,而是覆盖该类型规定的整组未签名字段。 改动 noncetodata 或费用上限中的任意一项, 签名摘要都会改变,原签名不再对应。

Type 2 · 精确签名对象

keccak256(0x02 || rlp([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList]))

签名得到的 yParity / r / s 不在自己的签名摘要里;它们随后被加入完整 payload。[6]
SIGNING DIGEST

“我要签什么”

由类型域、chainId 和未签名字段计算。签名器用它生成证明。

keccak(type || unsigned payload)
TRANSACTION HASH

“这份签名交易是谁”

由完整已签名字节计算,包含签名。它在入块前就能确定。

keccak(type || signed payload)

chainId 到底保护什么?

chainId 把签名绑定到一条链的域,避免同一份签名交易被直接搬到另一条使用相同账户规则的链上重放。 Type 1–4 把它作为显式字段;Legacy 交易由 EIP-155 把 chainId 纳入签名前像,并编码进 vchainId 不是节点互联时使用的 network id。

常见显示是否写进 raw tx来源
chainId视类型Type 1–4 显式编码;Legacy 没有独立 chainId 字段,EIP-155 把它纳入签名前像并反映在 v
yParity / r / sTyped 是Type 1–4 使用 yParity / r / s;Legacy 编码 v / r / s
from节点从摘要与签名恢复
hash完整已签名编码的 Keccak-256

08 · Typed envelopes

Type 0–4:不是五种业务,而是五套信封

“转 ETH / 调合约 / 部署合约”描述动作;Type 描述字段格式。两条分类轴不要混在一起。

EIP-2718 定义了 TransactionType || TransactionPayload 的类型化信封。 新功能可以新增类型字节与字段列表,而不必继续挤进 Legacy 的 v。 截至 2026 年 7 月,以太坊主网现行协议交易是 Legacy 加 Type 1–4。[8][12]

LONDON · DEFAULT GENERAL-PURPOSE

Type 2 · EIP-1559 dynamic fee

把单一 gasPrice 拆成总价上限和小费上限,是普通钱包交易的主流格式。

0x02 || RLP([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList, yParity, r, s])
  • 可转 ETH、调用合约或创建合约
  • accessList 可以为空
  • baseFee 不是交易字段
现行以太坊主网交易类型与新增字段
类型 主要目的 费用字段 新增 / 特有字段 可否空 to 创建
Legacy / RPC 0原始格式gasPricewire 无显式 0x00 类型前缀可以
Type 1预声明访问地址与存储槽gasPricechainId, accessList可以
Type 2动态费用通用交易maxPriorityFee + maxFee沿用 accessList可以
Type 3为 Rollup 发布 Blob 数据Type 2 + Blob 费上限maxFeePerBlobGas, blobVersionedHashes不可以
Type 4让 EOA 设置代码委托Type 2 费用字段authorizationList不可以

TYPE 3 · BLOB

交易签的是承诺哈希,不是把 Blob 字节塞进 calldata

Fusaka / PeerDAS 把入块后的 Blob 数据切成列并通过数据可用性采样传播;EVM 仍不能直接读取 Blob 内容。 Type 3 的签名字段只放 blobVersionedHashesmaxFeePerBlobGas。 交易哈希只覆盖规范签名 body,不覆盖交易池提交 wrapper 或入块后的 data-column sidecars。[9][13]

TYPE 4 · EIP-7702

一笔交易里有外层签名,也可能有多份授权签名

授权元组写的是目标代码地址,authority 由元组签名恢复;外层 sender 可以是另一账户。 授权列表先于外层 EVM 调用处理;即使随后的外层执行 revert,已处理的委托与 authority nonce 也不回滚。 委托会持续存在,直到后续授权改写或清除。[10]

09 · Provenance

区块浏览器上显示的,哪些是你签下的?

交易对象、收据、区块上下文与执行追踪常被放在同一页,但它们不是同一层协议对象。

BEFORE EXECUTION

交易本体

  • type 与类型字段
  • nonce / to / value / data
  • Gas 与费用上限
  • 类型扩展字段
  • 签名
AFTER EXECUTION

协议收据

  • status
  • cumulativeGasUsed
  • logsBloom
  • logs
RPC / INDEXER CONTEXT

补充显示

  • from / transactionHash
  • gasUsed / effectiveGasPrice
  • blockHash / blockNumber
  • transactionIndex
  • decoded method / token transfers
常见浏览器字段的真实来源
显示项 用户签下? 什么时候出现 精确含义
Transaction Hash派生自签名结果签名完成后规范已签名交易编码的 Keccak-256
From不单独编码节点拿到交易后即可恢复摘要与签名恢复出的外层发送者
Status执行后顶层执行是否成功;1 不必然等于业务目标实现
Gas Used执行后这笔交易的实际 Gas 消耗
Logs / Token Transfers执行后 / 索引后合约事件与索引器对事件的解释
Block / Position / Time入块后验证者把交易放入的区块上下文
Confirmations后续区块与共识推进后浏览器根据链头或最终性派生的状态

TRANSACTION

真正的协议交易

有发送者签名、nonce、费用字段与独立交易哈希;可进入交易池和区块,并产生收据。

ETH_CALL

节点本地模拟

在指定状态上执行 call object,状态改动不持久化,不消耗真实 nonce 或 ETH,不产生链上交易哈希与收据。

INTERNAL TRANSACTION

其实是执行追踪

合约内部 CALL / DELEGATECALL / CREATE 等执行帧没有自己的外层签名、nonce、独立交易哈希或收据。

10 · Synthesis

把一笔交易重新装回去

从“我要做什么”,到“协议究竟接受了哪组字节”。

签名前的八项字段检查

  1. 01

    链对吗?核对 chainId 与钱包网络,尤其是跨链桥、测试网和同地址多链场景。

  2. 02

    真正的 to 是谁?区分最终接收者、代币合约、路由合约与代理合约。

  3. 03

    value 是多少 ETH?它与代币金额、最大手续费是三回事。

  4. 04

    calldata 被可靠解码了吗?核对函数、recipient、spender、amount、min received 与 deadline。

  5. 05

    nonce 是否符合你的 pending 队列?替换候选必须使用预期的同一 nonce。

  6. 06

    gasLimit 合理吗?过低可能 Out of Gas;异常高值要结合模拟与调用复杂度判断。

  7. 07

    费用上限能接受吗?看 max fee,而不是只看钱包估算的“预计费用”。

  8. 08

    有没有类型扩展?Blob 或 EIP-7702 授权列表代表额外能力,不能当成普通 Type 2 略过。

Comprehension check

六道题,检验你是否真的分层了

已完成 0 / 6

1. 下列哪一项通常显示在交易对象里,却不是规范签名交易本体的序列化字段?

2. 一笔 ERC-20 转账里,代币数量通常写在哪里?

3. 交易已经入块,但合约执行 revert。哪项说法正确?

4. gasLimit = 65,000 最准确的意思是?

5. Type 3 的规范签名 body 会把完整 Blob 字节写进去吗?

6. 哪一项在签名完成、尚未入块时就可以确定?

如果只记住一句话

先问一个值来自哪里:是用户签下的字段、节点从签名派生的身份、 EVM 执行后的收据,还是验证者决定的区块上下文?来源一分开,绝大多数交易概念就不会混。

11 · Sources & glossary

术语速查与一手资料

课程按 2026 年 7 月以太坊主网现行规则核对;协议变化时,以当前规范与已激活升级为准。

raw transaction 需结合类型判断的“原始交易”

工具常用 raw 泛指已签名字节。对普通类型,它通常就是可提交的规范签名交易编码;Type 3 则要区分计算交易哈希的 signed body,与提交时还携带 blobs、commitments、cell proofs 的网络 wrapper。

signing preimage / digest 签名前像 / 签名摘要

按类型和字段顺序构造、尚未加入外层签名的字节,以及对它做 Keccak-256 得到的 32 字节摘要。

calldata 调用数据

消息调用传给合约的只读输入字节。交易层字段常叫 data,RPC 常叫 input;ABI 是常见解释约定。

receipt 交易收据

交易执行后产生的协议结果对象,核心包含状态、累计 Gas、日志布隆过滤器和日志;RPC 会附加更多上下文。

access list 访问列表

预先列出将访问的地址与存储槽,使其以“已预热”成本计价;它不是访问白名单,未列资源仍可被访问。

internal transaction 内部交易

浏览器对合约内部调用或价值移动的通俗命名。协议上它们是执行帧或 trace,不是独立签名交易。

  1. [1]
    ethereum.org · Transactions

    交易定义、基础字段、calldata、合约创建与类型化交易概览。

  2. [2]
    ethereum.org · Ethereum accounts

    账户 nonce、EOA 与合约账户的协议语义。

  3. [3]
    EIP-2681 · Limit account nonce to 2⁶⁴−1

    账户 nonce 的共识上限。

  4. [4]
    Solidity · Contract ABI Specification

    函数选择器、静态与动态参数的规范编码。

  5. [5]
    EIP-7825 · Transaction Gas Limit Cap

    Fusaka 激活的单笔交易 Gas Limit 上限。

  6. [6]
    EIP-1559 · Fee Market Change

    Type 2 字段顺序、签名摘要与有效 Gas 价格规则。

  7. [7]
    EIP-155 · Simple Replay Attack Protection

    Legacy 交易如何把 chainId 纳入签名前像与 v。

  8. [8]
    EIP-2718 · Typed Transaction Envelope

    类型字节、payload 与 Legacy 兼容边界。

  9. [9]
    EIP-4844 · Shard Blob Transactions

    Type 3 字段、Blob 费与 versioned hashes。

  10. [10]
    EIP-7702 · Set Code for EOAs

    Type 4、authorizationList、双层签名与委托处理。

  11. [11]
    ethereum.org · JSON-RPC API

    交易对象、eth_call、收据与执行上下文字段。

  12. [12]
    Ethereum Execution Specs · Transactions

    当前 fork 的交易联合类型、编码、签名恢复与交易哈希参考实现。

  13. [13]
    EIP-7594 · PeerDAS

    Fusaka 后 Blob 数据列、cell proofs、交易池 wrapper 与共识传播规则。

One transaction · four origins

字段写下意图,签名封住意图;执行产生结果,区块赋予位置。

回到本课顶部 ↑