Solidity语言详解——view和pure函数的使用区别
Solidity 语言有两类和状态读写有关的函数类型,一类是 view 函数(也称为视图函数),另一类是 pure 函数(也称为纯函数)。他们的区别是 view 函数不修改状态,pure 函数即不修改状态也不读取状态。
view 函数
可以将函数声明为 view
函数类型,这种情况下函数保证不修改状态。
如果编译器的 EVM 目标是拜占庭或更新的(默认),则在调用
view
函数时使用操作码STATICCALL
,这将强制状态在执行EVM时保持不变。对于库view
函数使用了DELEGATECALL
,因为没有组合DELEGATECALL
和STATICCALL
。这意味着库view
函数没有防止状态修改的运行时检查。这应该不会对安全性产生负面影响,因为库代码通常在编译时已知,而静态检查器执行编译时检查。
下面的语句被认为是在修改状态:
- 修改状态变量;
- 触发事件;
- 创建其他合约;
- 使用
selfdestruct
; - 通过调用发送以太币;
- 调用任何未标记
view
或pure
的函数; - 使用低级调用;
- 使用包含某些操作码的内联汇编。
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.9.0;contract C {function f(uint a, uint b) public view returns (uint) {return a * (b + 42) + block.timestamp;}
}
constant
曾经是view
的别名,但在0.5.0版本中删除了这一点。
Getter 方法被自动标记为
view
。
在 0.5.0 版本之前,编译器没有为
view
函数使用STATICCALL
操作码。这样可以通过使用无效的显式类型转换来修改view
函数中的状态。通过对view
函数使用STATICCALL
,在EVM级别上可以防止对状态的修改。
pure 函数
在保证不读取或修改状态的情况下,函数可以被声明为 pure
函数。特别是,在编译时只给出函数输入和msg.data
,但又不知道当前区块链状态的情况下,建议使用 pure
函数。这意味着对 immutable
变量的读取可以是非纯操作。
如果编译器的 EVM 目标是拜占庭或更新的(默认),则使用操作码
STATICCALL
,这不能保证状态没有被读取,但至少它没有被修改。
除了上面解释的状态修改语句列表,下面的语句被认为是读取状态的:
- 从状态变量中读取;
- 访问
address(this).balance
或address.balance
; - 访问
block
,tx
,msg
的任何成员(除了msg.sig
和msg.data
); - 调用任何未标记为
pure
的函数; - 使用包含某些操作码的内联汇编。
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.9.0;contract C {function f(uint a, uint b) public pure returns (uint) {return a * (b + 42);}
}
纯函数可以使用 revert()
和 require()
函数在发生错误时恢复潜在的状态变化。
恢复状态变化不被认为是一种“状态修改”,因为只有在以前没有 view
或 pure
限制的代码中对状态所做的更改才会被恢复,并且该代码可以选择捕获 revert
而不传递它。
这种行为也符合 STATICCALL
操作码。
在 EVM 级别不可能阻止函数读取状态,只能阻止它们写入状态(即只有
view
可以在 EVM 级别强制执行,而pure
不能)。
在 0.5.0 版本之前,编译器没有为
pure
函数使用STATICCALL
操作码。这允许通过使用无效的显式类型转换在pure
函数中修改状态。通过对pure
函数使用STATICCALL
,在 EVM 级别上可以防止对状态的修改。
在 0.4.17 版本之前,编译器没有强制
pure
函数不读取状态。这是一个编译时类型检查,可以规避做无效的合约类型之间的显式转换,因为编译器可以验证合约的类型不做状态改变操作,但不能在运行时检查调用合约的实际类型。
Solidity语言详解——view和pure函数的使用区别相关推荐
- Solidity语言详解
Solidity语言学习学习总结 文章目录 Solidity语言学习学习总结 一.合约文件剖析 1.1一个合约文件的结构如下: 1.2合约的引入import 1.3引入状态变量.函数.事件.函数修改器 ...
- c语言霍夫曼函数,使用C语言详解霍夫曼树数据结构
1.基本概念 a.路径和路径长度 若在一棵树中存在着一个结点序列 k1,k2,--,kj, 使得 ki是ki+1 的双亲(1<=i 从 k1 到 kj 所经过的分支数称为这两点之间的路径长度,它 ...
- smali语言详解之一般/构造方法(函数)的声明与返回值关键字
smali语言详解之一般/构造方法(函数)的声明与返回值关键字 一. smali语言的方法声明格式 .method与.end method成对出现,类似于java中的花括号 1.1.非静态的一般方法 ...
- c语言getline函数什么意思,详解C++ cin.getline函数
cin 虽然可以使用 cin 和 >> 运算符来输入字符串,但它可能会导致一些需要注意的问题. 当 cin 读取数据时,它会传递并忽略任何前导白色空格字符(空格.制表符或换行符).一旦它接 ...
- php打印出函数的内容吗,PHP打印函数集合详解以及PHP打印函数对比详解(精)
1 echo();2 print();3 die();4 printf();5 sprintf();6 print_r();7 var_dump(); 1 echo() 可以同时输出多个字符串,可以多 ...
- c++指针详解_c语言详解sizeof
一.sizeof的概念 sizeof是C语言的一种单目操作符,如C语言的其他操作符++.--等. 它并不是函数. sizeof操作符以字节形式给出了其操作数的存储大小. 操作数可以是一个表达式或括在括 ...
- python中get函数是什么意思_详解python中get函数的用法(附代码)_后端开发
strncmp函数用法详解_后端开发 strncmp函数为字符串比较函数,其函数语法为"int strncmp ( const char * str1, const char * str2, ...
- 如何用c语言编写stm32的程序吗,STM32入门C语言详解
<STM32入门C语言详解>由会员分享,可在线阅读,更多相关<STM32入门C语言详解(6页珍藏版)>请在人人文库网上搜索. 1.最新 料推荐阅读 flash : 芯片内部存储 ...
- php simplexml_load_file 详解,php中simplexml_load_file函数用法实例讲解
php中simplexml_load_file函数用法实例讲解 发布于 2015-02-07 06:53:40 | 136 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文 ...
- python scatter参数详解_Python 中 scatter 函数参数及用法详解
Python 中 scatter 函数参数及用法详解 Python 中 scatter 函数参数及用法详解 这里有新鲜出炉的 Python 教程, 程序狗速度看过来! Python 编程语言 Pyth ...
最新文章
- leetcode-C语言代码练习
- c++学习笔记之类模板
- 云HBase内核解析
- c语言 字符型数据如何输入,scanf()函数如何输入字符型数据?
- xcode6 使用MJRefresh
- Python_Tika
- awstats日志分析小结
- d3.js 旋转图形_PROE、Creo绘制手轮图形案例,二维草图绘制练习项目
- vuecli3代码压缩混淆使用uglifyjs压缩JS
- 解决 npm i 时出现npm ERRcode EINTEGRITY npm ERR sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+I
- python国际象棋小游戏代码_用Python编写一个国际象棋AI程序
- RS232通信协议详解
- Unity Camera Filed Of View
- uniapp开发微信小程序-软考刷题小程序
- 写一个PE的壳_Part 2:ASLR+修复输入表(IAT)+重定位表支持(.reloc)
- 利用snowfall.jquery.js实现爱心满屏飞
- 使用python将txt格式的数据转换为csv格式,读取csv数据前几行
- 数字逻辑练习题(一)
- 几幅图教你区分数字地、模拟地、电源地、单点接地
- mysql ssl 2026_解决连接到 Amazon RDS for MySQL 或 Aurora 实例时的 ERROR 2026 SSL 连接错误...