zoukankan      html  css  js  c++  java
  • 智能合约最佳实践 之 Solidity 编码规范

    最新内容会更新在主站深入浅出区块链社区
    原文链接:智能合约最佳实践 之 Solidity 编码规范

    每一门语言都有其相应的编码规范, Solidity 也一样, 下面官方推荐的规范及我的总结,供大家参考,希望可以帮助大家写出更好规范的智能合约。

    命名规范

    避免使用

    小写的l,大写的I,大写的O 应该避免在命名中单独出现,因为很容易产生混淆。

    合约、库、事件、枚举及结构体命名

    合约、库、事件及结构体命名应该使用单词首字母大写的方式,这个方式也称为:帕斯卡命名法或大驼峰式命名法,比如:SimpleToken, SmartBank, CertificateHashRepository,Player。

    函数、参数、变量及修饰器

    函数、参数、变量及修饰器应该使用首单词小写后面单词大写的方式,这个方式也称为:(小)驼峰式命名法,是一种混合大小写的方式,如:

    • 函数名应该如:getBalance,transfer,verifyOwner,addMember。
    • 参数和变量应该如:initialSupply,senderAddress,account,isPreSale。
    • 修饰器应该如:onlyAfter,onlyOwner。

    代码格式相关

    缩进

    使用空格(spaces)而不是Tab, 缩进应该是4个空格

    空行

    合约之间应该有空行,例如:

    contract A {
        ...
    }
        
        
    contract B {
        ...
    }
        
        
    contract C {
        ...
    }
    

    而不是使用:

    contract A {
        ...
    }
    contract B {
        ...
    }
        
    contract C {
        ...
    }
    
    • 函数之间应该有空行,例如:
    contract A {
        function spam() public {
            ...
        }
        
        function ham() public {
            ...
        }
    }
    

    没有实现的话,空行可以省去,如:

    contract A {
        function spam() public;
        function ham() public;
    }
    

    而不是:

    contract A {
        function spam() public {
            ...
        }
        function ham() public {
            ...
        }
    }
    

    左括号应该跟定义在一行

    定义包括合约定义、函数定义、库定义、结构体定义等等,例如推荐使用:

     contract Coin {
        struct Bank {
            address owner;
            uint balance;
        }
    }
    

    而不是:

    contract Coin
    {
        struct Bank {
            address owner;
            uint balance;
        }
    }
    

    左括号应该跟条件控制在一行

    在使用if, else, while, for 时,推荐的写法是:

    if (...) {
        ...
    }
    
    for (...) {
        ...
    }
    

    而不是:

    if (...)
    {
        ...
    }
    
    while(...){
    }
    
    for (...) {
        ...;}
    

    如果控制语句内只有一行,括号可省略,如:

    if (x < 10)
        x += 1;
    

    但像下面一个语句有多方就不能省略,如:

    if (x < 10)
        someArray.push(Coin({
            name: 'spam',
            value: 42
        }));
    

    表达式内的空格

    • 一个单行的表达里,在小括号、中括号、大括号里应该避免不必要的空格,例如推荐使用:

      spam(ham[1], Coin({name: "ham"}));
      

      而不是:

      spam( ham[ 1 ], Coin( { name: "ham" } ) );
      

      有一种例外是,结尾的括号跟在结束的分号后面, 应该加一个空格,如下面的方式也是推荐的:

      function singleLine() public { spam(); }
      
    • 分号;前不应该有空格,例如推荐使用:

      function spam(uint i, Coin coin) public;
      

      而不是:

      function spam(uint i , Coin coin) public ;
      
    • 不要为对齐添加不必要的空格,例如推荐使用:

      x = 1;
      y = 2;
      long_variable = 3;
      

      而不是:

      x             = 1;
      y             = 2;
      long_variable = 3;
      
    • 回退函数不应该有空格,例如推荐使用:

      function() public {
          ...
      }
      
      

      而不是:

      function () public {
          ...
      }
      

    控制每一行长度

    每行不应该太长,最好在79(或99)个字符以内,函数的参数应该是单独的行,且只有一个缩进,例如推荐的方式是:

    thisFunctionCallIsReallyLong(
        longArgument1,
        longArgument2,
        longArgument3
    );
    

    而不是:

    thisFunctionCallIsReallyLong(longArgument1,
                                  longArgument2,
                                  longArgument3
    );
    
    thisFunctionCallIsReallyLong(longArgument1,
        longArgument2,
        longArgument3
    );
    
    thisFunctionCallIsReallyLong(
        longArgument1, longArgument2,
        longArgument3
    );
    
    thisFunctionCallIsReallyLong(
    longArgument1,
    longArgument2,
    longArgument3
    );
    
    thisFunctionCallIsReallyLong(
        longArgument1,
        longArgument2,
        longArgument3);
    

    对应的赋值语句应该是这样写:

    thisIsALongNestedMapping[being][set][to_some_value] = someFunction(
       argument1,
       argument2,
       argument3,
       argument4
    );
    

    而不是:

    thisIsALongNestedMapping[being][set][to_some_value] = someFunction(argument1,
                                                                       argument2,
                                                                       argument3,
                                                                       argument4);
    

    事件定义也应该遵循同样的原则,例如应该使用:

    event LongAndLotsOfArgs(
        adress sender,
        adress recipient,
        uint256 publicKey,
        uint256 amount,
        bytes32[] options
    );
    
    LongAndLotsOfArgs(
        sender,
        recipient,
        publicKey,
        amount,
        options
    );
    

    而不是:

    event LongAndLotsOfArgs(adress sender,
                            adress recipient,
                            uint256 publicKey,
                            uint256 amount,
                            bytes32[] options);
    
    LongAndLotsOfArgs(sender,
                      recipient,
                      publicKey,
                      amount,
                      options);
    

    文件编码格式

    推荐使用utf-8 及 ASCII 编码

    引入文件应该在最上方

    建议使用:

    import "owned";
    
    
    contract A {
        ...
    }
    
    
    contract B is owned {
        ...
    }
    

    而不是:

    contract A {
        ...
    }
    
    
    import "owned";
    
    
    contract B is owned {
        ...
    }
    

    函数编写规范

    函数的顺序

    在编写函数的时候,应该让大家容易找到构造函数,回退函数,官方推荐的的函数顺序是:

    1. 构造函数
    2. 回退函数 (如果有)
    3. 外部函数(external)
    4. 公有函数(public)
    5. 内部函数(internal)
    6. 私有函数(private)

    同一类函数时,constant函数放在后面, 例如推荐方式为:

     contract A {
        // 构造函数
        function A() public {
            ...
        }
    
        // 回退函数
        function() public {
            ...
        }
    
        // 外部函数
        // ...
    
        // 带有constant 外部函数 
        // ...
    
        // 公有函数
        // ...
    
        // 内部函数
        // ...
    
        // 私有函数
        // ...
    }
    

    而不是下面的函数顺序:

     contract A {
    
    
        // 外部函数
        // ...
    
        // 公有函数
        // ...
    
        // 内部函数
        // ...
        
        function A() public {
            ...
        }
    
        function() public {
            ...
        }
    
        // 私有函数
        // ...
    }
    

    明确函数的可见性

    所有的函数(包括构造函数)应该在定义的时候明确函数的可见性,例如应该使用:

    function explicitlyPublic(uint val) public {
        doSomething();
    }
    

    而不是

    function implicitlyPublic(uint val) {
        doSomething();
    }
    

    可见性应该在修饰符前面

    函数的可见性应该写在自定义的函数修饰符前面,例如:

    function kill() public onlyowner {
        selfdestruct(owner);
    }
    

    而不是

    function kill() onlyowner public {
        selfdestruct(owner);
    }
    

    区分函数和事件

    为了防止函数和事件(Event)产生混淆,声明一个事件使用大写并加入前缀(可使用LOG)。对于函数, 始终以小写字母开头,构造函数除外。

    // 不建议
    event Transfer() {}
    function transfer() {}
    
    // 建议
    event LogTransfer() {}
    function transfer() external {}
    

    常量

    常量应该使用全大写及下划线分割大词的方式,如:MAX_BLOCKS,TOKEN_NAME, CONTRACT_VERSION。

    参考视频

    我们也推出了目前市面上最全的视频教程:深入详解以太坊智能合约语言Solidity
    目前我们也在招募体验师,可以点击链接了解。

  • 相关阅读:
    zookeeper集群搭建
    Redis集群管理
    postman的使用
    python接口自动化:requests+ddt+htmltestrunner数据驱动框架
    python实现建立websocket通信
    python实现建立soap通信(调用及测试webservice接口)
    python接口自动化:响应内容中json字符串对象的处理
    python接口自动化:调试接口的代码(无token情况下)
    python接口自动化:https请求,取消警告
    python接口自动化:对外接口sign签名
  • 原文地址:https://www.cnblogs.com/tinyxiong/p/8989673.html
Copyright © 2011-2022 走看看