前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【易错概念】Solidity语法constant/view/pure关键字定义

【易错概念】Solidity语法constant/view/pure关键字定义

作者头像
辉哥
发布2018-09-27 10:13:54
1.8K0
发布2018-09-27 10:13:54
举报

1,摘要

通过本文学习,熟悉了解以太坊智能合约语言Solidity语法中constant,view,pure的区别。

2,区别总结

在Solidity中constant,view,pure三个函数修饰词的作用是告诉编译器,函数不改变/不读取状态变量,这样函数执行就可以不消耗gas了(是完全不消耗!),因为不需要矿工来验证。 在Solidity v4.17之前,只有constant,后来有人嫌constant这个词本身代表变量中的常量,不适合用来修饰函数,所以将constant拆成了view和pure。 view的作用和constant一模一样,可以读取状态变量但是不能改; pure则更为严格,pure修饰的函数不能改也不能读状态变量,否则编译通不过。 大家可以运行以下测试代码来加深这3个关键字的理解。

contract constantViewPure{
    string name;
    uint public age;
    
    function constantViewPure() public{
        name = "liushiming";
        age = 29;
    }
    
    function getAgeByConstant() public constant returns(uint){
        age += 1;  //声明为constant,在函数体中又试图去改变状态变量的值,编译会报warning, 但是可以通过
        return age;  // return 30, 但是!状态变量age的值不会改变,仍然为29!
    } 
    
    function getAgeByView() public view returns(uint){
        age += 1; //view和constant效果一致,编译会报warning,但是可以通过
        return age; // return 30,但是!状态变量age的值不会改变,仍然为29!
    }
    
    function getAgeByPure() public pure returns(uint){
        return age; //编译报错!pure比constant和view都要严格,pure完全禁止读写状态变量!
        return 1;
    }
}

3,详细描述

3.1 Constant 状态变量

状态变量可以被声明为 constant。在这种情况下,只能使用那些在编译时有确定值的表达式来给它们赋值。 任何通过访问 storage,区块链数据(例如 now, this.balance 或者 block.number)或执行数据( msg.gas ) 或对外部合约的调用来给它们赋值都是不允许的。 在内存分配上有边界效应(side-effect)的表达式是允许的,但对其他内存对象产生边界效应的表达式则不行。 内建(built-in)函数 keccak256,sha256,ripemd160,ecrecover,addmod 和 mulmod 是允许的(即使他们确实会调用外部合约)。

允许带有边界效应的内存分配器的原因是这将允许构建复杂的对象,比如查找表(lookup-table)。 此功能尚未完全可用。

编译器不会为这些变量预留存储,它们的每次出现都会被替换为相应的常量表达式(这将可能被优化器计算为实际的某个值)。

不是所有类型的状态变量都支持用 constant 来修饰,当前支持的仅有值类型和字符串。

pragma solidity ^0.4.0;

contract C {
    uint constant x = 32**22 + 8;
    string constant text = "abc";
    bytes32 constant myHash = keccak256("abc");
}

3.2 View 函数

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

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

  1. 修改状态变量。
  2. 产生事件
  3. 创建其它合约
  4. 使用 selfdestruct
  5. 通过调用发送以太币。
  6. 调用任何没有标记为 view 或者 pure 的函数。
  7. 使用低级调用。
  8. 使用包含特定操作码的内联汇编。
pragma solidity ^0.4.16;

contract C {
    function f(uint a, uint b) public view returns (uint) {
        return a * (b + 42) + now;
    }
}

注解:

  • onstant 是 view 的别名。
  • Getter 方法被标记为 view。
  • 编译器没有强制 view 方法不能修改状态。

3.3 Pure 函数

函数可以声明为 pure ,在这种情况下,承诺不读取或修改状态。

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

  • 读取状态变量。
  • 访问 this.balance 或者 <address>.balance。
  • 访问 block,tx, msg 中任意成员 (除 msg.sig 和 msg.data 之外)。
  • 调用任何未标记为 pure 的函数。
  • 使用包含某些操作码的内联汇编。
pragma solidity ^0.4.16;

contract C {
    function f(uint a, uint b) public pure returns (uint) {
        return a * (b + 42);
    }
}

警告

  • 编译器没有强制 pure 方法不能读取状态。

4,参考

(1)合约官网参考 (2)Solidity constant view pure关键字的区别与联系

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.09.18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1,摘要
  • 2,区别总结
  • 3,详细描述
    • 3.1 Constant 状态变量
      • 3.2 View 函数
        • 3.3 Pure 函数
        • 4,参考
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档