【问题标题】:Why assertion is used on this Smart Contract?为什么在这个智能合约上使用断言?
【发布时间】:2022-01-09 23:15:13
【问题描述】:
contract Sharer {
    function sendHalf(address payable addr) public payable returns (uint balance) {
        require(msg.value % 2 == 0, "Even value required.");
        uint balanceBeforeTransfer = address(this).balance;
        addr.transfer(msg.value / 2);
        // Since transfer throws an exception on failure and
        // cannot call back here, there should be no way for us to
        // still have half of the money.
        assert(address(this).balance == balanceBeforeTransfer - msg.value / 2);
        return address(this).balance;
    }
}

对于上面的合约,在什么情况下断言失败/address(this).balance 没有减少 (msg.value / 2)?为什么我们需要断言?

【问题讨论】:

    标签: solidity assert evm


    【解决方案1】:

    如果addr.transfer(msg.value / 2) 失败,它会恢复sendHalf() 的执行。

    所以assert() 在这种情况下是多余的。

    【讨论】:

      【解决方案2】:

      断言是正确的,这正是它存在的原因。你使用assert() 来声明你认为永远存在的东西。如果它们被证明是错误的,那么您的合同中就有错误。

      断言不仅仅是一个花哨的if。虽然它确实执行运行时检查,但它也是为形式验证提供目标的方法之一。 Solidity 编译器中内置的 SMTChecker 等工具可以通过尝试证明有关您的代码的各种陈述来检测错误。问题是——这样的工具怎么能告诉你得到的结果不是你想要的结果?用断言记录您的假设是一种非常直接的方法,可以为工具提供额外信息,以区分预期行为和错误行为。

      此外,虽然合约现在很简单并且很容易看出它不会失败,但代码不会永远保持简单。只有在合同没有其他应付功能的假设下,该条件才成立。你会记得每次添加应付函数时都要修改这个函数吗?如果合约增长并且函数被埋在文件底部的几个其他函数下怎么办?最重要的是——其他人将来修改代码怎么办?他们甚至会注意到这个限制吗?断言是一种好方法,不必依赖任何人注意到这一点并将其转变为自动检查。

      最后,断言是正确的,但它显而易见吗?实际上有很多假设:

      • 合约只能通过以下几种特定方式接收以太币:
        1. 通过调用其支付函数 - sendHalf() 是这里唯一的一个
        2. 调用其receive()fallback() 函数 - 没有
        3. 是另一份合同的selfdestruct 的收件人
        4. 成为区块中开采的以太币的接收者
      • transfer() 的被调用者无法回调 sendHalf(),因为 transfer() 仅转发 2300 gas,而外部调用成本更高。
      • transfer() 的被调用者无法执行 selfdestruct,因为它需要花费 5000 gas。
      • transfer() 内部的还原不会以任何方式静音,因此即使 selfdestruct 的成本将 future 更改为
      • 以太坊上的交易仅按顺序执行,开采的以太币不能在合约执行过程中转移。

      这里有足够的假设,代码的作者可能根本无法 100% 确定他没有错过一些可能会变成安全漏洞的晦涩的极端情况。断言是明确排除这种可能性的一种简单而有效的方法。

      【讨论】:

        猜你喜欢
        • 2021-12-28
        • 2020-05-07
        • 2021-08-28
        • 2017-11-07
        • 1970-01-01
        • 2020-06-01
        • 2021-08-28
        • 2017-07-02
        • 2021-08-19
        相关资源
        最近更新 更多