Solidity - 智能合约语言
本章只介绍高级概念、开发过程和用 Solidity 编写的示例,因为 Solidity 在其官方网站上已有详尽的文档说明。 有关语言规范或实现,请参阅下面的 参考文献。 本章内容基于 [参考文献](#参考文献)中列出的多个网站。
坚固和卡娅
Solidity是一种高级、静态类型化、面向合约的语言,用于在以太坊平台上实现智能合约。 虽然 Solidity 最初是为以太坊设计的,但它在编写智能合约方面具有足够的通用性;因此,它也可用于其他区块链平台,如 Kaia。
Kaia 正式兼容伦敦以太坊虚拟机(EVM)版本。 不保证向后兼容 Kaia 上的其他 EVM 版本。 因此,强烈建议使用 Istanbul 目标选项编译 Solidity 代码。 请参阅 如何设置 Solc 的 EVM 版本。
v1.7.0 协议升级 - 不兼容的更改,包括伊斯坦布尔硬分叉项目和 Kaia 自己的项目。 如果是 Kairos 网络,则从区块编号 "#75,373,312 "开始启用,如果是主网络,则从区块编号 "#86,816,005 "开始启用。
v1.7.3 协议升级 - 包括伦敦***硬分叉产生的基本费用在内的不兼容变更。 如果是 Kairos 网络,则从区块编号 "#80,295,291 "开始启用,如果是主网络,则从区块编号 "#86,816,005 "开始启用。
v1.8.0 协议升级 - 包括伦敦***硬分叉产生的基本费用在内的不兼容变更。 如果是 Kairos 网络,则从区块编号 "#86,513,895 "开始启用,如果是主网,则从区块编号 "#86,816,005 "开始启用。
在为 Kaia 开发智能合约时,可以使用 Remix (一个基于浏览器的 IDE)和 Hardhat (一个开发框架)等开发工具。 Kaia 团队将努力保持以太坊开发工具与 Kaia 开发工具之间的兼容性,但在必要时可能会选择向 Kaia 智能合约开发人员提供这些工具的增强版或更新版。
使用 Remix 或 Hardhat 开发智能合约非常方便,但 Solidity 编译器也可在本地使用,只需按照下面网页中的说明构建或安装即可:
请注意,有两种命令行 Solidity 编译器:
- solc:全功能编译器
- 包含在 Solidity 文档中
- solcjs:用于 solc 的 Javascript 绑定
- 作为独立项目 [solc-js] 维护(https://github.com/ethereum/solc-js)
- solcjs 的命令行选项与 solc 的命令行选项不兼容。
其他有助于入门 Solidity 的资料包括以下内容:
如何编写智能合约
本节以 Solidity 源代码为例,让读者了解智能合约的外观以及如何编写合约。 请注意,此处包含的代码仅供解释之用,并不用于生产目的。 在代码中,"(require) "表示任何 Solidity 源文件都需要该行,而"(optional) "则表示不一定需要该行。 符号 Ln: 并非 Solidity 代码的一部分,在此加入只是为了显示行号。 请不要在实际使用的源代码中使用这些符号。
L01: pragma solidity 0.5.12; // (required) version pragmaL02:L03: import "filename"; // (optional) importing other source filesL04:L05: // (optional) smart contract definitionL06: contract UserStorage {L07: mapping(address => uint) userData; // state variableL08:L09: function set(uint x) public {L10: userData[msg.sender] = x;L11: }L12:L13: function get() public view returns (uint) {L14: return userData[msg.sender];L15: }L16:L17: function getUserData(address user) public view returns (uint) {L18: return userData[user];L19: }L20: }
上述代码不言自明,因此熟悉其他编程语言的人可以跳过本节的解释,直接跳到下一节。 不过,对于那些不清楚代码作用的人,或者对于 Solidity 是第一种编程语言的人,我们会在下面附上源代码的简短说明:
- 代码中以双斜线开头的部分是注释,而不是代码;它们用于注释和解释代码。 编译器会忽略注释。
- L01 "中的 "pragma "语句表示编译器的最小版本。
- L03
中的import语句从"filename`"导入所有全局符号。 文件名 "应为实际文件名。 L05-L20定义了一个名为UserStorage的智能合约。 关键字contract位于合约名称之前,声明代码代表一个智能合约。 Solidity 中的契约类似于面向对象语言中的类。 每个合约可包含状态变量、函数、函数修改器、事件、结构类型和枚举类型的声明。 此外,合同还可以继承其他合同。 示例代码包含一个合同定义,但一个 Solidity 文件可能包含多个合同定义。- 在
L07中,userData是映射类型的状态变量。 状态变量永久保存在合约存储器中。 状态变量userData维护着address和uint值之间的映射。 地址 "类型保存一个 20 字节的地址(Kaia 使用的 20 字节地址与以太坊类似)。 L09定义了一个公共函数set,用于在userData中保存信息发送者的x值。 变量 "msg.sender "是 Solidity 中定义的一个特殊变量,表示消息(即当前呼叫)发送者的地址。 关键字 "public "表示该函数是合约接口的一部分,可在外部或内部调用。- L13
中的函数get和 L17中的函数getUserData是用view声明的,这意味着函数承诺不修改任何状态变量。 它们的声明包括returns (uint),这意味着它们返回一个uint值。
有关 Solidity 语言语法和语 义的更多信息,请参阅 Solidity 文档。
如何编译、部署和执行
编译 Solidity 代码的一种方法是使用命令行编译器 solc。 这种编译器可以产生各种输出,从简单的二进制文件和汇编到抽象语法树(parse tree\ )。 假设上面的代码保存在 UserStorage.sol(上面显示的源文件中不包括 L03),编译文件 UserStorage.sol的一些示例如下。
$ solc --bin UserStorage.sol
- 该命令将以二进制_即_字节码_的形式打印编译输出。
solc -o output --bin --ast --asm UserStorage.sol
- 编译器会生成二进制文件、抽象语法树和汇编代码,并将它们作为单独的文件存放在 "输出 "目录下。
solc --optimize --bin UserStorage.sol
- 为提高性能,可在编译过程中使用
--optimize标记激活优化器。
下面列出了一些用于编译、部署和执行智能合约的资源。
注:本部分内容今后将进行更新。
调试智能合约
由于缺乏成熟的调试工具,调试 Solidity 代码比调试用其他编程语言编写的代码更加困难。 下面,我们列出了一些用于 Solidity 调试的资源。
注:本部分内容今后将进行更新。
智能合约最佳实践
要消除智能合约中的安全问题和代码质量问题,必须学习并遵循 Solidity 编程的最佳实践。 在此,我们展示了 Solidity 最佳实践的参考资料。