智能合约语言Solidity - 错误处理

news/2024/6/28 20:21:17

链客,专为开发者而生,有问必答!

此文章来自https://www.liankexing.com,未经允许拒绝转载。

在这里插入图片描述

Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊、智能合约有所了解,如果你还不了解,建议你先看以太坊是什么?

什么是错误处理

错误处理是指在程序发生错误时的处理方式,Solidity处理的方式和常见的语言不一样,其时通过回退状态的方式来处理错误,发生异常时会撤销当前调用所改变的状态,同时给调用者返还一个错误标识。

为什么要这么设计呢?

我们把区块链理解为全球分享的分布式事务性数据库,全球共享意味着每个人都可以读取其中记录,想要修改这个数据库的内容,就必须创建一个事务,意味着要的修改只能被完全应用或不进行。

如何处理

Solidity提供2个函数assert和requrie进行检查,条件如果不满足则抛出异常,assert函数通常用来检查内部错误,另一个用来检查输入变量或合同状态变量是否满足条件及验证调用外部合约返回值。如果正确使用assert,由一个solitity分析工具就可以分析出只能合约中的错误,帮助我们发现合约中逻辑错误的bug。

另外还有两种方式来触发异常:

revert函数可以用来标记错误并回退当前调用

使用throw关键字抛出异常

当子调用中发生异常时,异常会自动向上“冒泡”。 不过也有一些例外:send,和底层的函数调用call, delegatecall,callcode,当发生异常时,这些函数返回false。

在下面通过一个示例来说明如何使用require来检查输入条件,以及assert用于内部错误检查:

pragma solidity ^0.4.0;contract Sharer { function sendHalf(address addr) public payable returns (uint balance) { require(msg.value % 2 == 0); // 仅允许偶数 uint balanceBeforeTransfer = this.balance; addr.transfer(msg.value / 2); // 如果失败,会抛出异常,下面的代码就不是执行 assert(this.balance == balanceBeforeTransfer - msg.value / 2); return this.balance; }}

运行测试2:附加2wei 去调用sendHalf,运行正常。

运行测试3:附加2wei以及sendHalf参数为当前合约本身,在转账是发生异常,因为合约无法接收转账,错误提示上图类似。

assert类型异常

在下述场景中自动产生assert类型的异常:

如果越界,或负的序号值访问数组,如i >= x.length 或 i < 0时访问x[i]

如果序号越界,或负的序号值时访问一个定长的bytesN。

被除数为0, 如5/0 或 23 % 0。

对一个二进制移动一个负的值。如:5<

require类型异常

在下述场景中自动产生require类型的异常:

调用throw

如果调用require的参数为false

如果在使用new创建一个新合约时出现第3条的原因没有正常完成。

如果调用外部函数调用时,被调用的对象不包含代码。

当发生require类型的异常时,Solidity会执行一个回退操作(指令0xfd)。当发生assert类型的异常时,Solidity会执行一个无效操作(指令0xfe)。在上述的两种情况下,EVM都会撤回所有的状态改变。是因为期望的结果没有发生,就没法继续安全执行。注意assert类型的异常会消耗掉所有的gas, 而require从大都会版本(Metropolis, 即目前主网所在的版本)起不会消耗gas。


http://lihuaxi.xjx100.cn/news/237690.html

相关文章

Docker网络解决方案-Flannel部署记录

Docker跨主机容器间网络通信实现的工具有Pipework、Flannel、Weave、Open vSwitch&#xff08;虚拟交换机&#xff09;、Calico实现跨主机容器间的通信。其中Pipework、Weave、Flannel&#xff0c;三者的区别是&#xff1a; Weave的思路 12在每个宿主机上布置一个特殊的route的…

postgres语法_SQL Create Table解释了MySQL和Postgres的语法示例

postgres语法A table is a group of data stored in a database.表是存储在数据库中的一组数据。 To create a table in a database you use the CREATE TABLE statement. You give a name to the table and a list of columns with its datatypes.要在数据库中创建表&#…

json的简单的数据格式

json的简单数据格式 var arr{"obj1":["张三","12","女"],"obj2":["李四","12","女"],"obj3":["王五","12","女"],} var str""; $.each(a…

智能合约语言 Solidity 以太单位及时间单位

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自https://www.liankexing.com&#xff0c;未经允许拒绝转载。 Solidity是以太坊智能合约编程语言&#xff0c;当然你在阅读这篇文章之前&#xff0c;你应该对以太坊、智能合约有初步或者深入的了解&…

Android逆向--如何调试smali代码?

最近在重整Android逆向分析环境&#xff0c;一切都在从零开始&#xff0c;做下记录&#xff0c;给大家分享。 本文介绍Android逆向中smali代码的调试及环境的准备。 事先准备如下工具&#xff1a; Android killer&#xff1a;反编译APK应用为smali源码的工具 Android studi…

svg: svg预定义的形状

SVG 有一些预定义的形状元素&#xff0c;可被开发者使用和操作&#xff1a;矩形 <rect>圆形 <circle>椭圆 <ellipse>线 <line>折线 <polyline>多边形 <polygon>路径 <path> 矩形 <rect x"20" y"20" width&qu…

grafana美人鱼_编码美人鱼–我如何从海洋生物学家转到前端开发人员

grafana美人鱼I have wanted to share my story for a while, but I didn’t know exactly how to start, or even what name to give it. 我想分享我的故事一段时间&#xff0c;但我不知道确切的开头&#xff0c;甚至不知道用什么名字。 But recently I was talking with som…

Android拍照得到全尺寸图片并进行压缩/拍照或者图库选择 压缩后 图片 上传

http://www.jb51.net/article/77223.htm https://www.cnblogs.com/breeze1988/p/4019510.html