了解语言基础知识
所有 Solidity 合同通常都包括:
- Pragma 指令
- 状态变量
- 函数
- 事件
虽然对生产级智能合同进行编程时会涉及更多知识,但上述这些内容应能让你迈出正确的一步。
如果你了解这些概念,则可以立即开始为各种用例编写智能合同!
Pragma 指令
Pragma 是用来指示编译器检查其 Solidity 版本是否与所需版本匹配的关键字。 如果匹配,则表示源文件可以成功运行。 如果不匹配,编译器将发出错误。
请始终确保在合同定义中包含 Solidity 最新版本。 若要查找 Solidity 的当前版本,请访问 Solidity 网站。 使用源文件中的最新版本。
版本 pragma 指令如下所示:
pragma solidity ^0.7.0;
此行意味着源文件将使用高于 0.7.0
版本(最高版本为 0.7.9
)的编译器进行编译。 从版本 0.8.0
开始,可能会引入一些中断性变更,导致源文件无法成功编译。
状态变量
状态变量是任何 Solidity 源文件的关键。 状态变量永久存储在合同存储中。
pragma solidity >0.7.0 <0.8.0;
contract Marketplace {
uint price; // State variable
注意
合同源文件始终以定义“contract ContractName”开头。
在本例中,状态变量名为 price
,类型为“uint”。 整数类型 uint 表示此变量是 256 位的无符号整数。 这意味着它可以存储 0 到 2256 -1 范围内的正数。
对于所有变量定义,必须指定类型和变量名。
此外,可以将状态变量的可见性指定为:
- public:合同接口的一部分,可以从其他合同访问。
- internal:仅限从当前合同内部访问。
- 专用:仅对定义它的合同可见。
函数
在合同中,可执行代码单元成为函数。 函数描述实现一个任务的单个操作。 它们是可重用的,也可以从其他源文件(如库)进行调用。 Solidity 中函数的行为类似于其他编程语言中的函数。
下面是定义函数的一个基本示例:
pragma solidity >0.7.0 <0.8.0;
contract Marketplace {
function buy() public {
// ...
}
}
这段代码显示了一个名为 buy
的函数,它具有公共可见性,这意味着它可以由其他合同访问。 函数可以使用以下可见性说明符之一:public、private、internal 和 external。
函数可以在内部进行调用,也可以从另一个合同外部进行调用。 函数可以接受参数并返回变量,以便在它们之间传递参数和值。
下面是一个函数示例,该函数接受一个参数(一个称为 price
的整数),并返回一个整数:
pragma solidity >0.7.0 <0.8.0;
contract Marketplace {
function buy(uint price) public returns (uint) {
// ...
}
}
函数修饰符
函数修饰符可用于更改函数的行为。 它们的工作原理是在函数执行前检查条件。 例如,函数可以检查只有指定为卖方的用户才能列出要出售的商品。
pragma solidity >0.7.0 <0.8.0;
contract Marketplace {
address public seller;
modifier onlySeller() {
require(
msg.sender == seller,
"Only seller can put an item up for sale."
);
_;
}
function listItem() public view onlySeller {
// ...
}
}
此示例介绍以下各项:
- 类型为 address 的变量,用于存储卖方用户的 20 字节 Ethereum 地址。 本模块稍后会详细介绍这些变量。
- 名为
onlySeller
的修饰符,用于说明只有卖方才能列出商品。 - 特殊符号
_;
,表示函数体插入的位置。 - 使用修饰符
onlySeller
的函数定义。
可在函数定义中使用的其他函数修饰符包括:
- pure,用于描述不允许修改或访问状态的函数。
- view,用于描述不允许修改状态的函数。
- payable,用于描述可以接收 Ether 的函数。
事件
事件描述了合同中采取的操作。 与函数类似,事件具有在调用事件时需要指定的参数。
若要调用事件,必须将关键字“emit”与事件名称及其参数一起使用。
pragma solidity >0.7.0 <0.8.0;
contract Marketplace {
event PurchasedItem(address buyer, uint price);
function buy() public {
// ...
emit PurchasedItem(msg.sender, msg.value);
}
}
调用事件时,事件会被捕获为事务日志中的事务,事务日志是区块链中的一种特殊数据结构。 这些日志与合同的地址相关联,已合并到区块链中,并且始终保持不变。 无法从合同中访问日志及其事件数据,并且无法修改它。