资讯专栏INFORMATION COLUMN

智能合约最佳实践之Solidity编码规范

kevin / 2795人阅读

摘要:命名规范避免使用小写的,大写的,大写的应该避免在命名中多带带出现,因为很容易产生混淆。对于函数,始终以小写字母开头,构造函数除外。

本文首发于深入浅出区块链社区
原文链接:智能合约最佳实践之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 {
    ...
}
函数编写规范 函数的顺序

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

构造函数

回退函数 (如果有)

外部函数(external)

公有函数(public)

内部函数(internal)

私有函数(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
目前我们也在招募体验师,可以点击链接了解。

参考文献

Solidity style-guide

☛ 深入浅出区块链 - 系统学习区块链,打造最好的区块链技术博客。

☛ 我的知识星球为各位解答区块链技术问题,欢迎加入讨论。

☛ 关注公众号“深入浅出区块链技术”第一时间获取区块链技术信息。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/24070.html

相关文章

  • 区块链技术学习指引

    摘要:引言给迷失在如何学习区块链技术的同学一个指引,区块链技术是随比特币诞生,因此要搞明白区块链技术,应该先了解下比特币。但区块链技术不单应用于比特币,还有非常多的现实应用场景,想做区块链应用开发,可进一步阅读以太坊系列。 本文始发于深入浅出区块链社区, 原文:区块链技术学习指引 原文已更新,请读者前往原文阅读 本章的文章越来越多,本文是一个索引帖,方便找到自己感兴趣的文章,你也可以使用左侧...

    Cristic 评论0 收藏0
  • 智能合约语言Solidity教程系列3 - 函数类型

    摘要:本文首发于深入浅出区块链社区原文链接智能合约语言教程系列函数类型原文已更新,请读者前往原文阅读教程系列第三篇函数类型介绍。函数类型函数也是一种类型,且属于值类型。但以此相反,合约中函数本身默认是的,仅仅是当作类型名使用时默认是的。 本文首发于深入浅出区块链社区原文链接:智能合约语言Solidity教程系列3 - 函数类型原文已更新,请读者前往原文阅读 Solidity 教程系列第三篇 ...

    qylost 评论0 收藏0
  • 区块链学习资料

    摘要:比特币比特币既可以指这种虚拟货币单位,也指比特币网络或者网络节点使用的比特币软件。有效的区块经过全网络的共识后会被追加到主区块链中。 区块链资料汇总 更多区块链资料 区块链 区块链是一串通过验证的区块,当中的每一个区块都与上一个相连,一直连到创世区块。 确认当一项交易被区块收录时,我们可以说它有一次确认。矿工们在此区块之后每再产生一个区块,此项交易的确认数就再加一。当确认数达到六及以上...

    王晗 评论0 收藏0
  • 写给前端的区块链开发入门指南:零基础开发基于以太坊智能合约的 ICO DApp

    摘要:围绕以太坊的开发生态是目前相对最成熟的,比如有开发框架,有智能合约在线集成开发环境,还有专设的开发者问答频道。 showImg(https://segmentfault.com/img/bVbaJOL?w=1200&h=514); 张泉灵说,时代抛弃我们的时候连声再见都不会说,马云说对于新兴事物,绝大多数人是看不见、看不起、看不懂、来不及。自从学完 Coursera 上的 Crypto...

    sean 评论0 收藏0
  • 写给前端的区块链开发入门指南:零基础开发基于以太坊智能合约的 ICO DApp

    摘要:围绕以太坊的开发生态是目前相对最成熟的,比如有开发框架,有智能合约在线集成开发环境,还有专设的开发者问答频道。 showImg(https://segmentfault.com/img/bVbaJOL?w=1200&h=514); 张泉灵说,时代抛弃我们的时候连声再见都不会说,马云说对于新兴事物,绝大多数人是看不见、看不起、看不懂、来不及。自从学完 Coursera 上的 Crypto...

    yzzz 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<