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

 

猜你喜欢

转载自www.cnblogs.com/zhaopp/p/11970454.html