本教程使用的开发环境是一款在线编译器——ChainIDE,具体的使用方法在之前的文章当中已经有讲解过,有需要的同学可以自行查看。
文件架构
Solidity语言的文件名后缀为.sol,一般用作智能合约的编写,文件内会包含以下的一些内容:
1.编译器版本定义
2.外部合约调用(非必需)
3.合约主体
4.注释(非必需)
编译器版本定义。版本限制是为了解决程序有可能被不兼容的编译器所导致编译失败而产生的,我们可以通过几个例子来了解一些它的常用方法。
pragma solidity ^0.4.0;
这句话的意思是,该文件使用的编译器是大于等于0.4.0但小于0.5.0(不包括0.5.0),后面这个条件由^符号进行限定,这样可以保证在编译器的一个中等版本内进行编译。
pragma solidity >=0.4.0 <0.7.0;
这种写法更像程序内的一种条件语句,也就是该文件使用的编译器大于等于0.4.0且小于0.7.0。
外部合约调用。在开源的仓库比如github,或者本地的文件内,有已经写好的合约,我们就可以通过外部调用的方式直接引用,不用再重写一遍。这种不仅是为了节约时间和精力,而且是为了保证安全,通常来说已经在区块链上运行了一段时间的库是具有安全保障的,比如大家会经常使用的Openzipplin的Safemath等众所周知的轮子。
调用方法也很简单:
import "filename";
这是最简单的,直接通过路径来进行库的引用,可以引用本地路径下的库,也可以引用github上的一些库。具体引用方式可以看下面两个例子。
import "github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.5.1/contracts/math/SafeMath.sol";
import "../test.sol"
上面那行引用的是github上的OpeZeppelin的库,这样会把这个库放到编译器环境当中进行编译。下面那行引用的是本地路径下的一个test.sol文件,文件的位置在它的父目录下。
import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping;
还有一个技巧是可以把引用的库给一个简称,这样在调用的时候可以更加方便,类似于python当中import pandas as py这种方式。
合约主体。智能合约就是由Contract关键字编写的程序模块,它的内部是作用域,它的大括号内的一切都是属于这个合约的一部分。一个合约主要会包含这五个元素:
1.状态变量。
uint storedData; // 状态变量
状态变量是一个永久储存在合约储存当中的值,状态变量可以是整形、布尔型、等等,状态变量的类型可以由程序设定,或者是通过逻辑进行推断得出,具体的细节内容我们会在下一节教程当中讲解。
2.自定义类型
enum Class { Chinese, Math, English } // 枚举
struct Student{ // 结构体
uint number;
bool isboy;
address WalletAddress;
uint grade;
}
自定义类型有枚举类型和结构体两种形式,都是通过一个程序开发者自行定义的方式来对改类型进行设定,并且在程序当中调用这个值。
3.函数
function get() public view returns (uint) {
return storedData;
}
函数是合约用来实现功能的逻辑部分,它包含了输入值,返回值,函数类型,函数可见性以及内部逻辑等部分,是合约当中一个非常重要的部分。
4.函数Modifier
modifier onlyOwner {
require(msg.sender == owner);
_;
}
Modifier可以更改函数的行为,比如让它加入一些前置判断条件,对函数的使用进行限制。这种Modifier是合约的可继承属性,可能被派生属性所覆盖,总的来说是函数设计的一种表达方式。
上面这个onlyOwner的modifier就表示只有与合约当中owner变量的值相同的地址才可以调用这个函数,后面的_表示待填充的代码。
5.事件
event EventName(address bidder, uint amount); //定义一个事件
function testEvent() public {
emit EventName(msg.sender, msg.value); // 触发一个事件
}
这个部分有些与平常的语言不一样的地方,由于程序运行的基础环境是EVM,程序的调试和监管所需的日志也是储存在EVM上的,event关键词就是定义一个事件,在emit的时候调用它。
在合约内是不可以查看这个事件的日志的,想要查看日志可以使用Javascript的接口从以太坊查询这个日志。
我们可以举个例子,比如你是一个制作DEX前端的程序员,你要跟合约进行交互,观察函数是否正确被调用了,交易是否完成,这个时候就可以通过调用日志来进行查询。这个部分在我们稍微后面一点的教程当中会提及。
最后,注释。虽然注释不是一个程序编译时的必须组成部分,但是不写注释的程序员都是要被开除的[狗头]。
// 这是一条注释
希望大家在写程序的时候也能好好写注释,这样在与别人协作或者是自己调试的时候会有很大帮助。
结语
今天的内容就到这里结束了,主要是帮助大家对.sol文件结构有个整体的认识,这样在真正开始编程的时候可以更快的入手。