如何减少智能合约 Gas 消耗

  • tenderly
  • 发布于 2022-07-22 11:30
  • 阅读 27

本文介绍了如何使用Tenderly Gas Profiler 分析智能合约的gas使用情况,并根据分析结果,采取最佳的编程实践来优化智能合约,从而减少gas费用。文章详细介绍了Gas Profiler的使用方法,以及一系列Solidity gas 优化的技巧,例如优化存储和内存使用、优化操作、以及使用更高效的解决方案。

Solidity Gas 优化:如何降低智能合约的 Gas 消耗

学习如何使用 Tenderly Gas Profiler 来分析智能合约的 gas 消耗,细化到单个函数调用。在掌握信息后,尝试一些最佳编码实践来优化你的智能合约并减少 gas 费用。

智能合约 gas 优化

Gas 用于支付执行智能合约所需的计算资源。你的智能合约越复杂,计算量越大,它使用的 gas 就越多,因此成本也就越高。

此外,gas 费用是激励以太坊矿工将交易添加到区块链的动力。当你发送交易时,为 gas 使用设置更高的限制会增加你的交易被包含在下一个区块中的机会。

然而,估计你的智能合约将使用多少 gas 通常具有挑战性。gas 的价格取决于许多不同的因素,包括 供需波动的以太坊价格。因此,首先正确优化智能合约以降低其 gas 消耗变得尤为重要。

🔥 最新内容

使用 Tenderly Virtual TestNets,构建和测试具有实际链上数据的真实世界合约和协议集成。在几毫秒内启动托管的、协作的开发环境。在来自 80 多个网络的生产数据之上进行构建,内置浏览器和调试工具。

试用 Virtual TestNets

智能合约 gas 估算 vs. 优化

许多智能合约工程师使用不同的工具来估算 gas 使用量,以避免 gas 支付不足或超额支付。然而,这些估算并不总是准确的,因为许多不同的因素会影响 gas 的价格。例如,不同的区块大小、区块时间、区块传播时间或与最近区块的比较使得难以准确估计下一个区块可能的最低 gas 价格。

这就是智能合约优化至关重要的原因,它允许工程师编写和改进他们的代码以减少其 gas 使用量。以太坊 gas 优化要求你确保你的代码在按预期执行的同时,消耗更少的计算资源。而这通过 Tenderly Gas Profiler 变得更加容易。

如何使用 Tenderly Gas Profiler 优化智能合约 gas 使用量

Gas Profiler 提供了一个详细的概述,说明交易在链上或链下运行后使用了多少 gas。该功能使用火焰图作为整个交易中 gas 消耗的可视化表示。然后,它允许你将 gas 使用量分解为单独的函数调用,并查看代码的哪些部分使用了最多的 gas 来执行。

以太坊 gas 优化

你可以通过 创建一个 Tenderly 账户,打开一个交易,然后单击导航栏中的 Gas Profiler 选项卡,轻松访问 Gas Profiler。

为什么要使用 Gas Profiler?

市场上的许多 gas 分析器实际上是 gas 估算器,主要侧重于显示智能合约中的平均 gas 消耗量。这可能很有帮助,但在大多数情况下,它没有提供工程师所需的详细程度。

另一方面,Tenderly Gas Profiler 使工程师可以轻松检查每个被调用函数在执行交易时花费了多少 gas。它是 分析智能合约 的重要工具,也是进一步代码优化的良好起点。Gas Profiler 允许你从高层次理解 gas 使用情况,然后深入研究内部函数执行以获得深入的了解。

Solidity 中的 gas 优化

如何在 Tenderly 中优化智能合约 gas 使用量

Gas Profiler 部分收集了你需要的信息后,你可以通过单击“在 Debugger 中查看”按钮,在 Tenderly Debugger 中打开你要检查的函数。

以太坊智能合约 gas 优化

进入 Debugger 后,你可以使用 Stack Execution Traces 进一步检查代码行以获取更多信息。有了如此详细的输入,你就可以确定可以进行哪些代码调整以减少 gas 消耗。

要评估发现的调整是否真的优化了 gas 使用量,你可以使用 Tenderly Simulator。在运行模拟之前,你可以编辑合约源代码以在代码中包含这些调整,并使用更改后的源代码模拟执行。

所以,下一步是单击 Re-Simulate 按钮。进入下一个视图后,单击 Edit Contract Source,这将打开一个窗口,你可以在其中优化计算量大的代码行。

智能合约中的 gas 优化

完成所需的编辑后,点击 Apply Changes 按钮,然后点击 Simulate Transaction。你将获得一个新的交易输出,其中包含更新后的 gas 使用量。你可以返回 Gas Profiler 以查看更新后的代码使用了多少 gas,以及你的优化是否成功。

在 Solidity 中进行 gas 优化的一些编码实践是什么?

在使用 Gas Profiler 分析 gas 消耗并打开 Edit Contract Source 视图后,你可以通过实现更有效的解决方案来优化你的智能合约代码。

以下是一些你可以尝试的最佳编码实践:

1. 优化存储使用

