市值: $2.5665T -2.09%
成交额(24h): $64.1207B 43.32%
恐惧与贪婪指数:

33 - 恐惧

  • 市值: $2.5665T -2.09%
  • 成交额(24h): $64.1207B 43.32%
  • 恐惧与贪婪指数:
  • 市值: $2.5665T -2.09%
加密货币
话题
百科
资讯
加密话题
视频
热门加密百科

选择语种

选择语种

选择货币

加密货币
话题
百科
资讯
加密话题
视频

阵列存储在 Solidity 中如何工作以及其成本是多少?

Dynamic arrays in Solidity store length in a slot, with elements placed at `keccak256(slot) + index`, ensuring deterministic, collision-free storage.

2025/11/23 11:59

了解 Solidity 中的数组存储

1. Solidity 中的数组存储在合约存储中,该存储在函数调用和交易之间是持久的。当声明动态数组时,例如uint[] public value ,分配给数组的槽仅保存数组的长度。实际数据元素存储在阵列槽号的 keccak256 散列中,从而实现安全且确定的位置映射。

2. 数组中的每个元素都放置在由公式keccak256(slot) + index导出的存储槽中。这种机制保证了即使合约中存在多个数组,它们的数据也不会发生冲突。由于以太坊存储是 256 位对齐的,因此每个槽可以容纳一个完整的 uint256 或同等大小的值。较大的类型可能跨越多个插槽。

3. 对于固定大小的数组,编译器从声明的变量位置开始保留连续的存储槽。像uint[3] ids这样的固定数组恰好使用三个相邻的槽。由于大小在编译时已知,因此不会存储长度等元数据,这使得访问更直接,并且在燃料方面稍微便宜一些。

4. 嵌套数组显着增加了复杂性。二维动态数组使用相同的哈希方法计算基位置,然后根据内部数组索引应用偏移量。由于读取或写入期间的多级散列和增加的 SLOAD 操作,访问模式变得更加昂贵。

5. 如果可能,将值打包到结构中或使用较小的整数类型(例如,uint128 而不是 uint256),以允许多个变量适合单个存储槽。这减少了使用的时隙总数,并降低了涉及这些变量的部署和状态修改的 Gas 成本。

与阵列操作相关的 Gas 成本

1. 通过push()追加到动态数组会产生一定的成本,具体取决于添加的元素是零还是非零。如果存储的值非零,则在设置先前的空槽时,会导致 SSTORE 操作的 Gas 成本为 20,000。根据 EIP-1283 规则,假设槽已包含数据,后续非零值的覆盖将花费 5,000 个 Gas。

2. 从数组中读取元素会触发 SLOAD 操作,每次访问消耗 2,100 Gas。在链上逻辑中应避免对大型数组进行频繁迭代,因为每次读取都会增加此基本成本。链下索引服务更适合检索完整数据集。

3. 动态数组本质上不支持删除元素,除非实现手动移位。调用pop()会删除最后一项,并在清理存储槽时退还 15,000 个 Gas,从而激励清理未使用的状态。然而,从中间删除项目需要移动所有后续元素,导致 O(n) 计算和高 Gas 使用量。

4. 在合同创建期间初始化大型阵列会大大增加部署成本。每个预设值都会消耗存储初始化气体。将数组初始化为空并通过用户交互逐渐填充它们通常会更有效,从而将成本分散到多个事务中。

5. 函数内临时使用的内存阵列不会写入持久存储,从而完全避免 SSTORE 成本。这些非常适合中间计算,但无法保留事务范围之外的数据。在将选择性结果写入存储之前使用内存阵列进行批处理可以优化整体效率。

高效阵列使用的优化技术

1. 当需要通过密钥进行随机访问时,优先选择映射而不是数组。像映射(uint =>地址)这样的映射提供恒定时间的查找,而无需迭代或管理长度的开销。映射还消除了对索引范围和调整大小的担忧。

2. 谨慎地对单个数组元素使用delete。手动将元素设置为零可能比依赖删除更便宜,尤其是在不适用退款的情况下。为了完全清理,重复调用 pop() 直到数组为空可以最大限度地从已清理的存储槽中退款。

3. 限制数组内容的链上暴露。使用数组数据发出事件允许外部系统重建状态,而无需直接从存储中读取。事件的成本低于永久存储写入,并支持通过索引参数进行过滤。

