市值: $2.1591T 2.61%
成交额(24h): $74.6886B -50.71%
恐惧与贪婪指数:

15 - 极度恐惧

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

选择语种

选择语种

选择货币

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

阵列存储在 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),我们将及时删除。

相关百科

在Bybit上进行BTC交易如何选择线性永续合约和反向永续合约?

在Bybit上进行BTC交易如何选择线性永续合约和反向永续合约?

2026-06-06 02:54:55

合同结算机制1. Bybit的线性永续合约以USDT结算,这意味着所有盈亏计算、保证金要求和清算门槛均以稳定币单位计价。 2.反向永续合约以BTC本身结算,因此每笔交易都会直接影响交易者的BTC余额——收益会增加BTC持有量,而损失会减少BTC持有量。 3. 反向合约的定价引擎使用 BTC/USDT...

如何识别和避免止损、欺骗等期货市场操纵行为?

如何识别和避免止损、欺骗等期货市场操纵行为?

2026-06-07 14:20:10

Bitcoin 减半机制1. Bitcoin 的协议强制执行固定的发行时间表,其中大约每 210,000 个区块,区块奖励就会减少一半。 2. 该事件大约每四年发生一次,直接减少了新进入流通的 BTC 数量。 3.截至2020年减半,矿工每区块获得6.25 BTC;下一次减少将达到 3.125 BT...

如何在Bybit上设置风险管理规则来限制我的每日最大损失?

如何在Bybit上设置风险管理规则来限制我的每日最大损失?

2026-06-04 16:40:15

账户级损失限额配置1. 使用双因素身份验证通过网络或移动应用程序登录您的 Bybit 帐户。 2. 导航至“资产”部分,然后从左侧菜单中选择“风险管理”。 3. 选择“每日损失限制”并将该功能切换为“开”以激活控制。 4. 输入代表当前交易日 USDT 最大允许净亏损的数值。 5. 使用您的电子邮件...

如何在币安上启用投资组合保证金模式以降低我的保证金要求?

如何在币安上启用投资组合保证金模式以降低我的保证金要求?

2026-06-05 04:59:43

Bitcoin 减半机制1. Bitcoin 的协议强制执行固定的发行时间表,其中大约每 210,000 个区块,区块奖励就会减少一半。 2. 该事件大约每四年发生一次,直接减少每个区块新进入流通的 BTC 数量。 3.截至2020年减半,矿工每区块获得6.25 BTC;下一次减少将使其达到 3.1...

如何将我的未平仓期货头寸从币安迁移到Bybit而不平仓?

如何将我的未平仓期货头寸从币安迁移到Bybit而不平仓?

2026-06-04 03:59:47

Bitcoin 减半机制1. Bitcoin 的协议强制执行固定的发行时间表,其中大约每 210,000 个区块,区块奖励就会减少一半。 2. 该事件大约每四年发生一次,直接减少了新进入流通的 BTC 数量。 3.截至2020年减半,矿工每区块获得6.25 BTC;下一次减少将达到 3.125 BT...

如何处理美国加密货币期货交易利润的税务影响?

如何处理美国加密货币期货交易利润的税务影响?

2026-05-29 18:19:59

Bitcoin 减半机制1. Bitcoin 的协议强制规定 2100 万枚代币的固定供应上限,并通过区块奖励引入新单位。 2. 每 210,000 个区块(大约每四年)区块奖励就会减少一半,这个过程称为减半。 3. 最近一次减半发生在 2024 年 4 月,每个区块的奖励从 6.25 BTC 减少...

在Bybit上进行BTC交易如何选择线性永续合约和反向永续合约?

在Bybit上进行BTC交易如何选择线性永续合约和反向永续合约?

2026-06-06 02:54:55

合同结算机制1. Bybit的线性永续合约以USDT结算,这意味着所有盈亏计算、保证金要求和清算门槛均以稳定币单位计价。 2.反向永续合约以BTC本身结算,因此每笔交易都会直接影响交易者的BTC余额——收益会增加BTC持有量,而损失会减少BTC持有量。 3. 反向合约的定价引擎使用 BTC/USDT...

如何识别和避免止损、欺骗等期货市场操纵行为?

如何识别和避免止损、欺骗等期货市场操纵行为?

2026-06-07 14:20:10

Bitcoin 减半机制1. Bitcoin 的协议强制执行固定的发行时间表,其中大约每 210,000 个区块,区块奖励就会减少一半。 2. 该事件大约每四年发生一次,直接减少了新进入流通的 BTC 数量。 3.截至2020年减半,矿工每区块获得6.25 BTC;下一次减少将达到 3.125 BT...

如何在Bybit上设置风险管理规则来限制我的每日最大损失?

如何在Bybit上设置风险管理规则来限制我的每日最大损失?

2026-06-04 16:40:15

账户级损失限额配置1. 使用双因素身份验证通过网络或移动应用程序登录您的 Bybit 帐户。 2. 导航至“资产”部分,然后从左侧菜单中选择“风险管理”。 3. 选择“每日损失限制”并将该功能切换为“开”以激活控制。 4. 输入代表当前交易日 USDT 最大允许净亏损的数值。 5. 使用您的电子邮件...

如何在币安上启用投资组合保证金模式以降低我的保证金要求?

如何在币安上启用投资组合保证金模式以降低我的保证金要求?

2026-06-05 04:59:43

Bitcoin 减半机制1. Bitcoin 的协议强制执行固定的发行时间表,其中大约每 210,000 个区块,区块奖励就会减少一半。 2. 该事件大约每四年发生一次,直接减少每个区块新进入流通的 BTC 数量。 3.截至2020年减半,矿工每区块获得6.25 BTC;下一次减少将使其达到 3.1...

如何将我的未平仓期货头寸从币安迁移到Bybit而不平仓?

如何将我的未平仓期货头寸从币安迁移到Bybit而不平仓?

2026-06-04 03:59:47

Bitcoin 减半机制1. Bitcoin 的协议强制执行固定的发行时间表,其中大约每 210,000 个区块,区块奖励就会减少一半。 2. 该事件大约每四年发生一次,直接减少了新进入流通的 BTC 数量。 3.截至2020年减半,矿工每区块获得6.25 BTC;下一次减少将达到 3.125 BT...

如何处理美国加密货币期货交易利润的税务影响?

如何处理美国加密货币期货交易利润的税务影响?

2026-05-29 18:19:59

Bitcoin 减半机制1. Bitcoin 的协议强制规定 2100 万枚代币的固定供应上限,并通过区块奖励引入新单位。 2. 每 210,000 个区块(大约每四年)区块奖励就会减少一半,这个过程称为减半。 3. 最近一次减半发生在 2024 年 4 月,每个区块的奖励从 6.25 BTC 减少...

查看所有文章

User not found or password invalid

Your input is correct