SignalPlus波动率专栏(20240
Ethereum Dencun 硬分叉内容介绍
Dencun 是由 Deneb 及 Cancun 两个名称所组成,分别代表 Ethereum 共识层与执行层的硬分叉。Dencun 硬分叉已经在 Goerli、Sepolia 及 Holesky 测试网完成,主网将在 Epoch 269568(约为 2024 年 3 月 13 日)进行。
阅读提示
在阅读本文前,需要了解的先备知识包括:
硬分叉
Ethereum 分为共识层(Consensus Layer)及执行层(Execution Layer)
Dencun 升级包含 9 个 EIP,分别是:
EIP-1153: Transient storage opcodes(执行层改动)
EIP-4788: Beacon block root in the EVM(执行层与共识层改动)
EIP-4844: Shard Blob Transactions(执行层与共识层改动)
EIP-5656: MCOPY - Memory copying instruction(执行层改动)
EIP-6780: SELFDESTRUCT only in same transaction(执行层改动)
EIP-7044: Perpetually Valid Signed Voluntary Exits(共识层改动)
EIP-7045: Increase Max Attestation Inclusion Slot(共识层改动)
EIP-7514: Add Max Epoch Churn Limit(共识层改动)
EIP-7516: BLOBBASEFEE opcode(执行层改动)
这篇文章将介绍这几个 EIP(不包含 EIP-4844)的改动与影响,EIP-4844 的介绍可以参考:
Rollup 的大补帖:Proto-Danksharding(一)
https://medium.com/taipei-ethereum-meetup/rollup-and-the-boost-from-proto-danksharding-85d2fe0566b6
Rollup 的大补帖:Proto-Danksharding(二)
https://medium.com/taipei-ethereum-meetup/rollup-proto-danksharding-implementation-detail-913a3c61fde8
接下来介绍与顺序会大致区分为「执行层改动相关的 EIP」「共识层改动相关的 EIP」及「与 EIP-4844 相关的 EIP」。
EIP-1153
执行层改动
EIP-1153: Transient storage opcodes
https://eips.ethereum.org/EIPS/eip-1153
EIP-1153: fan page
https://www.eip1153.com/
EIP-1153: Transient storage opcodes
https://ethereum-magicians.org/t/eip-1153-transient-storage-opcodes/553
EIP-1153 新增两个 Opcode:TSTORE 与 TLOAD,用来写入与读取「暂时的」Storage 数据。它们将可为许多合约开发者省下不少 Gas 成本。
背景
Storage 指的就是智能合约透过 SSTORE 这个 Opcode 将数据写入到该合约的储存空间中,数据写入后是永久存在的,直到合约主动移除该笔数据为止。而「暂时的」这个特质则是相对于「永久存在」,TSTORE 写入的数据有效期限只有到该笔交易结束为止,该笔交易执行完后 TSTORE 写入的值就会被丢弃。
运作细节
TSTORE 相比于 SSTORE 便宜非常多,而其有效期限又能横跨不同合约之间的呼叫(直到交易结束),不像 Memory 虽然便宜但 Memory 里的值只专属于每个合约自己,A 合约无法去读取 B 合约的 Memory。这对许多用途非常有帮助:
Reentrancy Lock。目前 Reentrancy Lock 只能用 SSTORE 来仿真,虽然 SSTORE 的规则经过 EIP-2200 后有对 Reentrancy Lock 这样的用途减轻不少 Gas 成本,但 TSTORE 可以将成本再大幅降低:从 5000 降为 100。
使用于单笔交易内的 ERC-20 approve。如果 A 合约和 B 合约进行交互,而 A 合约需要从 B 合约身上转走 ERC-20,此时 B 合约会先对 A 合约做 approve ERC-20 的动作然后才呼叫 A 合约。因为 ERC-20 的 approve 都是透过 SSTORE 所以成本不低,改成使用 TSTORE 后将能大幅降低成本。
透过 CREATE2 部署合约时的部署参数。因为 Constructor 参数会影响 CREATE2 部署的合约地址,所以如果不想被 Constructor 参数影响的话,合约 Constructor 就会设计为去部署者合约的 Storage 读取参数,例如 Uniswap V3 的 Pool。透过 TSTORE,这样的模式就能省下许多成本。
注意事项
合约开发者在用 TSTORE 改写自己的 Reentrancy Lock 时,记得还是要在该清空 Lock 时清空,不要想说交易结束后它会自己清空所以可省下清空的 Gas 消耗,否则交易过程中如果有需要再次进入合约的话就有可能因为 Lock 没解锁(没清空)而无法进入。
EIP-1153 已经在 Solidity 0.8.24 版中推出,开发者可以提前试用。这里有开发者实作的 Mutex 范例。仰赖 TSTORE 的 Uniswap V4 也将在 Dencun 升级完成后上线。
这个 EIP 新增新的 Opcode,所以开发者如果要部署合约到多链,要注意是否所有的链都有支持最新的 Opcode,否则将导致无法使用。
EIP-4788
执行层改动
EIP-4788: Beacon block root in the EVM
https://eips.ethereum.org/EIPS/eip-4788
EIP-4788: Beacon root in EVM
https://ethereum-magicians.org/t/eip-4788-beacon-root-in-evm/8281
EIP-4788 新增一个 BEACON_ROOTS_ADDRESS 合约来让人读取共识层区块的数据,也就是执行层将能读取到共识层的数据。透过这个合约,Staking 及 Restaking 协议可以在不信任任何第三方的前提下读取并使用共识层的数据,例如读取某个验证者的状态。
运作细节
使用者或合约可以透过呼叫合约的方式去查询某个时间点的共识层区块根(Beacon Block Root)。区块根如同区块内容的哈希值(Beacon Block Hash),是区块内容透过 SSZ 编码的方式所得到的 Merkle Tree 的树根(Merkle Tree Root)。呼叫者将时间戳(timestamp)编码成 uint256 的值并当作呼叫内容,合约会以时间戳去 Storage 寻找相对应的共识层区块根并回传。
开发者如果要使用共识层的信息,则他的合约会透过 BEACON_ROOTS_ADDRESS 合约查询他要读取的共识层区块的区块根,然后再搭配该共识层区块的信息(例如某个验证者的余额)及 Merkle Proof 来验证该信息是否属于该区块根。(SSZ 因为将内容都做成 Merkle Tree,所以内容里任何信息都可以产生相对应的 Merkle Proof 来验证该信息存在于该内容里。)
△ 使用者提供 Merkle Proof 与共识层区块的时间戳
△ Merkle Proof 搭配询问区块根来验证某个时间点的验证者余额
不过 BEACON_ROOTS_ADDRESS 合约里存的共识层区块根其实是「母」区块(也就是前一个区块)的区块根,而不是和执行层同一个区块的区块根。
△ Block 11001 的时间戳(1234567)对应的是 Block 11000 的区块根。同样地,Block 11000 的时间戳(1234555)对应的是 Block 10999 的区块根。
注意事项
BEACON_ROOTS_ADDRESS 合约里储存最多 8191 个共识层区块根,8191 个以前的区块根会被覆写。例如假设现在是 Block 18191,则当下能存取到区块根范围会是 Block 10000 到 Block 18190 的区块根。
EIP-5656
执行层改动
EIP-5656: MCOPY - Memory copying instruction
https://eips.ethereum.org/EIPS/eip-5656
EIP-5656 新增一个 MCOPY Opcode,专门用来复制合约执行过程中 Memory 里储存的值。合约将可受益于这个 Opcode 节省的 Gas 成本。
合约开发者若要使用 MCOPY Opcode,需要将编译程序版本指定为 0.8.24(或以上)以及 EVM 版本指定为 Cancun:
△ 要使用 MCOPY 需要设定编译程序版本及 EVM 版本
注:0.8.24 版的编译程序只开放透过 Assembly 的方式来使用 MCOPY(mcopy(),link),未来的版本才会自动由编译程序来在需要复制 Memory 的地方套用 MCOPY。
注意事项
这个 EIP 新增新的 Opcode,所以开发者如果要部署合约到多链,要注意是否所有的链都有支持最新的 Opcode,否则将导致无法使用。
EIP-6780
执行层改动
EIP-6780: SELFDESTRUCT only in same transaction
https://eips.ethereum.org/EIPS/eip-6780
EIP-6780: Deactivate SELFDESTRUCT, except where it occurs in the same transaction in which a contract was created
https://ethereum-magicians.org/t/eip-6780-deactivate-selfdestruct-except-where-it-occurs-in-the-same-transaction-in-which-a-contract-was-created/13539
EIP-6780 修改了 SELFDESTRUCT Opcode 的行为,为 Verkle Tree 及淘汰 SELFDESTRUCT Opcode 做准备。合约有使用到 SELFDESTRUCT Opcode 的开发者需要特别注意。
背景
SELFDESTRUCT Opcode 目前的行为是:(1) 删除该合约的代码及 Storage,并 (2) 将身上的 ETH 全都转给指定的地址。
一开始设计 SELFDESTRUCT Opcode 搭配 Refund 机制来激励开发者移除用不到的合约及储存空间,协助维持 Ethereum 状态在一个适合的大小。但真的这么做的人不多,反倒是出现像 Parity Multisig 这样因为 SELFDESTRUCT 导致数十万 ETH 冻结的意外,因此 Ethereum 社群希望能逐渐淘汰掉 SELFDESTRUCT Opcode。过去有不少修改或移除 SELFDESTRUCT Opcode 的提案,EIP-6780 是其中一个并且最终被收入进 Dencun 硬分叉中。
注:在 2023 年初的 Shanghai 硬分叉中,EIP-6049 已经正式宣告 SELFDESTRUCT 将会被淘汰。
Verkle Tree 是 Ethereum 社群目前正在积极研究与开发的状态储存结构,将用来取代目前的 Merkle Patricia Tree。Verkle Tree 将会让 Ethereum 状态的证明大小变得更小,因此也是 Stateless Client 设计中的关键。有了 Stateless Client,节点的硬件将会降低,让更多人可以以更轻量、便宜的硬件来运行节点,提升网络的去中心化程度。
运作细节
在 EIP-6780 后,SELFDESTRUCT Opcode 将会移除 (1) 的行为,只保留 (2)「将身上的 ETH 全都转给指定的地址」的功能。合约的代码及 Storage 都将维持不动,除非该合约是在同一笔交易创建然后又进行 SELFDESTRUCT。
所以当 SELFDESTRUCT 被触发时:
如果合约不是在同一笔交易被创建,则合约的代码及 Storage 都维持不动,但把身上的 ETH 全都转给指定的地址。
如果合约是在同一笔交易被创建,则行为和原本(EIP-6780 以前)一样:合约的代码及 Storage 都会被移除,ETH 也会被转给指定地址。