原文标题:《干货 | 搞懂 “柏林” 之后的合约 Gas 开销》 撰文:Franco Victorio 翻译 & 校对:阿剑 「柏林」硬分叉已于 4 月 15 日激活,该硬分叉所包含 EIP 中的两个(EIP-2929 和 EIP-2930)都会影响事务的 Gas 开销。本文会解释 “柏林” 激活之前,一些操作码的 Gas 消耗量是如何计算的,而 EIP-2929 对此有何影响,以及,2930 引入的访问清单(Access List)功能应如何使用。 摘要这篇文章很长,你要是只想知道结论,看完这部分就可以把网页关掉了: 柏林硬分叉改变了某些操作码的 Gas 开销。如果你在自己的应用中硬编码了一些操作可使用的 Gas 数量,这些操作可能会卡死。如果真的出现了这种情况,而你的智能合约又是没法升级的,用户就需要使用 “访问清单” 功能来使用你的应用。 访问清单功能可略微减少 Gas 开销,但有些时候也可能会提高总的 Gas 消耗量。 geth 客户端引入了一种新的 RPC 方法,叫做 eth_createAccessList 来简化访问清单的生成。
「柏林」升级以前的 Gas 开销EVM 所执行的每一个操作码都有一个对应的 Gas 消耗量。大部分操作码的消耗量都是固定的:PUSH1 总是消耗 3 gas,而 MUL 消耗 5 gas,等等。有一些操作码的消耗量是可变的:举个例子,SHA3 操作码的开销由输入值的长度决定。 我们先了解 SLOAD 和 SSTORE 操作码,因为这两个操作码受 “柏林” 影响最大。后面我们会再谈谈那些以地址为目标的操作,比如所有的 EXT* 类操作码和 CALL* 类操作码,因为它们的 Gas 开销也被改变了。 「柏林」 以前的 SLOAD 在 EIP-2929 实施前,SLOAD 开销的计算方式很简单:总是消耗 800 gas。所以,也没啥可展开的。 「柏林」以前的 SSTORE **要讲到 Gas 消耗量的计算,SSTORE 操作码可能是最复杂的了。因为消耗多少取决于该存储项槽当前的值、要写入的新值、该存储项是否已经修改过。我们只会分析少数几种场景,了解个大概。如果你想了解更多,请阅读本文末尾所附的 EIP 链接。 如果存储项的值从 0 改为 1 (或者任意非零的值),Gas 消耗量是 20000 如果存储项的值从 1 改为 2 (或者任意非零的值),Gas 消耗量是 5000 如果存储项的值从 1 (或任意非零的值) 改为 0,消耗量也是 5000,但你会在事务执行结束后获得 gas 补贴。我们这里也不讨论 gas 返还机制,因为它不会受到柏林的影响 在一笔事务中,如果存储项已不是第一次修改,则后续每一次
(责任编辑:admin)
|