本文深入探讨了Solidity中payable关键字的奥秘。通常payable关键字用于允许函数接收以太币。但一个有趣的现象是,给函数添加payable关键字实际上可以减少Gas消耗。这是因为非payable函数需要额外的opcode来检查是否接收了以太币,而payable函数则不需要,从而减少了Gas消耗。作者建议,gas优化重要,但不要为了节省少量gas而牺牲函数的本意。
嘿,朋友们 👋🏻
欢迎来到解读系列的另一篇文章,在这个系列中,我们深入探讨某个特定的智能合约/Web3 主题。
如果你最近一直在使用 Solidity 开发智能合约,那么你可能已经遇到过 payable 关键字。
这篇博客专门讨论它,我们将解读它所有有趣以及奇怪的秘密。😃
在智能合约可以做的所有奇妙的事情中,存储你的钱(ETH)就是其中之一。现在,为了在智能合约中接收 ETH,Solidity 语言有一个特定的关键字叫做 payable。
一个 payable 关键字,用非常简单的术语来说,是 solidity 语言中的一个修饰符,可以附加到任何函数上。一旦附加,这个关键字允许函数接收以太币。换句话说,在触发一个带有 payable 关键字的函数时,你可以连同该交易一起发送以太币 ( msg.value)。
虽然这一切都很好,但几个月前,我在滚动浏览 Twitter 时,偶然发现了一个关于 payable 关键字 的有趣警告。它吸引了我的所有注意力,我发现每当一个 payable 修饰符附加到任何函数时,都会发生一个有趣的(但真的有点奇怪)的场景 👀。
让我们快速看一下这个有趣的奇怪场景:
pragma solidity ^0.8.7;
contract payableKeyword{
uint256 public state;
function setStateVariable() public{
state = 100;
}
}
在上图附加的图片中,我们有一个非常简单的 setter 函数,它将 uint256 变量 state 设置为 100。 如果你触发这个函数,你会发现交易 gas 成本大约在 43300 左右。
好的,现在让我们看看第二种情况。
pragma solidity ^0.8.7;
contract payableKeyword{
uint256 public state;
function setStateVariable() public payable{
state = 100;
}
}
在第二种情况下,我们有完全相同的函数,它执行一个完全类似的设置状态变量的交易。 然而,这里唯一的区别是附加到该函数的额外的 payable 修饰符。
非常有趣的是,如果你查看调用此函数的交易 gas 成本,它大约为 43276,低于上面提到的没有 payable 关键字的函数。
是的,你没看错。
添加一个简单的 payable 关键字就减少了函数中的 gas 消耗。 😃
好了,现在是时候理解了 —— 为什么 payable 修饰符会降低 Gas 消耗?
对这个问题一个非常简单的答案是:
添加 payable 关键字会减少正在执行的操作码数量,从而降低 gas 消耗量。
这很奇怪,不是吗?向函数添加一个额外的修饰符,怎么会减少操作码的数量,而不是增加它呢???
好吧,这里有一些技术(和逻辑的)解释。😃
在 Non-Payable 函数的情况下:
a. 包含额外的检查,以确保在调用函数时没有传递 ether 值。
b. 这些检查会增加正在执行的操作码的数量。
c. 增加的操作码数量最终导致更高的 gas 使用量。
在 Payable 函数的情况下:
a. 不需要额外的检查,因为该函数可以接受 ether 的零值或非零值。
b. 没有额外的检查意味着没有执行额外的操作码。
c. 执行中的较低操作码意味着较低的 gas 消耗。
以上所有细节是否意味着我们应该使用 PAYABLE 函数来节省 gas?
嗯,这可能是一个讨论。
毫无疑问,gas 优化是每个智能合约大师在他们的合约中梦想的事情。
然而,一个紧迫的问题是:
虽然节省 gas 很重要,但为了节省一些额外的 gas 而损害函数的预期行为、最小化必要的状态更改或使用不充分的策略,这并不是一个好主意。
换句话说,如果一个函数与接收以太币无关,那么它就不应该附加任何 payable 关键字,即使这样可以节省你一些 gas。
因此,我坚信仅仅为了节省 gas 而在一个函数中添加一个不必要的 payable 关键字可能是一个糟糕的决定。 上面提到的在添加 payable 关键字时 gas 减少的场景只是一个奇怪的 solidity 语言设计,根本没有效果。
- 原文链接: decipherclub.com/deciphe...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!