该EIP(以太坊改进提案)旨在通过结构化的净Gas计量方式,实现EIP-1283和EIP-1706的结合。它重新定义了SSTORE操作码的Gas成本计算,从而降低了某些存储操作的Gas费用,支持了新的合约存储用途,并解决了EIP-1283可能引入的重入攻击风险。
这是一个实现了净 Gas 计量(net gas metering)的 EIP。它是 EIP-1283 和 EIP-1706 的结合版本,具有结构化定义,以便与其他 Gas 变更(例如 EIP-1884)互操作。
本 EIP 提供了 SSTORE 操作码的净 Gas 计量变更的结构化定义,为合约存储启用了新的用法,并减少了在与大多数实现的工作方式不符时出现的过高 Gas 成本。
本 EIP 提出了一种在 SSTORE 上进行 Gas 计量的方法,利用了大多数实现普遍可用的信息,并要求对实现结构进行尽可能小的更改。
受益于本 EIP 的 Gas 削减方案的用法包括:
EIP-1283 的原始定义造成了一种新的重入攻击现有合约的危险,因为 Solidity 默认会为简单的传输调用提供 2300 Gas 的“津贴”。如果 SSTORE 不允许在剩余 Gas 较低的状态下执行,这种危险可以很容易地缓解,而不会破坏向后兼容性和 EIP-1283 的初衷。
本 EIP 还通过参数替换了 EIP-1283 原始的 Gas 值定义,使其更加结构化,并更容易在未来定义更改。
定义变量 $SLOAD_GAS$、$SSTORE_SET_GAS$、$SSTORE_RESET_GAS$ 和 $SSTORE_CLEARS_SCHEDULE$。这些变量的新旧值如下:
$SLOAD_GAS$:从 200 更改为 800。$SSTORE_SET_GAS$:20000,未更改。$SSTORE_RESET_GAS$:5000,未更改。$SSTORE_CLEARS_SCHEDULE$:15000,未更改。使用这些变量更改 EIP-1283 的定义。结合 EIP-1283 和 EIP-1706 的新规范将如下所示。术语 原始值、当前值 和 新值 在 EIP-1283 中定义。
用以下逻辑替换 SSTORE 操作码的 Gas 成本计算(包括退款):
$SLOAD_GAS$。$SSTORE_SET_GAS$。$SSTORE_RESET_GAS$。如果 新值 为 0,则将 $SSTORE_CLEARS_SCHEDULE$ 加到退款计数器中。$SLOAD_GAS$。应用以下两条条款。$SSTORE_CLEARS_SCHEDULE$。$SSTORE_CLEARS_SCHEDULE$ 加到退款计数器中。$SSTORE_SET_GAS - SLOAD_GAS$ 加到退款计数器中。$SSTORE_RESET_GAS - SLOAD_GAS$ 加到退款计数器中。实现还应注意,根据上述定义,如果实现使用 call-frame 退款计数器,则计数器可能变为负数。如果实现使用 transaction-wise 退款计数器,则计数器始终保持正数。
本 EIP 主要实现了瞬时存储(transient storage)试图做的事情(EIP-1087 和 EIP-1153),但没有引入“脏映射”(dirty maps)概念或额外存储结构的复杂性。
关于 SSTORE 的 Gas 成本和退款,请参阅附录中关于本 EIP 满足的属性证明。
检查 EIP-1087 动机中提供的示例(其中 $SLOAD_GAS$ 为 200):
$20000 + 200 - 19800 = 400$ Gas。$20000 + 5 * 200 = 21000$ Gas。$5000 * 3 + 200 - 4800 = 10400$ Gas。为了保持现有合约隐式的重入保护,如果剩余 Gas 低于 Solidity 中“transfer”/“send”给予的 Gas 津贴,则不应允许事务修改状态。以下是其他建议的补救措施和反对实施它们的理由:
SSTORE 成本
SSTORE 写入脏槽的成本提高到 >=2300 Gas
SSTORE 更改应用于使用新版本部署的合约。本 EIP 需要硬分叉才能实现。预计不会增加 Gas 成本,许多合约将看到 Gas 减少。
执行 SSTORE 从未能在低于 5000 Gas 的情况下完成,因此它不会对以太坊主网引入不兼容性。Gas 估算应考虑到此要求。
| 代码 | 已用 Gas | 退款 | 原始 | 第一次 | 第二次 | 第三次 |
|---|---|---|---|---|---|---|
0x60006000556000600055 |
1612 | 0 | 0 | 0 | 0 | |
0x60006000556001600055 |
20812 | 0 | 0 | 0 | 1 | |
0x60016000556000600055 |
20812 | 19200 | 0 | 1 | 0 | |
0x60016000556002600055 |
20812 | 0 | 0 | 1 | 2 | |
0x60016000556001600055 |
20812 | 0 | 0 | 1 | 1 | |
0x60006000556000600055 |
5812 | 15000 | 1 | 0 | 0 | |
0x60006000556001600055 |
5812 | 4200 | 1 | 0 | 1 | |
0x60006000556002600055 |
5812 | 0 | 1 | 0 | 2 | |
0x60026000556000600055 |
5812 | 15000 | 1 | 2 | 0 | |
0x60026000556003600055 |
5812 | 0 | 1 | 2 | 3 | |
0x60026000556001600055 |
5812 | 4200 | 1 | 2 | 1 | |
0x60026000556002600055 |
5812 | 0 | 1 | 2 | 2 | |
0x60016000556000600055 |
5812 | 15000 | 1 | 1 | 0 | |
0x60016000556002600055 |
5812 | 0 | 1 | 1 | 2 | |
0x60016000556001600055 |
1612 | 0 | 1 | 1 | 1 | |
0x600160005560006000556001600055 |
40818 | 19200 | 0 | 1 | 0 | 1 |
0x600060005560016000556000600055 |
10818 | 19200 | 1 | 0 | 1 | 0 |
待补充。
由于 存储槽的原始值 被定义为 当前事务 发生回滚时的值,因此很容易看出调用帧不会干扰 SSTORE 的 Gas 计算。所以,尽管下面的证明没有讨论调用帧,但它适用于所有带有调用帧的情况。我们将分别讨论 原始值 为零和不为零的情况,并使用 归纳法 来证明 SSTORE Gas 成本的一些属性。
最终值 是事务结束时特定存储槽的值。实际使用的 Gas 是 已用 Gas 减去 退款 的绝对值。我们用 $N$ 来表示对存储槽进行 SSTORE 操作的总次数。对于下面讨论的状态,请参阅“解释”部分中的 状态转换。
在下面的证明中,我们假设所有参数都没有改变,这意味着 $SLOAD_GAS$ 是 200。然而,请注意,无论 $SLOAD_GAS$ 如何变化,该证明仍然适用。
当 原始值 为 0 时,我们想证明:
$200 * N$ Gas,因为不需要磁盘写入。$20000 + 200 * (N-1)$ Gas,因为这需要将此槽写入磁盘。我们总是从状态 A 开始。第一次 SSTORE 可以:
$200 * N == 200 * 1$。$20000 + 200 * (N-1) == 20000 + 200 * 0$。$200 * (N-1)$。当前的 Gas 成本是 $200 + 200 * (N-1)$。它满足 情况一。$200 * (N-1)$。当前的 Gas 成本是 $20000 + 200 * (N-1)$。它满足 情况二。$20000 + 200 * (N-2)$。当前的 Gas 成本是 $200 + 20000 + 200 * (N-2)$。它满足 情况二。$20000 + 200 * (N-2)$。当前的 Gas 成本是 $200 - 19800 + 20000 + 200 * (N-2)$。它满足 情况一。当 原始值 不为 0 时,我们想证明:
$200 * N$ Gas,因为不需要磁盘写入。$5000 - 15000 + 200 * (N-1)$ Gas。请注意 $15000$ 是实际定义中的退款。$5000 + 200 * (N-1)$ Gas。我们总是从状态 X 开始。第一次 SSTORE 可以:
$200 * N == 200 * 1$。$5000 + 200 * (N-1) == 5000 + 200 * 0$。$5000 - 15000$,其中 15000 是退款。我们满足 情况二,因为 $5000 - 15000 + 200 * (N-1) == 5000 - 15000 + 200 * 0$。$200 * (N-1)$。当前的 Gas 成本是 $200 + 200 * (N-1)$。它满足 情况一。$200 * (N-1)$。当前的 Gas 成本是 $5000 + 200 * (N-1)$。它满足 情况三。$200 * (N-1)$。当前的绝对 Gas 成本是 $5000 - 15000 + 200 * (N-1)$。它满足 情况二。$5000 + 200 * (N-2)$。当前的绝对 Gas 成本是 $200 - 4800 + 5000 + 200 * (N-2)$。它满足 情况一。$5000 + 200 * (N-2)$。当前的 Gas 成本是 $200 + 5000 + 200 * (N-2)$。它满足 情况三。$5000 + 200 * (N-2)$。当前的绝对 Gas 成本是 $200 - 15000 + 5000 + 200 * (N-2)$。它满足 情况二。$5000 - 15000 + 200 * (N-2)$。当前的绝对 Gas 成本是 $200 + 10200 + 5000 - 15000 + 200 * (N-2)$。它满足 情况一。$5000 - 15000 + 200 * (N-2)$。当前的绝对 Gas 成本是 $200 + 15000 + 5000 - 15000 + 200 * (N-2)$。它满足 情况三。$5000 - 15000 + 200 * (N-2)$。当前的绝对 Gas 成本是 $200 + 5000 - 15000 + 200 * (N-2)$。它满足 情况二。通过 CC0 放弃版权及相关权利。
- 原文链接: github.com/nerolation/EI...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!