solidity智能合约开发七:高级理论

1、随机数

pragma solidity >=0.4.22 <0.5.0;

contract random{
    //生成100以内的随机数,msg.sender可以用别的全局变量替代
    function test1() returns(uint){
        return uint256(keccak256(now,msg.sender))%100;
    }

    uint256 win = 50;
    //百分之50的概率为正(可以模拟骰子大小)
//通过win的调节可以调整正负的概率
    function test2() returns(bool){
        return uint256(keccak256(now,msg.sender))%100 <50;
    }
    
}

2、静态library库

在Solidity中,与合约有些不同,Library不能处理ether。你可以把它当作一个EVM中的单例,又或者是一个部署一次后不再部署,然后能被做任意其它合约调用的公共代码。

这带来的一个显然好处是节省大量的gas(当然也可以减少重复代码对区块链带来的污染),因为代码不用一而再,再而三的部署,不同的合约可以依赖于同一个已部署的合约。

事实上,多个合约依赖于一个现存的代码,可以让营造一个更安全的环境。因为一方面这些方面有良好的代码审查(比如,Zepelin所做的伟大的工作),以及这些代码经过线上实际运行的验证。

pragma solidity >=0.4.22 <0.5.0;

library CounterLib {
    //没有普通属性,只能有结构体
    struct Counter { uint i; }
    //Counter storage self 是默认的第一个函数
    function incremented(Counter storage self,uint a) returns (uint) {
        self.i = self.i + a;
        return self.i;
    }
}
contract CounterContract {
//引入库中的结构体
    using CounterLib for CounterLib.Counter;
//定义
    CounterLib.Counter counter;

    function increment(uint a) view returns (uint) {
         //通过定义的结构体调用库中的函数
         counter.incremented(a);
         return counter.i;
    }
}
library SafeMathLib {
  function times(uint a, uint b) returns (uint) {
    uint c = a * b;
    assert(a == 0 || c / a == b);
    return c;
  }

  function minus(uint a, uint b) returns (uint) {
    assert(b <= a);
    return a - b;
  }

  function plus(uint a, uint b) returns (uint) {
    uint c = a + b;
    assert(c>=a && c>=b);
    return c;
  }

  function assert(bool assertion) private {
    if (!assertion) throw;
  }
}

contract libraryTest{
//引入库,uint作为第一个参数的类型
    using SafeMathLib for uint;
        
    function test(uint a,uint b) view returns(uint,uint){
        //调用
        uint jia = a.plus(b);
        uint jian = a.minus(b);
        return (jia,jian);
    }
}

3、interface—接口的妙用

pragma solidity >=0.4.22 <0.5.0;

contract number1{
    
    mapping(address => uint) addrMap1;
    
    function setNum1(uint _num) public {
        addrMap1[msg.sender] = _num;
    }
    
    function getNum(address _addr) public view returns(uint){
        return addrMap1[_addr];
    }
    
}


contract number2{
    
    mapping(address => uint) addrMap2;
    
    function setNum2(uint _num) public {
        addrMap2[msg.sender] = _num;
    }
    
    function getNum(address _addr) public view  returns(uint){
        return addrMap2[_addr];
    }
    
}

contract numberInterface{
    function getNum(address _addr) public view returns(uint);
}


contract interfaceTest{
    
    function test(address _addr) public view returns(uint,address){
      //接口的使用,同一个接口接收了不同的合约地址,接口的参数为实现接口的合约的合约地址 
       numberInterface f = numberInterface(_addr);
        return (f.getNum(msg.sender),msg.sender);
    }
    
}

4、call函数——底层的调用

  • 在一个合约里调用另一个合约——通过构造器构造实例调用,相当于外部调用
pragma solidity >=0.4.22 <0.5.0;

contract cat{
    
    uint public c = 100;
    
    function test(uint a) returns(uint){
        c = a;
        return c;
    }
    
}

contract animal{
    //定义一个cat合约
    cat mycat;
    //构造器,发布的时候需要填入cat合约地址
    constructor(address _catAddr){
        mycat = cat(_catAddr);
    }
    
    function getCat(uint a) returns(uint i){
        return mycat.test(a);
    }
}
  • 在一个合约里调用另一个合约——通过call调用,地址调用
    1、call是底层调用,只能返回true false;
contract cat{
    
    uint public c = 100;
    
    function test(uint a) returns(uint){
        c = a;
       //msg.sender为animal1合约地址
        address addr = msg.sender;
        return c;
    }
    
}

contract animal1{
    
    address catAddr;
    constructor(address _catAddr){
        catAddr = _catAddr;
    }
    
    function getCat(uint a) returns(bool){
        return catAddr.call(bytes4(sha3("test(uint256)")),a);
    }

}
  • 在一个合约里调用另一个合约——通过delegatecall调用
    1、通过delegatecall调用,相当于放入了本合约内部来使用,所以应用的全局变量要保持一致,如下uint public c
contract cat{
    //这个值不会改变
    uint public c = 100;
    
    function test(uint a) returns(uint){
        c = a;
        //这个值不会改变
        address addr = msg.sender;
        return c;
    }
    
}

contract animal2{
//会改变这个值
    uint public c = 0;
    
    address catAddr;
    constructor(address _catAddr){
        catAddr = _catAddr;
    }
    
    function getCat(uint a) returns(bool){
        return catAddr.delegatecall(bytes4(sha3("test(uint256)")),a);
    }    
}

5、继承带参构造函数

1、继承时,默认的调用了父合约的空的构造函数
2、如果父合约的构造函数带参,则需要实例化父类的带参构造函数,
如下

pragma solidity >=0.4.22 <0.5.0;


contract father{
    uint public money;
    uint public height;
    
    constructor(uint a,uint b){
        money = a;
        height = b;
    }
    
}

contract son is father{
    //实例化父合约的带参构造函数
    constructor(uint a,uint b) father(a,b){
        money = a;
        height = b;
    }
    
}

6、浅析事件event的用途

1、事件的触发

pragma solidity >=0.4.22 <0.5.0;

contract eventTest{
     //事件定义  
    event senderLogger(address);
    event valueLogger(uint);
    
//回调函数,给合约转账
    function() payable{
        senderLogger(msg.sender);
        valueLogger(msg.value);
    }
      
}

下图中的logs存储在区块头,from指的是转账地址,to是接收地址,topic指的是事件唯一标识,args是事件参数

solidity智能合约开发七:高级理论_第1张图片
image.png

2、事件的监听
待补充

7、合约嵌入内联汇编 solidity assembly

  • 在solidity中执行汇编
  • 优化效率,减少gas(不一定每次都能减少)
  • 完成solidity完成不了的功能
solidity智能合约开发七:高级理论_第2张图片
image.png

你可能感兴趣的:(solidity智能合约开发七:高级理论)