4. 针对追加繁重的工作负载实施检查点或链表模式。通过仅存储条目之间的增量或引用,合约减少了冗余数据存储并最大限度地减少了昂贵的重组。这种方法非常适合跟踪历史状态或用户活动日志。

5. 谨慎利用汇编级优化。内联 Yul 代码可以比高级 Solidity 构造更快地计算存储位置,但会带来寻址不正确的风险。只有高级开发人员才应该尝试低级存储操作,以确保跨不同编译器版本进行彻底测试。

常见问题解答

当访问越界数组索引时会发生什么?访问当前数组长度之外的索引会触发无效的操作码,消耗所有剩余的气体并恢复交易。在访问之前,必须在代码中显式处理边界检查。

数组可以作为参数在合约之间传递吗?是的,数组可以在内部和外部函数调用中传递。 Calldata 数组对于大型输入非常有效,因为它们避免了复制到内存中。外部接口需要ABI编码,支持静态和动态类型。

动态数组的增长大小是否有限制?理论限制受到可用气体和区块大小限制的约束。实际的限制包括追加和迭代的成本不断上升。在链上处理过大的数组时,合约有达到交易 Gas 限制的风险。

空数组声明会消耗存储空间吗?声明一个数组而不初始化它会将其长度设置为零并占用一个存储槽。在添加元素之前不会分配额外的槽。这种最小的占用空间使得未初始化的阵列对于延迟填充来说具有成本效益。

免责声明:info@kdj.com

所提供的信息并非交易建议。根据本文提供的信息进行的任何投资,kdj.com不承担任何责任。加密货币具有高波动性,强烈建议您深入研究后,谨慎投资!

如您认为本网站上使用的内容侵犯了您的版权,请立即联系我们(info@kdj.com),我们将及时删除。

相关百科

如何计算持有 BTCUSDT 期货头寸的总成本

如何计算持有 BTCUSDT 期货头寸的总成本

2026-10-26 04:06:35

BTCUSDT 期货头寸的总成本构成1. 持有BTCUSDT期货头寸的总成本包括显性费用和隐性费用。显性成本包括开仓和平仓交易费用,而隐性成本主要来自一段时间内的资金费率支付或收入。 2. 开仓费用按照入场时的名义价值与交易所的吃单/挂单费用表的乘积计算——对于主要平台上的吃单来说,开仓费用通常在 ...

如何同时监控 XRPUSDT 资金费率和未平仓合约

如何同时监控 XRPUSDT 资金费率和未平仓合约

2026-10-20 18:39:42

XRPUSDT 永续合约的资金费率机制1. XRPUSDT永续合约的资金费率每八小时计算一次,使用XRP和USDT计价借贷市场之间的溢价指数和利差。 2. Binance、Bybit 和 OKX 等交易所在其衍生品 API 端点中发布实时资金费率数据,从而实现仪表板或警报系统的自动摄取。 3. 正的...

如何设置 SOLUSDT 永续合约盈亏平衡止损

如何设置 SOLUSDT 永续合约盈亏平衡止损

2026-10-23 09:34:18

了解盈亏平衡止损机制1. 盈亏平衡止损是一种动态订单,随着头寸盈利变动而向上调整,执行时锁定零净损失。 2. 它仅在交易达到预定利润阈值后才起作用——通常是初始风险或入场费的 1 至 2 倍。 3. 在币安 SOLUSDT 永续合约上,此逻辑必须手动触发或编写脚本,因为本机交易所 UI 不会自动将止...

如何使用币安期货计算器进行 ETHUSDT 交易

如何使用币安期货计算器进行 ETHUSDT 交易

2026-10-21 02:00:11

了解币安期货计算器界面1. 该计算器直接嵌入币安合约交易界面中,可通过订单输入面板下的 ETHUSDT 永续合约页面访问。 2. 随着用户调整输入字段(包括仓位大小、入场价格、杠杆水平以及止盈或止损水平),它会动态更新。 3. 接受多种格式的输入值:合约数量(ETH)、名义价值(USDT)或保证金金...

合约强平前如何查看BTCUSDT标记价格

合约强平前如何查看BTCUSDT标记价格

2026-10-26 12:20:18

