在 remix 中有三个例子,这是第2个 Owner 案例,看这篇之前,请先确定看过之前的2篇。
Owner 这个案例,主要是存储、检查、修改智能合约的以太坊地址。
源码如下
pragma solidity >=0.7.0 <0.8.0;
/**
@title Owner
@dev Set & change owner
*/
contract Owner {
address private owner;
// event for EVM logging
event OwnerSet(address indexed oldOwner, address indexed newOwner);
// modifier to check if caller is owner
modifier isOwner() {
// If the first argument of 'require' evaluates to 'false', execution terminates and all
// changes to the state and to Ether balances are reverted.
// This used to consume all gas in old EVM versions, but not anymore.
// It is often a good idea to use 'require' to check if functions are called correctly.
// As a second argument, you can also provide an explanation about what went wrong.
require(msg.sender == owner, "Caller is not owner");
_;
}
/**
@dev Set contract deployer as owner
*/
constructor() {
owner = msg.sender; // 'msg.sender' is sender of current call, contract deployer for a constructor
emit OwnerSet(address(0), owner);
}
/**
@dev Change owner
@param newOwner address of new owner
*/
function changeOwner(address newOwner) public isOwner {
emit OwnerSet(owner, newOwner);
owner = newOwner;
}
/**
@dev Return owner address
@return address of owner
*/
function getOwner() external view returns (address) {
return owner;
}
}
接下来开始分析
contract Owner
定义一个智能合约 Owner。
address private owner;
定义一个数据类型是 address、属性是 private
的变量。private
表示只能当前合约访问,继承合约也不能访问,跟我们接触其他语言一样。
address
是智能合约或用户的以太坊地址,这是一个以太坊的数据类型,像 string
、uint
类型一样。
event OwnerSet(address indexed oldOwner, address indexed newOwner);
声明一个事件。事件是合约和区块链通讯的一种机制,前端应用可以监听某些事件。indexed
表示这个事件变量可以被搜索。会通过 emit
关键字触发事件。
modifier isOwner() {
require(msg.sender == owner, "Caller is not owner");
_;
}
modifier
声明一个函数修饰器,这有点像 python 和 javascript 的修饰器。_;
是一个固定写法,表示被修饰的函数体内容。
msg.sender
是一个全局变量,表示当前调用者或者智能合约的 address。
require
检查条件不满足时抛出异常,并停止执行。
这段代码的意思就是声明一个函数器,用于检查发送者是否等于智能合约中的拥有者。
constructor() {
owner = msg.sender;
emit OwnerSet(address(0), owner);
}
constructor
是构造函数,跟我们理解的 class 的构造函数一样。智能合约部署时执行。函数内设置 owner
的变量等于部署者的 address,并触发事件 OwnerSet
。
function changeOwner(address newOwner) public isOwner {
emit OwnerSet(owner, newOwner);
owner = newOwner;
}
定义一个函数 changeOwner 修改智能合约的所有者,其中用到了刚才定义的修饰器 isOwner
,这个写法跟 python 的@符号不一样。
function getOwner() external view returns (address) {
return owner;
}
定义一个函数 getOwner
返回智能合约的所有者。这里用到了一个 external
属性,顾名思义这个函数只能在合约之外调用,但是不能被合约内的其他函数调用,这也是于 public
的不同之处。
总结一下
这个例子涉及到知识点有点多,private
、external
限制条件,address
数字类型,msg.sender
全局变量,require
条件检测,事件,函数修饰器。