Solidity - 风格指南



风格指南有助于保持代码布局的一致性并使代码更易于阅读。以下是使用 Solidity 编写合约时应遵循的最佳实践。

代码布局

  • 缩进 − 使用 4 个空格代替制表符来维护缩进级别。避免混合使用空格和制表符。

  • 两行空行规则 − 在两个合约定义之间使用 2 行空行。

pragma solidity ^0.5.0;

contract LedgerBalance {
   //...
}
contract Updater {
   //...
}
  • 一行空行规则 − 在两个函数之间使用 1 行空行。如果只有声明,则无需空行。

pragma solidity ^0.5.0;

contract A {
   function balance() public pure;
   function account() public pure;
}
contract B is A {
   function balance() public pure {
      // ...
   }
   function account() public pure {
      // ...
   }
}
  • 最大行长 − 单行不应超过 79 个字符,以便读者可以轻松解析代码。

  • 换行规则 − 第一个参数应在新行中,不带开括号。每个参数使用单个缩进。结束元素 ); 应为最后一个。

function_with_a_long_name(
   longArgument1,
   longArgument2,
   longArgument3
);
variable = function_with_a_long_name(
   longArgument1,
   longArgument2,
   longArgument3
);
event multipleArguments(
   address sender,
   address recipient,
   uint256 publicKey,
   uint256 amount,
   bytes32[] options
);
MultipleArguments(
   sender,
   recipient,
   publicKey,
   amount,
   options
);
  • 源代码编码 − 最好使用 UTF-8 或 ASCII 编码。

  • 导入 − 导入语句应放置在文件顶部,紧跟在 pragma 声明之后。

  • 函数顺序 − 函数应根据其可见性进行分组。

pragma solidity ^0.5.0;

contract A {
   constructor() public {
      // ...
   }
   function() external {
      // ...
   }

   // External functions
   // ...

   // External view functions
   // ...

   // External pure functions 
   // ...

   // Public functions
   // ...

   // Internal functions
   // ...

   // Private functions
   // ...
}
  • 避免额外的空格 − 避免在括号、方括号或花括号内立即使用空格。

  • 控制结构 − 花括号应与声明位于同一行。在自己的行上关闭,并保持相同的缩进。在开花括号前使用空格。

pragma solidity ^0.5.0;

contract Coin {
   struct Bank {
      address owner;
      uint balance;
   }
}
if (x < 3) {
   x += 1;
} else if (x > 7) {
   x -= 1;
} else {
   x = 5;
}
if (x < 3)
   x += 1;
else
   x -= 1;
  • 函数声明 − 对花括号使用上述规则。始终添加可见性标签。可见性标签应在任何自定义修饰符之前出现。

function kill() public onlyowner {
   selfdestruct(owner);
}
  • 映射 − 声明映射变量时避免使用空格。

mapping(uint => uint) map;
mapping(address => bool) registeredAddresses;
mapping(uint => mapping(bool => Data[])) public data;
mapping(uint => mapping(uint => s)) data;
  • 变量声明 − 声明数组变量时避免使用空格。

uint[] x;  // not unit [] x;
  • 字符串声明 − 使用双引号而不是单引号来声明字符串。

str = "foo";
str = "Hamlet says, 'To be or not to be...'";

布局顺序

元素应按以下顺序布局。

  • Pragma 语句

  • 导入语句

  • 接口

  • 合约

在接口、库或合约内,顺序应为 -

  • 类型声明

  • 状态变量

  • 事件

  • 函数

命名约定

  • 合约和库应使用 CapWords 样式命名。例如,SmartContract、Owner 等。

  • 合约和库名称应与其文件名匹配。

  • 如果在一个文件中有多个合约/库,则使用核心合约/库的名称。

Owned.sol

pragma solidity ^0.5.0;

// Owned.sol
contract Owned {
   address public owner;
   constructor() public {
      owner = msg.sender;
   }
   modifier onlyOwner {
      //....
   }
   function transferOwnership(address newOwner) public onlyOwner {
      //...
   }
}

Congress.sol

pragma solidity ^0.5.0;

// Congress.sol
import "./Owned.sol";

contract Congress is Owned, TokenRecipient {
   //...
}
  • 结构体名称

    − 使用 CapWords 样式,例如 SmartCoin。

  • 事件名称

    − 使用 CapWords 样式,例如 Deposit、AfterTransfer。

  • 函数名称

    − 使用 mixedCase 样式,例如 initiateSupply。

  • 局部变量和状态变量

    − 使用 mixedCase 样式,例如 creatorAddress、supply。

  • 常量

    − 使用全部大写字母,并使用下划线分隔单词,例如 MAX_BLOCKS。

  • 修饰符名称

    − 使用 mixCase 样式,例如 onlyAfter。

  • 枚举名称

    − 使用 CapWords 样式,例如 TokenGroup。

广告