01 · Orientation
先把四个词分开
地址、账户、钱包、控制权处在四个不同层次。
第四章收束 · 经典模型为主,现代边界校准为辅
当钱包界面显示“账户 1:0x7A…19,余额 3.2 ETH”时,一行 UI 把四件事压在了一起:一个地址、一条链上账户记录、 一个帮你签名和发送请求的钱包,以及决定请求是否被授权的 控制规则。不先拆开它们,后面所有概念都会粘在一起。
在执行层的经典模型里,世界状态可以先想成一张巨大映射: 用 20 字节地址查找账户记录;记录里保存 nonce、ETH 余额、存储根和代码哈希。[1]
σ′ = Υ( σ, ordered transactions ) σ 是旧世界状态,σ′ 是新世界状态。Υ 表示协议规定的状态转换规则。 地址只是索引;“这个变化是否被允许”还要看签名、代码和交易上下文。
四层心智模型
地址是索引
像数据库键,用来定位状态与接收消息。它不是用户名,也不自动说明背后是谁。
账户是状态记录
协议关心的是 nonce、原生 ETH 余额、代码承诺和持久存储承诺。
钱包是交互工具
管理密钥或智能账户权限、构造请求、展示资产;钱包不等于链上的账户。
控制权是一套规则
经典 EOA 看有效签名,合约账户看代码;现代智能账户可以组合多种授权策略。
这也解释了一个常见句子:“币在我的钱包里”只是方便表达。
ETH 余额保存在以太坊状态中,ERC-20 余额通常保存在代币合约的
balances[address] 映射里;钱包读取这些状态并替你组织授权请求。
你真正保管的是能满足控制规则的秘密或凭证。
下一章会专门解释私钥、公钥、地址与助记词;第六章会拆交易字段和传播流程; 第十一章会拆状态树。本课只引入足够细节,把账户模型装完整。
02 · State model
为什么以太坊选择账户模型?
UTXO 追踪“还没花掉的输出”,账户模型维护“当前状态”。
想象两种记账方式。第一种把每张未使用的现金券单独编号:付款时销毁旧券, 再创建收款券与找零券。第二种为每个人维护一行余额:付款时直接减少 Alice, 增加 Bob。前者接近比特币的 UTXO 模型,后者接近以太坊的账户模型。
Interactive · 01
同一笔 2 ETH 支付,两种状态表示
点击“执行支付”,观察被消费的输出与被原地更新的余额。
UTXO · 未花费输出集合
花掉整张旧输出,再产生收款输出与找零输出;不是把某张券“改小”。
ACCOUNT · 地址到账户状态
同一全局状态里的余额字段被更新;交易历史仍然保留,并不是抹掉旧历史。
初始 Alice 在 UTXO 侧拥有两张独立输出;在账户侧拥有一条 4.5 ETH 余额记录。
| 问题 | UTXO 模型 | 账户模型 |
|---|---|---|
| 当前状态是什么 | 所有尚未被消费的输出集合 | 地址到账户记录与合约存储的映射 |
| 支付如何发生 | 消费旧输出,创建新输出 | 验证后更新相关账户字段 |
| 找零如何表示 | 通常创建新的找零输出 | 发送者剩余余额留在同一账户 |
| 复杂程序状态 | 通常要把状态附着在输出与脚本设计上 | 合约地址天然拥有可持续更新的存储空间 |
| 并行分析 | 输入集合明确,冲突通常更局部 | 多个调用可能触碰共享状态,需要处理依赖顺序 |
账户模型给以太坊带来了什么?
最大收益不是“看起来像银行余额”,而是复杂状态的连续性。 一个借贷合约可以在固定地址下持续维护抵押率、债务、利率索引和清算参数; 下一笔调用直接读取上一次调用留下的状态。多份合约还能在同一笔交易中互相调用, 形成可组合应用。
代价也很真实:共享可变状态让执行顺序重要。两笔交易分别看都有效, 换序后可能得到不同结果;因此账户模型不仅要回答“余额多少”,还要用 nonce、 Gas、确定性执行与共识顺序共同约束状态推进。
账户模型更新的是当前世界状态。区块和交易历史仍以可验证方式保留, 所以节点可以从较早状态按顺序重放交易,重新计算后来的状态。
03 · Account record
账户记录里,究竟存了什么?
地址不是记录的一部分;它是找到记录的键。
初学者常把账户想成一张“姓名、密码、余额”表。协议并不认识姓名,也不保存密码。 执行层关注四个字段:nonce、balance、storageRoot、codeHash。 这四个字段既能表示普通 EOA,也能表示拥有代码和存储的合约账户。
Interactive · 02
账户记录检查器
切换三种形态。第三种展示 Pectra 之后不能忽略的委托 EOA。
经典 EOA
0x7A4c…A219授权
控制规则私钥产生的有效签名
- nonce
- 7已发送 7 笔顶层交易;下一笔通常使用 nonce 7。
- balance
- 3.200000 ETH这里只是协议原生 ETH 余额,不是所有 ERC-20 资产总额。
- storageRoot
- EMPTY_STORAGE_ROOT经典 EOA 通常没有持久合约存储。
- codeHash
- keccak256("")经典 EOA 的代码为空;这是入门二分法。
经典视图 地址由密钥体系导出,私钥签名授权顶层交易;账户本身不保存私钥。
四个字段逐一拆开
nonce 是顺序与唯一性的计数器。对经典 EOA,可把它理解为已发出交易的顺序号; 网络不会在同一账户状态下接受两笔相同 nonce 的交易都成功执行。对合约账户, nonce 还参与跟踪合约创建。它不是全网统一区块高度,也不是钱包随意生成的备注。
balance 以 wei 记录原生 ETH,1 ETH = 1018 wei。 它不自动包括 USDC、WETH 或 NFT。那些资产的“谁拥有多少”通常写在各自合约存储中; 区块浏览器和钱包只是把多个合约的查询结果汇总展示。
storageRoot 是该账户持久存储内容的密码学承诺。你不需要现在掌握 trie, 只要知道它让一份可能很大的键值存储被一个固定大小的根值承诺。 合约执行改变存储槽后,这个根也会改变。
codeHash 承诺该账户的 EVM 代码。收到消息调用时,执行客户端据此取得代码并执行。 经典 EOA 的代码为空;传统合约账户拥有运行时字节码。EIP-7702 会在这里放入一个特殊 “委托指示器”,所以“有代码就一定是传统合约”已不再绝对。[3]
“任意 0x 地址都已经有一个账户”也不严谨。地址空间巨大,某个地址可能尚无状态记录; 协议还区分不存在、空账户与非空账户。入门时先抓住“地址是索引”,不要把每个可能地址想成预先建好的文件夹。
04 · Authority
两类经典账户,差异在控制规则
两者都能拥有地址和 ETH;真正的分界是如何触发行为。
Externally owned account
- 控制:满足协议要求的数字签名。
- 起点:经典模型中可以主动发起顶层交易。
- 创建:离线生成密钥即可得到地址,不需要链上部署。
- 行为:若没有委托代码,收到普通转账不会运行自定义程序。
- 风险:私钥泄露通常意味着攻击者获得同等控制力。
Contract account
- 控制:部署在地址上的代码与其持久状态。
- 起点:传统模型中不能凭空发起顶层交易,只能被调用后继续发送消息。
- 创建:部署执行消耗 Gas,并产生运行时代码和地址。
- 行为:收到调用时可转账、改存储、调用其他合约或创建合约。
- 风险:代码会忠实执行,包括漏洞、错误权限与恶意逻辑。
“合约账户没有私钥”并不等于“没人能管理它”。合约代码可以规定: 只有某个 EOA 签名者、多个管理员、DAO 投票或时间锁满足条件时才能执行某函数。 这些私钥控制的是调用权限,而不是合约地址天然对应的一把私钥。
反过来,“EOA 由私钥控制”也不代表私钥被存进链上账户。 私钥永远不应公开;节点通过签名恢复或验证授权者,再检查 nonce、余额和交易规则。 密钥与地址的数学关系会在下一章完整展开。
两类账户都能做什么?
| 能力 | 经典 EOA | 传统合约账户 |
|---|---|---|
| 拥有地址 | 是 | 是 |
| 持有原生 ETH | 是 | 是 |
| 成为 ERC-20 / NFT 所有者 | 是,记录在资产合约中 | 是,记录在资产合约中 |
| 发起协议顶层交易 | 是,由签名授权 | 经典模型下不是 |
| 收到调用后执行自定义代码 | 经典模型下不是 | 是 |
| 自定义多签、限额、恢复 | 原生规则很有限 | 可以由代码定义 |
不要只背“EOA 无代码、合约有代码”。先问: 什么证据允许它发起请求?收到消息后,是否有代码决定下一步? 这个问法在 EIP-7702 之后仍然有效。
05 · State transition
一次调用,改变的从来不只一个账户
用 Alice 向 Vault 存入 1 ETH,看账户模型如何原子推进。
Alice 在钱包中确认 Vault.deposit(),看起来只是点了一次按钮。
对执行层而言,这是一条有序状态转换:验证发送者、消费 nonce、计费、
转移 ETH、运行 Vault 代码、更新合约存储,最后把多处变化共同写进新世界状态。
Interactive · 03
一笔存款调用的状态切片
费用用 0.002 ETH 的教学示例表示,不代表实时费率。
Alice · EOA0x7A4c…A219
- nonce
- 7
- ETH balance
- 5.000 ETH
- authorization
- 尚未检查
Vault · Contract0xB41d…91C0
- ETH balance
- 12.000 ETH
- credit[Alice]
- 1.000 ETH
- code
- deposit()
World stateshared execution state
- stateRoot
- 0x8b7a…44e1
- result
- 等待输入
- gas used
- 0
调用前 Alice 的下一笔交易应使用 nonce 7;Vault 记录 Alice 已有 1 ETH 额度。
成功时,转账与存储更新一起生效;执行回滚时,调用造成的状态变化一起撤销。 但已经执行的计算仍消耗 Gas,顶层交易 nonce 也会被消费。[7]
为什么一个按钮会触碰多条记录?
Alice 的 EOA 要防止重放和承担费用,所以 nonce 与余额会变化; Vault 收到 1 ETH,所以原生余额变化;Vault 还要记住这 1 ETH 属于 Alice 的内部额度, 所以存储根变化;这些变化最终共同反映在新的 stateRoot 中。
注意“Vault 内部记了 Alice 1 ETH”与“Vault 地址的原生 ETH 余额增加 1 ETH” 是两层状态。前者是应用会计规则,后者是协议原生余额。合约如果写错内部会计, 协议不会替它猜测真实意图,只会确定性执行代码。
一笔顶层交易还可以触发多层内部消息调用。合约 A 调合约 B,B 再调 C, 这些内部消息不是三笔新的顶层签名交易,却都发生在同一个原子执行上下文里。 这正是以太坊“可组合性”的技术基础,也是重入、权限和 Gas 风险的来源。
本实验隐藏了费用预扣、退款、Base Fee 销毁、收据与日志等中间细节。 第六章会沿一笔真实交易逐字段拆解,第七章再专门讲 Gas。
06 · EIP-7702
经典二分法,为什么不再够用?
Pectra 之后,EOA 可以在自己的账户上设置代码委托指示器。
经典教材用一句话区分账户:“EOA 没有代码,合约账户有代码。” 这曾经非常好用,但 EIP-7702 已经让它变成入门近似。 新的 Set Code 交易类型允许 EOA 签署授权,把一个特殊委托指示器写入自己的代码字段。 后续对该 EOA 的执行会加载被指向的代码。[3]
EOA 签署授权
授权元组包含 chain_id、目标实现地址和 authority nonce。chain_id 非零时绑定该链;为 0 时可跨链使用。
写入委托指示器
账户代码成为 23 字节的 0xef0100 || address 指针,不是复制整份实现代码。
解析目标代码
调用触及该 EOA 时,执行客户端跟随一次指针,取得目标地址的代码。
在 EOA 上下文执行
代码逻辑来自目标地址,但余额、地址与存储上下文属于这个 EOA。
委托实现地址
像借来一套经过审计的钱包逻辑:批量调用、赞助 Gas、会话密钥或恢复规则都可由代码提供。
原 EOA 地址
资产地址不必迁移;委托代码在 authority 的执行上下文中读写,因此存储布局与升级安全至关重要。
它没有把 EOA 简单“变成合约账户”
更准确的说法是:协议允许某类带有效委托指示器的 EOA 保持交易发起能力, 同时在被执行时表现出可编程逻辑。授权可以被后续授权更换或清除;签名密钥仍承担关键控制角色。 委托设置后会跨交易保留,直到以后被替换或清除,并非只在当前调用中临时生效。 因此它是对账户行为边界的扩展,不是删除 EOA,也不是普通合约部署。
外层 Set Code 交易的发送者还可以与被授权的 EOA 不同,因此赞助者能够代付这次上链费用。
另一个反直觉细节是:有效授权元组在调用执行前被处理;即使后面的调用发生
REVERT,已经写入的委托指示器以及对应的 authority nonce 增量也不会随执行结果回滚。
所以不能用“交易失败了”推断账户没有发生委托变化。[3]
| 形态 | 顶层入口 | 执行逻辑 | 状态所在地址 |
|---|---|---|---|
| 经典 EOA | 协议验证交易签名 | 默认无自定义账户代码 | EOA 地址 |
| 传统合约账户 | 被交易或内部消息调用 | 本地址部署的运行时代码 | 合约地址 |
| EIP-7702 委托 EOA | 签名交易;也可被调用 | 委托指示器指向的实现代码 | 原 EOA 地址 |
| 传统 ERC-4337 合约路径 | UserOperation 经 EntryPoint 执行 | 智能账户合约的验证与执行逻辑 | 通常为智能账户合约地址;与 7702 组合时为原 EOA 地址 |
EIP-7702 授权指向的代码对账户具有极强能力。规范明确提醒:应用不应诱导用户直接签署任意授权, 钱包应审计、筛选并通过标准化接口管理委托。把一次授权当成普通“登录签名”,可能交出整个账户执行权。[4]
07 · ERC-4337
智能账户:把授权规则本身变成程序
ERC-4337 不修改共识协议,而是在上层建立一条 UserOperation 路径。
经典 EOA 的原生授权规则很硬:给出满足协议的签名,或不给。 智能账户希望把“什么算授权”交给代码:两把钥匙共同批准、大额转账等待 24 小时、 丢失主设备后由守护人恢复、某个应用只获得每日小额额度,甚至由赞助者支付 Gas。
“智能账户”首先描述的是一组可编程授权与执行能力,不是协议状态中新增加的 第三套账户数据结构。今天它可以表现为 ERC-4337 智能账户合约,也可以由 EIP-7702 委托 EOA 接入相似的账户逻辑。
构造 UserOperation
它像交易请求,但不是协议原生交易;签名语义由智能账户实现定义。
Bundler 收集打包
Bundler 模拟多个 UserOperation,再把它们装进一笔普通以太坊交易。
EntryPoint 协调验证
单例合约调用各智能账户验证逻辑,并处理执行、费用与可选 Paymaster。
智能账户执行调用
验证通过后,账户合约按自身规则批量调用应用或转移资产。
ERC-4337 没让“合约账户直接进入基础交易池”。Bundler 最终提交的仍是一笔协议认识的交易, 调用 EntryPoint;UserOperation 是上层对象,验证逻辑发生在合约系统中。[5]
UserOperation 的 nonce 属于 EntryPoint 与智能账户这条上层验证路径,不是账户四字段中的协议 nonce。 常见 EntryPoint 把它组织成 192 位 key 加 64 位顺序号,以支持多条独立序列; Bundler 提交外层协议交易时,还会另外消费 Bundler 发送账户自己的协议 nonce。[5]
EIP-7702 与 ERC-4337,不是二选一
EIP-7702 从协议层扩展 EOA,让既有地址可以委托智能账户逻辑;
ERC-4337 提供成熟的 UserOperation、Bundler、EntryPoint 与 Paymaster 流程。
一个委托 EOA 可以使用兼容 ERC-4337 的实现,从而保留原地址和资产,同时接入智能账户基础设施。
当一个 Bundle 携带 7702 授权时,Bundler 的外层提交必须使用
0x04 Set Code 交易类型,而不是把 UserOperation 直接变成协议交易。
但“可编程”不自动等于“更安全”。恢复人可能串谋,模块可能有漏洞,Paymaster 可能审查, 升级权限可能被滥用。账户抽象只是把固定风险变成可设计的规则; 好设计需要最小权限、可审计代码、明确升级路径和用户可理解的签名界面。
四种控制路径的对照视图
协议固定验证 secp256k1 签名;简单、兼容广,但恢复、限额、批处理能力有限。
KEY → TX
代码定义行为,但传统入口仍依赖某个 EOA 交易或另一个合约调用。
CALL → CODE
EOA 签署委托,保留原地址;调用时使用委托实现代码和本地址状态。
KEY + DELEGATE
账户合约自定义 UserOperation 验证;与 7702 组合时,同一管线也可服务状态留在原地址的委托 EOA。
RULES → USEROP
08 · Precision & safety
七个最容易带进实战的误区
账户模型学错,通常不是考试失分,而是签错授权。
“地址就是账户,复制地址等于复制账户。”
地址只是公开索引。复制地址只能让别人知道去哪里查询或转账; 控制账户需要满足签名或代码授权规则。不要把公开地址与秘密私钥混为一谈。
“我的代币都存放在 EOA 的 balance 字段里。”
账户的 balance 字段是原生 ETH。ERC-20 余额通常位于代币合约的存储映射, NFT 所有权也位于对应合约状态。钱包把这些异构状态聚合成资产列表。
“合约账户没有私钥,所以合约资产没人能动。”
合约资产由代码控制。代码可能允许管理员 EOA、多签、DAO、时间锁或任何调用者在特定条件下转移。 要阅读权限规则,而不是只看地址类型。
“任何失败交易都像从未发生,什么也不扣。”
执行回滚会撤销调用造成的状态写入与价值转移,但已完成的计算仍需支付 Gas, 顶层交易 nonce 也会前进。签名前应区分模拟失败、上链回滚和进入区块前被拒绝。
“只要某地址有 code,它就一定是传统合约账户。”
Pectra 后,EOA 可能持有 EIP-7702 委托指示器。区块浏览器、钱包和应用不能只用 “代码是否为空”推断所有账户行为。
“EIP-7702 授权只是给某个 DApp 一个小权限。”
原始委托授权让指定实现代码在账户上下文执行,能力非常强。 细粒度权限应由经过审计的委托实现和标准模块提供;不要向陌生应用签署任意授权元组。
“ERC-4337 是以太坊把全部 EOA 换成合约账户的硬分叉。”
ERC-4337 明确采用不改共识协议的上层路径:UserOperation、独立传播、Bundler 和 EntryPoint 合约。 它与 EOA 和普通交易体系并行,并可与 EIP-7702 组合。
看到签名请求时,先问五个问题
- 01
我在授权哪一种对象?普通交易、消息签名、代币 allowance、Permit、UserOperation 还是 EIP-7702 授权?
- 02
谁会验证它?协议、某个代币合约、EntryPoint、钱包模块还是应用后端?
- 03
权限边界是什么?一次调用、固定额度、特定目标、某条链,还是无期限的广泛控制?
- 04
能否撤销或替换?撤销动作是否也需要原密钥、管理员、时间锁或新的链上交易?
- 05
失败时谁承担什么?Gas、资产、nonce、赞助额度与重放风险分别落在哪个账户?
“连接钱包”不必然转移资产,“签名”也不必然安全。真正要读的是签名对象和验证规则。 不理解的 EIP-7702 委托、无限代币授权或智能账户模块,不要因为界面写着“登录”就确认。
09 · Recap
把整课压缩成一条控制链
从公开地址开始,沿着授权、执行与状态更新走到新的 stateRoot。
- 01
地址是索引,不是钱包。钱包是帮助你管理授权和交互的工具。
- 02
账户是状态记录。核心字段是 nonce、原生 ETH 余额、storageRoot 与 codeHash。
- 03
账户模型维护当前状态。UTXO 模型则维护尚未花费的输出集合。
- 04
经典 EOA 由签名授权顶层交易。传统合约账户由代码响应调用。
- 05
一次调用可原子改变多个账户。应用内部会计与协议原生余额是两层状态。
- 06
EIP-7702 让 EOA 可委托代码。代码来自实现地址,执行上下文与状态留在原 EOA。
- 07
ERC-4337 在上层抽象账户。UserOperation 经 Bundler 与 EntryPoint 调用智能账户。
- 08
可编程不自动等于安全。权限、升级、恢复、赞助与模块都要进入威胁模型。
现在检查你的理解
1. “地址”和“钱包”的关系,哪项最准确?
2. 一个 EOA 的 USDC 余额通常存在哪里?
3. 经典 EOA 的交易 nonce 主要解决什么?
4. EIP-7702 委托最准确的描述是什么?
5. ERC-4337 如何进入以太坊区块?
6. 一笔已上链交易执行回滚后,哪项通常仍然发生?
10 · Sources
术语与一手资料
“EOA 无代码”已标为经典模型;现代边界以当前 EIP 与官方文档校准。
核心术语
地址 ADDRESS
20 字节公开值,用作执行层状态与消息目标的索引。地址本身不是秘密,也不等于钱包应用。
外部账户 EOA
经典模型中由私钥签名授权、可发起顶层交易的账户。EIP-7702 允许它设置代码委托指示器。
合约账户 CONTRACT ACCOUNT
由部署的 EVM 代码控制行为、拥有独立地址与持久状态的账户;传统模型中被调用后才执行。
nonce ACCOUNT NONCE
账户计数器。对经典 EOA 主要提供交易顺序与重放保护;对合约还关联创建计数。
存储根 STORAGE ROOT
对某账户持久键值存储的密码学承诺。具体 trie 结构会在第十一章展开。
委托指示器 DELEGATION INDICATOR
EIP-7702 写入 EOA 代码字段的特殊 23 字节值 0xef0100 || address,指向要执行的实现代码。
UserOperation ERC-4337
描述智能账户请求的上层对象,不是协议原生交易;由 Bundler 打包并经 EntryPoint 执行。
钱包 WALLET
帮助用户管理密钥或账户权限、构造签名、连接网络和展示资产的界面或软件。
官方一手资料
-
01
ethereum.org — Ethereum accounts 两类经典账户、四个账户字段、地址与钱包的官方基础说明。
-
02
Ethereum Execution Layer Specification 当前执行层状态转换与分叉规则的可执行规范仓库。
-
03
EIP-7702 — Set Code for EOAs Set Code 交易、授权元组、委托指示器、执行上下文与安全考虑的规范来源。
-
04
ethereum.org — Pectra EIP-7702 guidelines 钱包、应用与硬件签名设备集成委托时的安全与互操作建议。
-
05
ERC-4337 — Account Abstraction Using Alt Mempool UserOperation、Bundler、EntryPoint、Paymaster 与“无需共识协议变更”的正式规范。
-
06
ethereum.org — Account abstraction EIP-7702 与 ERC-4337 两条账户抽象路径、恢复与 Gas 赞助的官方概览。
-
07
ethereum.org — Gas and fees 执行失败、状态回滚与已消耗 Gas 仍被计费的官方说明。
-
08
ethereum.org — Transactions 签名交易字段、nonce、value、Gas 与交易生命周期。
-
09
EIP-161 — State trie clearing 不存在、空账户、非空账户与状态清理边界的协议历史来源。
账户模型已经立住。进入第五章后,我们会把“有效签名”拆成私钥、公钥、地址、 椭圆曲线与 Keccak-256,再回头验证:为什么网络能相信授权,而永远不需要看见你的私钥。