了解BTCUSDT期货的标记价格1. 标记价格是交易所为防止市场波动期间出现不公平清算而使用的计算值。 2.反映了来自多个来源的公平、稳定的参考价格,包括指数价格和资金费率。 3. 与最新成交价不同,标记价格包含来自顶级现货交易所的时间加权平均值,以降低操纵风险。 4. 在币安上,BTCUSDT标记...

如何调整 TRUMPUSDT 永续合约的杠杆

如何调整 TRUMPUSDT 永续合约的杠杆

2026-10-30 22:19:37

了解 TRUMPUSDT 永续合约机制1. TRUMPUSDT 是在多个一级衍生品交易所上市的主题永续期货合约,旨在跟踪围绕美国政治叙事而非基础资产基本面的价格情绪。 2、根据平台不同,采用标准的反向或线性结算逻辑,以USDT作为报价和保证金资产。 3. 合约使用的标记价格源自现货 BTC/USDT...

如何计算持有 BTCUSDT 期货头寸的总成本

如何计算持有 BTCUSDT 期货头寸的总成本

2026-10-26 04:06:35

BTCUSDT 期货头寸的总成本构成1. 持有BTCUSDT期货头寸的总成本包括显性费用和隐性费用。显性成本包括开仓和平仓交易费用,而隐性成本主要来自一段时间内的资金费率支付或收入。 2. 开仓费用按照入场时的名义价值与交易所的吃单/挂单费用表的乘积计算——对于主要平台上的吃单来说,开仓费用通常在 ...

如何同时监控 XRPUSDT 资金费率和未平仓合约

如何同时监控 XRPUSDT 资金费率和未平仓合约

2026-10-20 18:39:42

XRPUSDT 永续合约的资金费率机制1. XRPUSDT永续合约的资金费率每八小时计算一次,使用XRP和USDT计价借贷市场之间的溢价指数和利差。 2. Binance、Bybit 和 OKX 等交易所在其衍生品 API 端点中发布实时资金费率数据,从而实现仪表板或警报系统的自动摄取。 3. 正的...

如何设置 SOLUSDT 永续合约盈亏平衡止损

如何设置 SOLUSDT 永续合约盈亏平衡止损

2026-10-23 09:34:18

了解盈亏平衡止损机制1. 盈亏平衡止损是一种动态订单,随着头寸盈利变动而向上调整,执行时锁定零净损失。 2. 它仅在交易达到预定利润阈值后才起作用——通常是初始风险或入场费的 1 至 2 倍。 3. 在币安 SOLUSDT 永续合约上,此逻辑必须手动触发或编写脚本,因为本机交易所 UI 不会自动将止...

如何使用币安期货计算器进行 ETHUSDT 交易

如何使用币安期货计算器进行 ETHUSDT 交易

2026-10-21 02:00:11

了解币安期货计算器界面1. 该计算器直接嵌入币安合约交易界面中,可通过订单输入面板下的 ETHUSDT 永续合约页面访问。 2. 随着用户调整输入字段(包括仓位大小、入场价格、杠杆水平以及止盈或止损水平),它会动态更新。 3. 接受多种格式的输入值:合约数量(ETH)、名义价值(USDT)或保证金金...

合约强平前如何查看BTCUSDT标记价格

合约强平前如何查看BTCUSDT标记价格

2026-10-26 12:20:18

了解BTCUSDT期货的标记价格1. 标记价格是交易所为防止市场波动期间出现不公平清算而使用的计算值。 2.反映了来自多个来源的公平、稳定的参考价格,包括指数价格和资金费率。 3. 与最新成交价不同,标记价格包含来自顶级现货交易所的时间加权平均值,以降低操纵风险。 4. 在币安上,BTCUSDT标记...

如何调整 TRUMPUSDT 永续合约的杠杆

如何调整 TRUMPUSDT 永续合约的杠杆

2026-10-30 22:19:37

了解 TRUMPUSDT 永续合约机制1. TRUMPUSDT 是在多个一级衍生品交易所上市的主题永续期货合约,旨在跟踪围绕美国政治叙事而非基础资产基本面的价格情绪。 2、根据平台不同,采用标准的反向或线性结算逻辑,以USDT作为报价和保证金资产。 3. 合约使用的标记价格源自现货 BTC/USDT...

查看所有文章

User not found or password invalid

Your input is correct