• 03 进阶篇


    3高级语法

    自动推导类型

    为了方便,并不总是需要明确指定一个变量的类型,编译器会通过第一个向这个对象赋予的值的类型来进行推断.

    例如:

    uint24 x = 0x123; var y = x;

    需要特别注意的是,由于类型推断是根据第一个变量进行的赋值。所以下面的代码将是一个无限循 环,因为⼀一个uint8的i的将小于2000。

    for (var i = 0; i < 2000; i++) { //uint8 -> 255 //越界归0 //无限循环 }

    全局变量/函数

    区块和交易的属性:

    代码:

     

     1 pragma solidity ^0.4.24;
     2 contract Test {
     3  4     bytes32 public blockhash;
     5     address public coinbase;
     6     uint public difficulty;
     7     uint public gaslimit;
     8     uint public blockNum;
     9     uint public timestamp;
    10     bytes public calldata;
    11     uint public gas;
    12     address public sender;
    13     bytes4 public sig;
    14     uint public msgValue;
    15     uint public now;
    16     uint public gasPrice;
    17     address public txOrigin;
    18     
    19 function tt (){
    20         //给定区块号的哈希值,只支持最近256个区块,且不包含当前区块
    21         blockhash = block.blockhash(block.number - 1);
    22         coinbase = block.coinbase ;//当前块矿工的地址。
    23         difficulty = block.difficulty;//当前块的难度。
    24         gaslimit = block.gaslimit;// (uint)当前块的gaslimit。
    25         blockNum = block.number;// (uint)当前区块的块号。
    26         timestamp = block.timestamp;// (uint)当前块的时间戳。
    27         calldata = msg.data;// (bytes)完整的调⽤用数据(calldata)。
    28         gas = msg.gas;// (uint)当前还剩的gas。
    29         sender = msg.sender; // (address)当前调用发起人的地址。
    30         sig = msg.sig;// (bytes4)调用数据的前四个字节(函数标识符)。
    31         msgValue = msg.value;// (uint)这个消息所附带的货币量,单位为wei。
    32         now = now;// (uint)当前块的时间戳,等同于block.timestamp
    33         gasPrice = tx.gasprice;// (uint) 交易的gas价格。
    34         txOrigin = tx.origin;// (address)交易的发送者(完整的调用链)  
    35     }
    36 }
    37  
    View Code
    
    

    货币单位

    ⼀一个字面量的数字,可以使用后缀 wei , finney , szabo 或 ether 来在不同面额中转换; 不含任何后缀的默认单位是 wei 。如1 ether == 1000 finney 的结果是 true 。

    代码:

     

     1 pragma solidity ^0.4.24;
     2 contract EthUnit{
     3     uint  a = 1 ether;
     4     uint  b = 10 ** 18 wei;
     5     uint  c = 1000 finney;
     6     uint  d = 1000000 szabo;
     7 function f1() constant public returns (bool){
     8     return a == b;
     9 }
    10 11 function f2() constant public returns (bool){
    12     return a == c;
    13 }
    14 15 function f3() constant public returns (bool){
    16     return a == d;
    17 }
    18 19  function f4() constant public returns (bool){
    20         return 1 ether == 100 wei;
    21     }
    22   }
    
    

    时间单位

    seconds,minutes,hours,days,weeks,years均可做为后缀,默认是seconds为单位。 1 = 1 seconds 1 minutes = 60 seconds 1 hours = 60 minutes 1 days = 24 hours 1 weeks = 7 days 1 years = 365 days

    代码:

     

     1 pragma solidity ^0.4.24;
     2 contract TimeUnit{
     3     function f1() pure public returns (bool) {
     4         return 1 == 1 seconds;
     5     }
     6     
     7 function f2() pure public returns (bool) {
     8     return 1 minutes == 60 seconds;
     9 }
    10 11 function f3() pure public returns (bool) {
    12     return 1 hours == 60 minutes;
    13 }
    14 15 function f4() pure public returns (bool) {
    16     return 1 days == 24 hours;
    17 }
    18 19 function f5() pure public returns (bool) {
    20     return 1 weeks == 7 days;
    21 }
    22  function f6() pure public returns (bool) {
    23         return 1 years == 365 days;
    24     }
    25 }
    26  
    
    

    事件(event)

     

     1 pragma solidity ^0.4.24;
     2 contract evnetTest{
     3     mapping(address=>uint256)public personToMoney;
     4 //定义一个时间事件,时间事件是一个语句,在后面要加分号,与结构体不同;
     5 /*
     6 1.定义一个时间事件,使用圆括号,后面加分号
     7 2.使用emit关键字
     8 3.在web3调用时可以监听到事件
     9 4.相当于日志
    10 */
    11 event playEnent(address,uint256,uint256);
    12 13 function paly()public payable
    14 {
    15     require(msg.value==100);
    16     personToMoney[msg.sender]=msg.value;
    17     
    18     //emit:关键字表示发射时间;出发触发事件
    19     emit playEnent(msg.sender,msg.value,block.timestamp);
    20 }
    21 22 function getBalance()public view returns(uint256){
    23     return address(this).balance;
    24 }
    25 }
    
    

    结果:

    访问函数

    -编译器为自动为所有的 public的状态变量 创建访问函数。下面的合约例子中,编译器会生成一个名叫data的无参,返回值是uint的类型的值data。状态变量的初始化可以在定义时完成。

    -访问函数有外部(external)可见性。如果通过内部(internal)的方式访问,比如直接访问,你可以直接把它当一个变量进行使用,但如果使用外部(external)的方式来访问,如通过this.,那么它必须通过函数的方式来调用。

      1.加public的常态变量,solidity会自动的生成一个同名的访问函数
     2.在合约内部使用这个状态变量的时候,直接当变量使用即可
     3.在合约外部访问这个public变量(data ),就需要使用xx .data()形式

    代码:

     1 pragma solidity ^0.4.24;
     2  3  contract test {
     4      uint256 public data =200;
     5  function getData()public view returns(uint256){
     6      return data;
     7  } 
     8  
     9  //this 代表合约本身,如果在合约内部使用this自身的方法的话,相当于外部调用
    10  function getData1()public view returns(uint256){
    11      return this.data();
    12  }
    13   }
    14  contract test1{
    15  function getData()public returns(uint256){
    16   test t=new test();
    17  return t.data();
    18   }
    19  }
    20  
    21 
    22  

    修饰器

    程序运行流程

    修改器(Modifiers)可以用来轻易的改变一个函数的行为。⽐比如⽤用于在函数执行前检查某种前置条件。 修改器是一种合约属性,可被继承,同时还可被派生的合约重写(override)。下面我们来看一段示例代 码:

    1.可以传递参数
    2._;
    3.放到是函数后面
     1 pragma solidity ^0.4.24;
     2  3 contract ModifyTest{
     4     uint256 public value;
     5     address public owner;
     6     //构造函数
     7     constructor()public{
     8         owner=msg.sender;
     9     }
    10  
    11     //修饰器其器器,可以进行传参
    12     modifier onlyOwner{
    13     require(msg.sender==owner);
    14     //_;表示这个修饰其器所修饰的函数代码
    15     _;
    16     
    17     }
    18     
    19     //使用修饰器,在将仅管理员可以执行的限定放到函数外面
    20     function changeValue(uint256 _value)onlyOwner public{
    21         //传参,一般前面加下滑县
    22         value=_value;
    23     }    
    24 }
    25
    View Code
     

    错误处理

    传统方法:采用 throw 和 if ... throw 模式(已过时),例如合约中有一些功能,只能被授权为拥有者的 地址才能调用

    if(msg.sender != owner) { throw; }

    等价于如下任意一种形式:

    if(msg.sender != owner) { revert(); }

    assert(msg.sender == owner);

    require(msg.sender == owner);

     

    代码:

     1 pragma solidity ^0.4.24;
     2 contract HasAnOwner {
     3     address public owner;
     4     uint public a ;
     5 constructor() public {
     6     owner = msg.sender;
     7 }
     8  9 function useSuperPowers()  public { 
    10     require(msg.sender == owner);
    11     /*
    12     if (msg.sender != owner){
    13         throw;
    14     }
    15     */
    16     
    17     a = 10;
    18    // do something only the owner should be allowed to do
    19 }
    20 }
    View Code

    合约

    合约的创建:

     

     1 pragma solidity ^0.4.24;
     2  3   contract C1{
     4       uint256 public value;
     5       constructor (uint256 _input)public{
     6           value=_input;
     7       }
     8       function getValue()public pure returns(uint256){
     9           return 100;
    10       }
    11       
    12   }
    13   contract C2{
    14       C1 public c1;
    15       C1 public c11;
    16       function getValue1()public returns(uint256){
    17           //创建一个合约,返回一个地址
    18       address addr=new C1(10 );
    19      // 地址需要显示的转换为特定类型,才可以正常使用
    20      c1= C1(addr);
    21      return c1.getValue();
    22       
    23   }    
    24   
    25   function getValue2()public returns(uint256){
    26       //定义的时候,同时完成转换
    27       c11=new C1(20 );
    28       return c11.getValue();
    29   } 
    30   
    31   C1 public c13;
    32   function getValue3(address _addr)public returns(uint256){
    33      //当传入地址是时,需要显示的转换,否则不可以用
    34       c13=C1(_addr);
    35       return c13.getValue();
    36   }
    37     }
    
    

    合约继承 is关键字;最远继承

     1 pragma solidity ^0.4.0;
     2 
     3 contract Base1{
     4 
     5   function data() pure returns(uint){
     6 
     7      return 1; 
     8 
     9   }
    10 
    11 }
    12 
    13 contract Base2{
    14 
    15    function data() pure returns(uint){
    16 
    17      return 2;
    18 
    19    }
    20 
    21 }
    22 
    23 //继承base2的data方法
    24 
    25 contract MostDerived1 is Base1, Base2{ }
    26 
    27 //继承base1的data方法
    28 
    29 contract MostDerived2 is Base2, Base1{
    30 
    31 }
    32 
    33 可以指定某个父合约
    34 
    35 pragma solidity ^0.4.0;
    36 
    37 contract Base1{
    38 
    39    function data() pure returns(uint){
    40 
    41      return 1;
    42 
    43    }
    44 
    45 }
    46 
    47 contract Base2{
    48 
    49      function data() pure returns(uint){
    50 
    51      return 2;
    52 
    53    }
    54 
    55 }
    56 
    57 contract MostDerived1 is Base1, Base2{
    58 
    59     function mydata() pure returns(uint){
    60 
    61        return Base1.data();
    62 
    63      }
    64 
    65 }
    66 
    67 contract MostDerived2 is Base2, Base1{
    68 
    69      function mydata() pure returns(uint){ return Base2.data();
    70 
    71   }
    72 
    73 }

    外部调用

     1  pragma solidity ^0.4.24;​
     2 
     3 contract InfoFeed{
     4 
     5 function info()public payable returns(uint256 ret){
     6      return 42;
     7  }
     8  function getBalance()public view returns(uint256){
     9      return address(this).balance;
    10  }
    11   }  
    12 13  contract Consumer{
    14      InfoFeed feed;
    15      function setFeed(address addr)public{
    16          feed=InfoFeed(addr);
    17      }
    18      function callFeed()public{
    19      //给Info合约转账10wei ,汽油费上线上限800
    20      //合约转账语法
    21      feed.info.value(10).gas(800)();
    22  }
    23  
    24  function()payable public{
    25      
    26  }
    27  
    28 function getBalance()public view returns(uint256){
    29      return address(this).balance;
    30  } 
    31   }
    View Code

    元祖

    return(a, b, c) solidity无法返回自定义的数据结构,所以若想返回一个自定义结构的数据,需要在函数中一次返回多个值,即元组。元组是一个数据集合,类似于字典但是无法修改数据,使用圆括号包括多种数据类型。

    1  //1. 返回⼀一个Student结构
    2     function getLily() public view returns(string, uint, uint, string) 
    3 {
    4         Student memory lily = Students[0];
    5         return (lily.name, lily.age, lily.score, lily.sex);
    6     }
    7 }
    View Code

    内置数学函数

    ripemd160,keccak256,addmod,ecrecover

    代码:

     1 pragma solidity ^0.4.24;
     2  3 contract operation{
     4 function Hash()public pure returns(bytes32){
     5     //先编码。后运算
     6     bytes memory v1=abi.encodePacked("hello",uint256(1),"world");
     7     return keccak256(v1);
     8     }
     9 10 function Test()public pure returns(bytes32){
    11     bytes32 hash=sha3("hello",uint256(1),"world");//以前的用法,不推荐使用了,和keccak256效果一样
    12     return keccak256("hello",uint256(1),"world");
    13   }
    14 }
    View Code

    delete

    delete操作符可以用于任何变量量,将其设置成默认值 如果对动态数组使用delete,则删除所有元素,其长度变为0 如果对静态数组使用delete,则重置所有索引的值

    1.new 创建对象、合约
    2.delete操作符可以用于任何变量,将其设置为默认值
    3.如果对动态数组使用delete,删除所有的元素,其长度变为零
    4.如果读静态数组使用delete,则重置所有的索引值(根据元素类型)
    5.如果对map 类型使用delete,什么都不会发生
    6.但如果对map 类型中的一个兼职键值使用delete,则删除与该键相关的值

     

     1 pragma solidity ^0.4.24;
     2 contract Delet{
     3 //1.string
     4 string public str ="hello";
     5 function deleteDtring()public{
     6     //删除之后n便变为0
     7     delete str;
     8 }
     9 10 //2.array,对于固定长度的数组。则会想删除每个元素的值,但是数组的元素不变
    11 int256[10] public arr=[1,2,3,4,5];
    12 function deleteFixArray()public{
    13     delete arr;
    14 }
    15 16 //3.array new 
    17 uint256[]  arr1=new uint256[](10);
    18 function setArray()public{
    19     for (uint256 i=0; i< arr1.length; i++){
    20         arr1[i]=i;
    21     }
    22     
    23 }
    24 function deleteArray()public{
    25     delete arr1;
    26     
    27 }
    28 function getArray()public view returns(uint256[]){
    29     return arr1;
    30 }
    31 32 //mapping
    33 mapping(uint256=>string)m1;
    34 function setMaping()public{
    35     m1[1]="hello";
    36     m1[2]="world";
    37 }
    38 function deleteMapping()public{
    39     //delete m1;不允许,只能删除键值内容
    40     
    41     delete m1[1];
    42 }
    43 function getMapping(uint256 _index)public view returns(string){
    44     return m1[_index];
    45     }
    46 }
    View Code
    
    

     补充:被internal修饰的函数,可以被内部合约调用,也可以被子合约调用,外部合约无法调用

    ECR20:代币编写规范   推荐:https://www.jianshu.com/p/a5158fbfaeb9

     

    每天的价值就是不停息的前进!!!
  • 相关阅读:
    【C#语言规范版本5.0学习】1.5类和对象(一)
    【C#语言规范版本5.0学习】1.5类和对象(二、类的方法)
    【C#语言规范版本5.0学习】1.4语句
    mac 安装docker
    Laravel 操作指令
    php 查看接口运行时间
    MySql 按日期条件查询数据
    Laravel操作上传文件的方法
    统计数据表中某个字段的值大于2条的数据
    循环中合并数组
  • 原文地址:https://www.cnblogs.com/zhaopp/p/11970454.html
Copyright © 2020-2023  润新知