每次交易被发送到区块链上,必须支付 Gas 费用。你可以设计和实现你的智能合约,使其具有Gas 效率。在本博客中将讨论两种 "类型"的 Gas,交易 Gas和部署 Gas
原文标题:Smart Contracts Gas optimization techniques
原文作者:Alberto Molina
原文来源:medium.com
编译: 登链社区
每次交易被发送到区块链上,必须支付 Gas 费用。消耗的 Gas 与交易所需的计算量有关,即:EVM 执行交易所需的计算量(如果交易不涉及 EVM,例如简单的以太币转账,Gas 的数量是固定的)。
你可以设计和实现你的智能合约,使其具有Gas 效率。在本博客中将讨论两种 "类型"的 Gas :
有时,减少一种 Gas 的技术会导致另一种 Gas 的增加,这是我们必须处理的权衡......
这是一份清单,在处理你的智能合约时应该记住的事情,以便节省 Gas。
在区块链存储上保存数据是很昂贵的,设法将需要在区块链上存储的信息量减少到最小,将会节省大量的交易 Gas。
在智能合约上执行的功能,应该只在出于安全、法律或任何其他非常好的理由下才添加。把所有剩下的任务放在链外,放在专门的后端甚至是前端,这样你就可以节省交易 Gas。
以太坊有 4 个内存位置,从最便宜的到最贵的:calldata,栈,内存和存储。如果使用得当,你将节省大量的交易 Gas。
Solidity 存储槽的长度为 32 字节,但并不是所有的数据类型都需要这么大的空间:bool, int8 ... int128, bytes1 ... bytes31 和地址需要的空间小于 32 字节。
solidity 编译器会尝试将变量打包在一个槽中,但需要这些变量定义在彼此的旁边。
例如,如果你接连定义了 2 个uint128,它们都会被打包到同一个存储槽中,因为它们各占 16 字节。然而,如果你定义了一个uint128,接着是一个unit256,然后是另一个int128,你将使用 3 个存储槽,因为在两个 int128 之间的 unit256 需要一个完整的存储槽。
你可以通过调整变量顺序节省存储空间和交易 Gas。
如果你要定义变量将占用一个完整存储槽,最好使用实际占用完整存储槽的变量。
让我用一个例子来解释一下:
若我们的智能合约只需要一个状态变量,一个永远不会大于 255 的无符号整数。我们会很想使用uint8作为数据类型。问题是,以太坊操作码被设计为使用 256 位的变量(EVM 堆栈的大小),而 uint8 只需要 8 位,然后 EVM 会在剩余的位上填上 "0",以便能够操作它。这个由 EVM 执行的填 "0" 操作将花费 Gas,因此为了节省交易 Gas,最好使用 uint256 而不是 uint8。
如果你打算在智能合约中重复使用代码,那么最好将所有的代码打包到一个库中,部署它,并通过 import 方式使合约指向它。
库可以有两种类型:
如果你需要部署多个功能完全相同的合约,应该考虑使用 "最小代理"(在 ERC 1167 中定义)
最小的代理只是一个合约,它将把所有的调用委托给一个预先定义的实现合约。它有一个定义好的字节码,代表最小代理合约的编译代码,你只需要把你的实现合约地址插入其中,你就可以根据需要部署最小代理的多个副本。参考ERC 1167[5] 相关文章,了解如何使用最小代理)。
由于最小的代理字节码非常小,部署它的成本也低到不能再低,因此节省一堆部署 Gas。
使用最小代理的注意事项,你应该牢记:最小代理的实现合约地址不能改变,这意味着你将不能升级他们的代码。
构造器方法只执行一次,在合约创建期间,但如果你设法简化它,将节省部署 Gas。
常量及不可变量(immutable):常量和不可变的状态变量在合约被部署后不能被改变。区别在于,常量必须在编译时定义,而不可变量可以在构造函数中定义。总是尽量使用常量,以便使构造函数更便宜。
合约的部署成本取决于几个方面,其中之一是你要部署的合约的大小(以 KB 为单位,请记住,单个合约的限制是 24KB)。
减少部署 Gas的一个简单方法,就是尽可能地使实现合约更小。
在部署前编译你的代码时,不要忘记激活 solidity 编译器 Gas 优化器。这个功能告诉编译器优化将被生成并部署到区块链上的字节码,这样就可以减少部署和交易Gas。
总的来说,优化器试图简化复杂的表达式,从而减少代码大小和执行成本。它还对函数进行形式化或内联。函数内联是一个可能导致更大的代码的操作,但它经常被做,因为它带来更多简化(运算)的机会。
本翻译由 Duet Protocol[6] 赞助支持。
参考资料
[1]登链翻译计划: https://github.com/lbc-team/Pioneer
[2]翻译小组: https://learnblockchain.cn/people/412
[3]Tiny 熊: https://learnblockchain.cn/people/15
[4]智能合约不是数据库: https://learnblockchain.cn/article/880
[5]ERC 1167: https://learnblockchain.cn/tags/EIP1167
[6]Duet Protocol: https://duet.finance/?utm_souce=learnblockchain
责任编辑:Kate