solidity的高阶语法(完结篇)
1.样式指南
样式指南有助于保持代码布局一致并使代码更具可读性。 以下是使用 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 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; elsex -= 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...'";
布局顺序
元素应按以下顺序布局。
-
编译指示语句
-
导入语句
-
接口
-
库
-
合约
在接口、库或合约中,顺序应为 −
-
类型声明
-
状态变量
-
活动
-
函数
命名约定
-
合同和库应使用 CapWords 样式命名。 例如,智能合约、所有者等。
-
合同和库名称应与其文件名匹配。
-
如果文件中有多个合约/库,请使用核心合约/库的名称。
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 {//... }
-
结构名称
− 使用像 SmartCoin 这样的 CapWords 风格。 -
事件名称
− 使用 CapWords 样式,例如 Deposit、AfterTransfer。 -
函数名称
− 使用像initiateSupply 这样的mixedCase 样式。 -
局部变量和状态变量
− 使用混合大小写样式,如creatorAddress、supply。 -
常量
− 使用所有大写字母和下划线来分隔单词,例如 MAX_BLOCKS。 -
修饰符名称
− 使用 mixCase 样式,如 onlyAfter。 -
枚举名称
− 使用像 TokenGroup 这样的 CapWords 样式。
2.特殊变量
特殊变量是全局可用的变量,提供有关区块链的信息。 以下是特殊变量列表 −
序号 | 特殊变量和描述 |
---|---|
1 | blockhash(uint blockNumber) returns (bytes32) 给定区块的哈希值 - 仅适用于 256 个最新区块(不包括当前区块)。 |
2 | block.coinbase (address payable) 当前区块矿工地址。 |
3 | block.difficulty (uint) 当前区块难度。 |
4 | block.gaslimit (uint) 当前区块的 GasLimit。 |
5 | block.number (uint) 当前区块号。 |
6 | block.timestamp 当前区块时间戳,以 UNIX 纪元以来的秒数表示。 |
7 | gasleft() returns (uint256) Remaining gas. |
8 | msg.data (bytes calldata) 完整的呼叫数据。 |
9 | msg.sender (address payable) 消息的发送者(当前通话)。 |
10 | msg.sig (bytes4) 调用数据的前四个字节(即函数标识符) |
11 | msg.value (uint) 与消息一起发送的 wei 数量。 |
12 | now (uint) 当前区块时间戳(block.timestamp 的别名)。 |
13 | tx.gasprice (uint) 交易的 Gas 价格。 |
14 | tx.origin (address payable) 交易的发送者(完整调用链)。 |
示例
尝试以下代码来查看 msg 的使用,msg 是 Solidity 中用于获取发件人地址的特殊变量。
pragma solidity ^0.5.0;contract LedgerBalance {mapping(address => uint) public balances;function updateBalance(uint newBalance) public {balances[msg.sender] = newBalance;} } contract Updater {function updateBalance() public returns (uint) {LedgerBalance ledgerBalance = new LedgerBalance();ledgerBalance.updateBalance(10);return ledgerBalance.balances(address(this));} }
使用 Solidity First 应用 章节中提供的步骤运行上述程序。
首先单击updateBalance按钮将值设置为10,然后查看日志,其中将显示解码输出为 −
输出
{"0": "uint256: 10" }