美文网首页
Solidity基础语法

Solidity基础语法

作者: 暴走的K哥哥 | 来源:发表于2018-04-24 19:41 被阅读0次

    Solidity

    Solidity是编写智能合约的语言,运行在ethereum虚拟机上。语法类似于JS,它拥有异常机制,一旦出现异常,所有的执行都会被撤回,这是为了保证合约执行的原子性,避免中间状态出现的数据不一致。

    官方提供了IDE: remix
    下面看一个简单的合约的例子:

    pragma solidity ^0.4.9;
    contract Helloworld {
        function multi(uint a, uint b) returns (uint c) {
        uint result = a * b;
        return result;
        }
    }
    
    

    上面这个函数很简单,调用multi方法进行乘法运算。

    基础语法

    1.数据类型

    • address 以太坊地址的长度,20个字节
    • int/uint 变长的有符号或无符号整型。支持以8递增,uint8到uint256。uint 默认为uint256。
    • bool 布尔型
    • mapping 键值对映射关系,如mapping(address => uint)
    • struct 结构体,如下例子


    2.状态变量storage和局部变量memory

    两者区别很容易理解,memory可以理解为临时变量,不会记录在链上,而storage是永久存储的。

    • 变量定义时默认为storage,而作为函数参数时,默认为memory
    contract HelloWorld{
        
        //等价于 string storage public a;
        string public a;
    
        //参数等价于string memory _a
        function changeNum(string _a){
        }
        
        
    }
    
    
    • 当函数参数为memory类型时,相当于值传递,storage才是指针传递
    contract HelloWorld2{
        
        string public a;
        
        function HelloWorld2(){
            a = "abc";
        }
        
        
        function f(){
            changeNum(a);
        }
        
        function changeNum(string _a){
            bytes(_a)[0] = "d";
          //由于_a默认为memory,所以_a只是值传递,所以此时修改a的值是不成功的,输出还是abc
          //需要把函数参数修改为string storage _a,才能输出dbc
        }
    }
    
    
    • 将变量赋值给一个新变量时,新变量的类型由赋值给它的类型决定。
    function changeNum(string _a){
            //_a默认为memory类型,所以b也为memory
            string b = _a;
            bytes(_a)[0] = "d";
        }
    
    

    3.函数四种访问权限

    函数声明有public、private、internal和external四种访问权限

    • 1.函数默认声明为public,即可以以internal方式调用,也可以通过external方式调用。可以理解为能够被内部合约访问和外部合约访问。
    • 2.Internal声明的只允许通过internal方式调用,不能被外部合约。而external能够被外部合约访问。
    • 3.private和internal类似,都不能被外部合约访问,唯一的不同是private函数不能被子类调用,而internal可以。

    如下例子:

    contract FunctionTest{
        
        function publicFunc() {}
    
        function callFunc(){
            //以`internal`的方式调用函数
            publicFunc();
            
            //以`external`的方式调用函数
            this.publicFunc();
        }
        
        function internalFunc() internal{}
        
        function externalFunc() external{}
        
        
    }
    
    contract FunctionTest1 {
        function externalCall(FuntionTest ft){
            //调用另一个合约的外部函数
            ft.publicFunc();
            ft.externalFunc();
           //ft.internalFunc();调用失败,无法调用internal函数
        }
    }
    
    
    

    4.pure、view、constant三种函数定义

    当函数有返回值时,可以添加这三种定义,用这三种方式定义的函数都只执行读操作,不会进行编译执行。即用了这三种方式定义的函数,不会执行函数里的逻辑,只会执行一个返回的读操作。所以执行这些函数不需要消耗gas费用。

    • pure区别是用于返回非变量,如returns 10;
    • 而view和constant用于返回全局变量,两者的区别为新旧版本
    contract HelloWorld4{
        
        uint public a = 1;
        
      //由于被constant声明的函数执行读操作,所以a无法被修改  
      //执行为f(),a依然为1
        function f() constant{
           a = 3;
        }
    
    }
    
    

    5.函数修饰符

    用于以声明方式修改函数的语义,如下例子:

    contract HelloWorld{
        
        address public sender;
        
        function HelloWorld(){
            //创建合约时将合约创建者赋值给sender
            sender = msg.sender;
            
        }
    
      modifier onlyOwner(){
          //如果调用合约的人不是合约创建者则throw
          if(msg.sender != sender) throw;
          _;  //占位符
      }
      
      //这样a函数就只能被合约的创建者调用了
      function a() onlyOwner{
          ...
      }
        
        
    
    

    6.回退函数

    fallback function 回退函数,每一个合约有且仅有一个没有名字的函数,往合约发送消息时,会执行该函数。如果合约要正常接受ether,需要加上payable声明。声明后,当有用户往合约转账时,将触发该函数,可以在里面写相应的逻辑。

    7.异常处理

    Solidity使用状态恢复来处理异常,就是说当抛出异常时将恢复到调用(包括自调用)前的状态。
    抛出异常的方式有assert,require,revert,throw。

    • assert函数,用于条件检查,只能测试内部错误和检查常量。
    //检查内部计算是否会整型溢出
    function add(uint256 a, uint256 b) internal constant returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);
        return c;
      }
    
    
    • require函数,也是用于条件检查,用于测试调用的输入或者合约状态变量。
    function sendHalf(address addr) payable returns (uint balance) {
            require(msg.value % 2 == 0); // 只允许偶数
            .....
        }
    
    
    • revert 函数用于标记错误并恢复当前调用。
        function buy(uint amount) payable {
            if (amount > msg.value / 2 ether)
                revert("Not enough Ether provided.");
        }
    
    
    • throw 和revert一样,但是throw在0.4.13被弃用,将来会被淘汰。

    相关文章

      网友评论

          本文标题:Solidity基础语法

          本文链接:https://www.haomeiwen.com/subject/idpjlftx.html