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

2023-12-25

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()宣告你认为永远有效的事情。如果它们被证明是错误的,那么你的合同中就有错误。

断言不仅仅是一种幻想if。虽然它确实执行运行时检查,但它也是提供形式验证目标的方法之一。工具如SMT检查器 https://docs.soliditylang.org/en/latest/smtchecker.htmlSolidity 内置编译器可以通过尝试证明有关代码的各种陈述来检测错误。问题是 - 这样的工具如何判断你得到的结果不是你想要的结果?用断言记录您的假设是一种非常简单的方法,可以为工具提供区分预期行为和有缺陷行为所需的额外信息。

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

最后,这个断言是正确的,但真的是这样吗?obvious?实际上有很多假设:

  • Contract can receive ether only in a few specific ways:
    1. 通过调用其应付函数 -sendHalf()这里只有一个人
    2. 其召唤receive() or fallback()功能 - 没有
    3. 是的接收者selfdestruct另一份合同的
    4. 成为区块中开采的以太币的接收者
  • 的被叫方transfer()无法回电sendHalf()因为transfer()仅转发 2300 Gas,外部调用成本更高。
  • 的被叫方transfer()不能执行selfdestruct因为它要花费 5000 天然气。
  • 恢复到内部transfer()不会以任何方式被压制,所以即使付出的代价selfdestruct将 future 更改为
  • 以太坊上的交易只能按顺序执行,开采的以太币不能在合约执行过程中转移。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么在这个智能合约上使用断言? 的相关文章

随机推荐

  • Perl 中浮点到十进制转换的二进制表示

    我读了堆栈溢出问题如何在 Perl 中将二进制字符串转换为数字 https stackoverflow com questions 483655 how do i convert a binary string to a number in
  • 异步 System.Threading.Timer 有时会抛出空异常[关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 我试图在一段时间间隔后异步执行代码 并且只想在完成代码执行后再次检查以防止重叠 为此 我使用以下变量和计时器代码 pri
  • 伪类和伪元素有什么区别?

    有什么区别div after and div after 我们什么时候必须使用 over 双冒号和单冒号表示法是区分的 伪类和伪元素 上述说法的实际含义是什么 From https developer mozilla org en US d
  • 如何在 Markdown 标记中缩进几行?

    我想写几行文字 它们的格式应正常 但每行应从第六列开始 IE 我不希望代码块格式化规则使这块文本看起来像代码 因为我将使用其他格式 如粗体等 如何在 Markdown 中做到这一点 Markdown 的原生功能无法做到这一点 然而 mark
  • Xcode 9 - 测试目标 X 遇到错误(无法连接到测试管理器)

    我正在尝试运行一些单元测试 但它一直给我错误 Showing Recent Issues Test target X encountered an error Unable to connect to test manager on d73
  • 使用什么算法来计算校验位?

    使用什么算法来计算数字列表的校验位 列表的长度在 8 到 12 位数字之间 也可以看看 如何生成验证码 号码 https stackoverflow com questions 46231 how to generate a verific
  • Firebase HTTP v1 API 不再批量发送?

    我收到了一封来自 Google 的电子邮件 通知我以下服务即将停用 在对 FCM 的单个 HTTP 请求中包含多个发送请求 称为批量发送 推荐的方法是 通过 HTTP v1 API 发送消息 该 API 已针对扇出性能进行了优化 在本页面
  • Symfony2 twig 翻译 {% trans %} 标签中的变量值

    我正在开发一个 Symfony2 项目并有一个问题 合而为一twig模板我从控制器收到一个变量 这是一个字符串 我需要翻译它 但语法 trans post name endtrans 返回错误 消息必须是 中的简单文本 那么有没有办法翻译变
  • C++0x 原子模板实现

    我知道英特尔的 TBB 中存在类似的模板 除此之外我在 google 或 Boost 库中找不到任何实现 您可以在 boost 中找到有关此功能实现的讨论 http lists boost org Archives boost 2008 1
  • 使用 htaccess 从特定文件夹中删除 SSL 集成

    我的整个网站都集成了 SSL 并放置了 htaccess 代码 以便在任何人访问我的域 URL 时重定向到 https 但我想将一个文件夹保留在 https 重定向之外 请帮我解决这个问题 下面是放置在我的根目录中的 htaccess 代码
  • 使用 pandas.merge_asof 进行全外连接

    您好 我需要将一些时间序列数据与最近的时间戳对齐 所以我认为pandas merge asof可能是一个很好的候选人 但是 它没有设置选项how outer 就像标准中一样merge method 一个例子可以是 df1 Value1 Ti
  • form_for 中 :model 和 @model 的区别?

    使用 form for 以下方式有什么区别 and 使用 user 是否会自动对 URL 操作使用 CRUD 方法 如果你只是给出一个模型实例 例如 user如果不指定操作 如第一个
  • Django:删除关系末尾时不会触发 m2m_changed

    NOTICE 由于生产环境限制 我必须坚持django 1 4暂时 我刚刚做了一个测试 看看当 ManyToMany 发生变化时是否可以挂钩事件 我有一个Group模型可容纳多个Item对象 每当任何组中的项目发生变化时 我都想对相关的 G
  • 将 CGPathRef 转换为 NSBezierPath

    在 Apple 文档中 他们为您提供了如何将 NSBezierPath 转换为 CGPathRef 的代码 我需要以相反的方式进行转换 从 CGPathRef 转换为 NSBezierPath UIBezierPath 有一个名为 cgPa
  • Azure 混合连接管理器不起作用

    要求 我有一个本地部署SQL服务器 and an Azure 网络应用服务需要互相交谈 我在另一台计算机上安装了混合连接管理器 该计算机与 SQL 服务器位于同一 LAN 中 我们将此计算机称为连接电脑 工作部分 安装和配置非常简单 混合连
  • 在officeR的body_add_table()函数中更改字体大小和样式

    我正在尝试更改官员表格中的字体大小body add table 功能 但没有成功 我怎样才能做到这一点 我正在使用以下代码 body add table my doc value tab02 style table template fon
  • CFFILE - 使用组件上传文件

    我有一个表单 我想提交给组件进行处理 CRUD 行为 问题是似乎将多部分 表单数据传递给组件会以某种方式丢失文件位置 当到达应该上传文件的组件部分时 我收到臭名昭著的表单字段不包含文件错误 我不是 100 确定为什么会发生这种情况 但如果我
  • 如何只推送到 Hg 中的一个分支?

    我有一个 Hg 存储库 其中有 3 个分支 但其中两个处于非活动状态 因为我已经将它们合并到我的默认分支中 hg heads显示 3 个头 每个分支一个 尽管汞分支显示其中 2 个分支为 非活动 当我尝试推送我的默认分支时 使用hg Pus
  • InvalidDefinitionException:无法构造“com.vehicle.datatransferobject.VehicleDTO”的实例

    在我在 Spring Boot 中构建的 REST 端点中 我试图传递我的vehicleDTO到我的控制器 但在它到达我的控制器之前 出现了错误 InvalidDefinitionException 无法构造实例com vehicle da
  • 为什么在这个智能合约上使用断言?

    contract Sharer function sendHalf address payable addr public payable returns uint balance require msg value 2 0 Even va