gpt4 book ai didi

solidity - 为什么在这个智能合约上使用断言?

转载 作者:行者123 更新时间:2023-12-05 03:34:16 25 4
gpt4 key购买 nike

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)?为什么我们在这里需要断言?

最佳答案

断言是真的,这正是它在那里的原因。您使用 assert() 来声明您认为将始终有效的内容。如果结果证明它们是假的,则说明您的契约(Contract)中存在错误。

断言不仅仅是花哨的if。虽然它确实执行运行时检查,但它也是为形式验证提供目标的方法之一。 SMTChecker 等工具内置在 Solidity 编译器中的程序可以通过尝试证明关于您的代码的各种陈述来检测错误。问题是 - 这样的工具如何判断您得到的结果不是您想要的结果?用断言记录您的假设是一种非常直接的方法,可以为工具提供识别预期行为与错误行为所需的额外信息。

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

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

  • 合约只能通过几种特定方式接收以太币:
    1. 通过调用它的 payable 函数 - sendHalf() 是这里唯一的一个
    2. 调用其 receive()fallback() 函数 - 没有
    3. 作为另一个合约的selfdestruct的接收者
    4. 作为区 block 中开采的以太币的接收者
  • transfer() 的被调用者无法回调sendHalf() 因为transfer() 只转发了2300 gas 并且外部调用成本更高.
  • transfer() 的调用者无法执行 selfdestruct 因为它花费了 5000 gas。
  • transfer() 中的还原不会以任何方式被沉默,所以即使 selfdestruct 的成本将 future 更改为 <= 2300 gas,发布它也会终止无论如何都要执行。
  • 以太坊上的交易仅按顺序执行,开采的以太币不能在契约(Contract)执行过程中转移。

这里有足够多的假设,代码的作者可能根本无法 100% 确定他没有遗漏一些可能会变成安全漏洞的模糊角落案例。断言可以是明确排除这种可能性的简单而有效的方法。

关于solidity - 为什么在这个智能合约上使用断言?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70216805/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com