当前位置: 首页 > news >正文

1.3 StorageTransient的gas计算

1.3 Storage&Transient的gas计算

1.3.1 简介:两种存储

在 EVM 中,智能合约有两种主要的数据存储区域:
持久化存储 (Storage)
这是我们通常所说的“状态”。它是一个键值对映射(key-value store),将 32 字节的键映射到 32 字节的值。

  • 持久性: 数据永久保存在以太坊区块链上,除非被合约逻辑修改。
  • 高成本: 读写操作非常昂贵,因为它们会改变区块链的状态,需要所有节点达成共识。
  • 指令: SLOADSSTORE

瞬时存储 (Transient Storage)
这是由 EIP-1153 引入的新概念。它也是一个键值对映射,但其生命周期仅限于单次交易。

  • 瞬时性: 数据在交易开始时为空,在交易结束时被丢弃。它不会永久改变区块链状态。
  • 低成本: 读写操作比持久化存储便宜得多,因为它不涉及永久的状态变更。
  • 用途: 主要用于在同一次交易内的不同合约调用之间传递状态,而无需昂贵地使用持久化存储。例如,在复杂的 DeFi 协议中用于“重入锁”或传递手续费信息。
  • 指令: TLOADTSTORE

1.3.2 SLOAD: 从持久化存储中读取

SLOAD 指令用于从合约的持久化存储中加载一个值到堆栈上。

    # STACK 从堆栈 (Stack) 弹出一个 32 字节的 key。key = pop(evm.stack).to_be_bytes32()# GAS 计算 Gas 费用if (evm.message.current_target, key) in evm.accessed_storage_keys:charge_gas(evm, GAS_WARM_ACCESS)else:evm.accessed_storage_keys.add((evm.message.current_target, key))charge_gas(evm, GAS_COLD_SLOAD)# OPERATION 从当前合约的存储中,读取 key 对应的 valuevalue = get_storage(evm.message.block_env.state, evm.message.current_target, key)

Gas 成本:冷热访问 (Cold vs. Warm Access)
为了防止拒绝服务攻击 (DoS),EVM 对首次访问某个存储槽(slot)的操作收取更高的费用。
冷访问 (Cold Access): 在一笔交易中,第一次访问某个账户的某个存储 key

  • Gas 成本: GAS_COLD_SLOAD (2100 Gas)
  • 代码中,通过检查 evm.accessed_storage_keys 集合来判断。如果 (address, key) 不在该集合中,就是冷访问。访问后,该键会被添加到集合中。

热访问 (Warm Access): 在同一笔交易中,对一个已经访问过的存储 key 进行再次访问。

  • Gas 成本: GAS_WARM_ACCESS (100 Gas)
  • 因为节点已经加载过这个数据,所以后续访问的成本要低得多。

1.3.3 SSTORE: 写入持久化存储

SSTORE 是最复杂的操作之一,因为它直接修改区块链状态,并且有复杂的 Gas 计费和退款机制。

if (evm.message.current_target, key) not in evm.accessed_storage_keys:evm.accessed_storage_keys.add((evm.message.current_target, key))gas_cost += GAS_COLD_SLOADif original_value == current_value and current_value != new_value:if original_value == 0:gas_cost += GAS_STORAGE_SETelse:gas_cost += GAS_STORAGE_UPDATE - GAS_COLD_SLOAD
else:gas_cost += GAS_WARM_ACCESS
# Refund Counter Calculation
if current_value != new_value:if original_value != 0 and current_value != 0 and new_value == 0:# Storage is cleared for the first time in the transactionevm.refund_counter += int(GAS_STORAGE_CLEAR_REFUND)if original_value != 0 and current_value == 0:# Gas refund issued earlier to be reversedevm.refund_counter -= int(GAS_STORAGE_CLEAR_REFUND)if original_value == new_value:# Storage slot being restored to its original valueif original_value == 0:# Slot was originally empty and was SET earlierevm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS)else:# Slot was originally non-empty and was UPDATED earlierevm.refund_counter += int(GAS_STORAGE_UPDATE - GAS_COLD_SLOAD - GAS_WARM_ACCESS)

Gas 成本:复杂的计费与退款机制
SSTORE 的 Gas 成本取决于多种因素:
访问成本:

  • 冷访问: 2100 Gas (GAS_COLD_SLOAD)
  • 热访问: 100 Gas (GAS_WARM_ACCESS)