存储槽的数量以及你在智能合约中表示数据的方式会严重影响 gas 的使用量。以下是一些建议:

  • 限制存储使用:由于存储是最昂贵的内存类型,你需要尽可能少地使用它,但这并不总是容易的。仅将存储用于必要的数据,仅此而已。尝试减少区块链存储的使用。例如,瞬态(非永久性)数据可以存储在内存中。此外,通过将中间结果保存在内存或堆栈中来防止存储修改。仅在所有计算完成后才将结果分配给存储变量。
  • 打包变量:以太坊中内存的最小量是一个 256 位插槽。即使插槽未满,你也需要支付整数数量。为避免这种情况,你可以使用变量打包技术。编译器会将几个连续的变量(其总长度为 256 或更少)打包到一个插槽中。在定义结构体时也使用此技术。此外,在定义时,请连续声明相同数据类型的存储变量。Solidity 编译器会自动打包它们。但是,请注意,这不适用于内存和 Calldata,因为它们的变量无法打包。

2. 优化内存使用

数据类型的选择是另一个决定以太坊虚拟机 (EVM) 在后台读取、写入和操作它们时所做工作量的因素。这直接影响 gas 的使用,因此仔细选择将有助于优化 gas。

  • Uint* vs. Uint256: EVM 以 256 位块执行操作,因此将 uint*(小于 256 位的无符号整数)转换为 uint256 会消耗额外的 gas。将更多变量打包到一个插槽中时,请使用小于或等于 128 位的无符号整数。如果这不可能,请使用 uint256 变量。
  • Mapping vs. array: 数据列表仅由 Solidity 中的两种数据类型表示:数组和映射。映射更有效且成本更低,而数组是可迭代和可打包的。最好使用映射来管理数据列表,除非需要迭代或可以压缩数据类型。这对于存储和内存都有好处。可以通过提供整数索引作为键来使用映射来管理有序列表。
  • 固定大小:Solidity 中任何固定大小的变量都比可变大小的变量便宜。如果可能,请使用固定大小的数组而不是动态数组。
  • 默认值:初始化变量时,最好设置它们的值,但这会消耗 gas。在 Solidity 中,所有变量默认设置为 0。因此,如果变量的默认值为 0,则不要显式将其设置为该值。
  • 常量:对于不变的数据,请使用常量而不是变量。

3. 优化操作

并非所有解决方案的实现方式在 gas 使用方面都同样有效。你决定实现函数调用或复杂逻辑表达式的方式可能会影响 gas 的使用量。以下是一些可以通过更优化的解决方案减少 gas 使用的情况:

  • 内部函数调用:当你调用公共函数时,它比调用内部函数花费的时间要长得多,因为所有参数都被复制到内存中。尽可能使用内部函数调用,其中参数作为引用传递。它们的执行成本略高,但多次使用时可以节省大量重复字节码。
  • 更少的函数:尽量减少内部函数和私有函数的数量,以平衡函数复杂性和数量。反过来,这将通过减少函数调用的数量来帮助你减少执行时的 gas 费用。但是,请记住,拥有太大的函数会使测试更加困难,甚至会危及安全性。因此,请注意不要过度减少函数的数量。
  • 短路:对于逻辑表达式,请尝试尽可能简化复杂的表达式。以最小化不必要评估第二个表达式的几率的方式编写它们。请记住,在逻辑析取 (OR/||) 中,当第一个表达式为真时,不会执行第二个表达式。此外,请记住,如果在逻辑析取 (AND/&) 中,第一个表达式的计算结果为假,则不会计算后续表达式。
  • 限制修饰符:修饰符的代码放置在修改的函数中,这会增加其大小和 gas 使用量。为避免这种情况,请减少修饰符的数量。
  • 单行交换:在一个指令中,你可以交换两个变量的值。使用:(a, b) = (b, a) 而不是使用辅助变量进行交换。

4. 探索一些通用建议

除了实施一些特定解决方案外,你还可以尝试避免一些可能导致更高 gas 费用的做法:

  • 尽量减少对存储变量的直接访问:尝试通过本地(内存和 Calldata)变量访问存储变量。不要重复读取/写入存储变量,而是将其复制到本地变量并改用它。仅在计算出最终结果时才写入存储变量。
  • 尽可能少地使用循环:仅在绝对必要且不可避免的情况下才在智能合约中使用循环。
  • 消除不必要的计算:尝试找到最有效的算法来执行计算。如果你的算法直接使用它们的计算结果,请删除计算。换句话说,消除未使用的计算。
  • 低效的数据结构:尝试找到更有效和合适的结构来表示你的数据。例如,如果你不需要按顺序迭代数据,则对于直接索引操作,请优先选择映射而不是数组。

5. 使用更少耗电的解决方案

还有一些其他选项可以帮助你优化智能合约并降低其 gas 消耗。考虑使用:

  • 在可用时预编译合约。
  • 优化的库。
  • 可压缩的数据结构。
  • ZK-SNARKs 以减少需要在链上存储和计算的数据量。

智能合约优化始于 gas 使用信息

虽然有不同的实践来优化智能合约,但你首先需要深入了解你的代码如何使用 gas。Tenderly Gas Profiler 允许你深入了解 gas 消耗的复杂性,方法是将其细化到单个函数调用。获得信息和适当的工具后,你可以尝试智能合约优化并找到一个可以帮助你减少 gas 费用的解决方案。

  • 原文链接: blog.tenderly.co/how-to-...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
tenderly
tenderly
江湖只有他的大名,没有他的介绍。