Solidity 语言有两类和状态读写有关的函数类型,一类是 view 函数(也称为视图函数),另一类是 pure 函数(也称为纯函数)。他们的区别是 view 函数不修改状态,pure 函数即不修改状态也不读取状态。

view 函数

可以将函数声明为 view 函数类型,这种情况下函数保证不修改状态。

如果编译器的 EVM 目标是拜占庭或更新的(默认),则在调用 view 函数时使用操作码 STATICCALL,这将强制状态在执行EVM时保持不变。对于库 view 函数使用了 DELEGATECALL,因为没有组合 DELEGATECALLSTATICCALL。这意味着库 view 函数没有防止状态修改的运行时检查。这应该不会对安全性产生负面影响,因为库代码通常在编译时已知,而静态检查器执行编译时检查。

下面的语句被认为是在修改状态:

  1. 修改状态变量;
  2. 触发事件;
  3. 创建其他合约;
  4. 使用 selfdestruct
  5. 通过调用发送以太币;
  6. 调用任何未标记 viewpure 的函数;
  7. 使用低级调用;
  8. 使用包含某些操作码的内联汇编。
// 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,这不能保证状态没有被读取,但至少它没有被修改。

除了上面解释的状态修改语句列表,下面的语句被认为是读取状态的:

  1. 从状态变量中读取;
  2. 访问 address(this).balanceaddress.balance
  3. 访问 block, tx, msg 的任何成员(除了 msg.sigmsg.data);
  4. 调用任何未标记为 pure 的函数;
  5. 使用包含某些操作码的内联汇编。
// 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() 函数在发生错误时恢复潜在的状态变化。

恢复状态变化不被认为是一种“状态修改”,因为只有在以前没有 viewpure 限制的代码中对状态所做的更改才会被恢复,并且该代码可以选择捕获 revert 而不传递它。

这种行为也符合 STATICCALL 操作码。

在 EVM 级别不可能阻止函数读取状态,只能阻止它们写入状态(即只有 view 可以在 EVM 级别强制执行,而pure 不能)。

在 0.5.0 版本之前,编译器没有为 pure 函数使用 STATICCALL 操作码。这允许通过使用无效的显式类型转换在 pure 函数中修改状态。通过对 pure 函数使用 STATICCALL,在 EVM 级别上可以防止对状态的修改。

在 0.4.17 版本之前,编译器没有强制 pure 函数不读取状态。这是一个编译时类型检查,可以规避做无效的合约类型之间的显式转换,因为编译器可以验证合约的类型不做状态改变操作,但不能在运行时检查调用合约的实际类型。

Solidity语言详解——view和pure函数的使用区别相关推荐

  1. Solidity语言详解

    Solidity语言学习学习总结 文章目录 Solidity语言学习学习总结 一.合约文件剖析 1.1一个合约文件的结构如下: 1.2合约的引入import 1.3引入状态变量.函数.事件.函数修改器 ...

  2. c语言霍夫曼函数,使用C语言详解霍夫曼树数据结构

    1.基本概念 a.路径和路径长度 若在一棵树中存在着一个结点序列 k1,k2,--,kj, 使得 ki是ki+1 的双亲(1<=i 从 k1 到 kj 所经过的分支数称为这两点之间的路径长度,它 ...

  3. smali语言详解之一般/构造方法(函数)的声明与返回值关键字

    smali语言详解之一般/构造方法(函数)的声明与返回值关键字 一. smali语言的方法声明格式 .method与.end method成对出现,类似于java中的花括号 1.1.非静态的一般方法 ...

  4. c语言getline函数什么意思,详解C++ cin.getline函数

    cin 虽然可以使用 cin 和 >> 运算符来输入字符串,但它可能会导致一些需要注意的问题. 当 cin 读取数据时,它会传递并忽略任何前导白色空格字符(空格.制表符或换行符).一旦它接 ...

  5. php打印出函数的内容吗,PHP打印函数集合详解以及PHP打印函数对比详解(精)

    1 echo();2 print();3 die();4 printf();5 sprintf();6 print_r();7 var_dump(); 1 echo() 可以同时输出多个字符串,可以多 ...

  6. c++指针详解_c语言详解sizeof

    一.sizeof的概念 sizeof是C语言的一种单目操作符,如C语言的其他操作符++.--等. 它并不是函数. sizeof操作符以字节形式给出了其操作数的存储大小. 操作数可以是一个表达式或括在括 ...

  7. python中get函数是什么意思_详解python中get函数的用法(附代码)_后端开发

    strncmp函数用法详解_后端开发 strncmp函数为字符串比较函数,其函数语法为"int strncmp ( const char * str1, const char * str2, ...

  8. 如何用c语言编写stm32的程序吗,STM32入门C语言详解

    <STM32入门C语言详解>由会员分享,可在线阅读,更多相关<STM32入门C语言详解(6页珍藏版)>请在人人文库网上搜索. 1.最新 料推荐阅读 flash : 芯片内部存储 ...

  9. php simplexml_load_file 详解,php中simplexml_load_file函数用法实例讲解

    php中simplexml_load_file函数用法实例讲解 发布于 2015-02-07 06:53:40 | 136 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文 ...

  10. python scatter参数详解_Python 中 scatter 函数参数及用法详解

    Python 中 scatter 函数参数及用法详解 Python 中 scatter 函数参数及用法详解 这里有新鲜出炉的 Python 教程, 程序狗速度看过来! Python 编程语言 Pyth ...

最新文章

  1. leetcode-C语言代码练习
  2. c++学习笔记之类模板
  3. 云HBase内核解析
  4. c语言 字符型数据如何输入,scanf()函数如何输入字符型数据?
  5. xcode6 使用MJRefresh
  6. Python_Tika
  7. awstats日志分析小结
  8. d3.js 旋转图形_PROE、Creo绘制手轮图形案例,二维草图绘制练习项目
  9. vuecli3代码压缩混淆使用uglifyjs压缩JS
  10. 解决 npm i 时出现npm ERRcode EINTEGRITY npm ERR sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+I
  11. python国际象棋小游戏代码_用Python编写一个国际象棋AI程序
  12. RS232通信协议详解
  13. Unity Camera Filed Of View
  14. uniapp开发微信小程序-软考刷题小程序
  15. 写一个PE的壳_Part 2:ASLR+修复输入表(IAT)+重定位表支持(.reloc)
  16. 利用snowfall.jquery.js实现爱心满屏飞
  17. 使用python将txt格式的数据转换为csv格式,读取csv数据前几行
  18. 数字逻辑练习题(一)
  19. 几幅图教你区分数字地、模拟地、电源地、单点接地
  20. mysql ssl 2026_解决连接到 Amazon RDS for MySQL 或 Aurora 实例时的 ERROR 2026 SSL 连接错误...

热门文章

  1. 『现学现忘』Git后悔药 — 34、git commit --amend 命令
  2. git commit 参数详解 --amend
  3. visual C#(二十五)实现UWP应用的用户界面
  4. 【渗透技巧】pop3协议渗透
  5. 什么是mysql 的冗余备份_什么是数据库中的“数据冗余”?
  6. CodeForces-721A-One-dimensional Japanese Crossword
  7. 利用python-pptx包批量修改ppt格式
  8. LINUX环境下安装MySQL数据库
  9. linux网易云打不开的问题
  10. JavaScript实现富文本编辑器