写入成本:

  • 创建 (Set): 当一个值为 0 的存储槽被设置为非 0 值时。

    • 成本: 20,000 Gas (GAS_STORAGE_SET)
  • 更新 (Update): 当一个非 0值的存储槽被设置为另一个非 0 值时。

    • 成本: 2,900 Gas (GAS_STORAGE_UPDATE - GAS_COLD_SLOAD)

    也就是说,SSTORE 的写入成本已经包含了一次热访问的成本,如果你已经为冷访问付了 2100 gas,就不应该再全额收取 5000 gas,否则会重复计费。
    Gas 退款 (Refund):

  • 为了鼓励良好的状态管理(清理不再使用的存储),EVM 会提供 Gas 退款。

  • 清理 (Clear): 当一个非 0 值的存储槽被设置为 0 时,会获得 4,800 Gas 的退款 (GAS_STORAGE_CLEAR_REFUND)。

  • 撤销退款(非0 → 0 → 非0),如果 slot 原来是非0,现在是0(说明之前已经清理过),但你又把它写回非0,然后又写回0。效果:撤销之前的退款,防止你通过反复写0骗取多次退款。

  • 退款在交易结束时统一结算,并且最多只能退还当次交易所用 Gas 的一部分。如果你把 slot 的值改回了交易开始时的原值(即“恢复原状”)。效果:EVM 会返还你之前写入时多收的 gas,因为最终状态没变,相当于没做无用功。
    你在同一笔交易内,对同一个 slot 进行了多次 SSTORE 操作。最终,这个 slot 的值又被“还原”为交易开始时的 original_value。EVM 规范规定:如果 slot 的最终值和 original_value 一样,应该退还之前多收的写入 gas(因为最终状态没变,相当于没做无用功)。
    退款时只退“写入部分”,不退“访问部分”

    • 如果原来是0,现在又变回0,返还 GAS_STORAGE_SET - GAS_WARM_ACCESS。
    • 如果原来是非0,现在又变回原来的非0,返还 GAS_STORAGE_UPDATE - GAS_COLD_SLOAD - GAS_WARM_ACCESS。

1.3.4 TLOAD: 从瞬时存储中读取

TLOAD 用于从瞬时存储中加载一个值到堆栈。

    # STACK 从堆栈弹出一个 32 字节的 key。key = pop(evm.stack).to_be_bytes32()# GAS 收取固定的 Gas 费用。charge_gas(evm, GAS_WARM_ACCESS)# OPERATION  从当前交易的瞬时存储中读取 key 对应的 valuevalue = get_transient_storage(evm.message.tx_env.transient_storage, evm.message.current_target, key)push(evm.stack, value)

Gas 成本
TLOAD 的成本非常简单,它不区分冷热访问。

  • Gas 成本: GAS_WARM_ACCESS (100 Gas)

1.3.5 TSTORE: 写入瞬时存储

TSTORE 用于向瞬时存储写入一个值。

    # STACK  从堆栈弹出 key 和 new_value。key = pop(evm.stack).to_be_bytes32()new_value = pop(evm.stack)# GAS 收取固定的 Gas 费用。charge_gas(evm, GAS_WARM_ACCESS)if evm.message.is_static:raise WriteInStaticContextset_transient_storage(evm.message.tx_env.transient_storage,evm.message.current_target,key,new_value,)

Gas 成本
TLOAD 类似,TSTORE 的成本也很简单,没有退款机制。

  • Gas 成本: GAS_WARM_ACCESS (100 Gas)

1.3.6 总结

指令存储类型主要功能Gas 成本关键特性
SLOAD持久化读取数据2100 (冷) / 100 (热)区分冷热访问
SSTORE持久化写入数据复杂,依赖值的变化有复杂的 Gas 计费和退款机制
TLOAD瞬时读取数据100 (固定)成本低,数据仅在交易内有效
TSTORE瞬时写入数据100 (固定)成本低,无退款,数据仅在交易内有效
http://www.dtcms.com/a/536161.html

相关文章:

  • 物联网技术与基础第六节上课笔记
  • SAP SD系统开票查询报表分享
  • it网站设计培训制作网站的工具
  • 南京网站建设工作室电商卖什么产品有前景
  • iOS 开发推送功能全流程详解 从 APNs 配置到上架发布的完整实践(含跨平台上传方案)
  • 李宏毅机器学习笔记33
  • 深入理解Bitbucket Pipelines:强大的CICD开源解决方案
  • Android 14 系统启动流程深度解析:rc文件的语法、解析及常见语法详解
  • 商城网站的seo优化改怎么做软件公司 网站建设费分录
  • 免费做淘宝客网站有哪些石家庄网站优化推广
  • 【瑆箫】正式入驻爱发电平台
  • 第三十三篇:贪心算法(二):区间调度与跳跃游戏
  • 美颜SDK跨平台适配实战解析:让AI美颜功能在iOS与Android都丝滑运行
  • 条款24:区分通用引用和右值引用
  • zookeeper + kafka
  • 旅游网站建设与规划网站可以做被告嘛
  • 医护上门系统开发的关键技术解析与实践指南
  • 大模型-模型压缩:量化、剪枝、蒸馏、二值化 (3
  • Win10结束支持后,Linux发行版ZorinOS下载量两天破10w?怎么安装?
  • php和mysql做租车网站平台广告投放
  • Spring Boot3零基础教程,KafkaTemplate 发送消息,笔记77
  • 强化学习2.3 MDP价值迭代和策略迭代收敛证明
  • 网站建设公司相关资质重养网站建设
  • Android 中 RecyclerView 控件实现局部刷新而非整行刷新
  • STM32学习路线!软硬件兼修:裸机+RTOS+LVGL+硬件设计+项目实战 (STM32多核心开发板)
  • iOS 26 文件导出与数据分析,多工具组合下的开发者实践指南
  • Gradle 与 CI/CD 集成:Jenkins/GitHub Actions 自动化构建配置
  • STM32——IWDG
  • 一般的网站开发语言用什么免费网页制作
  • 浅述视频汇聚平台EasyCVR视频编解码与转码技术如何成就视频体验