Solodity知识点集 — Ownable合约(五)
OpenZeppelin库的Ownable
合约
OpenZeppelin 是主打安保和社区审查的智能合约库,您可以在自己的 DApps中引用。
下面是一个来自 OpenZeppelin
Solidity 库的 Ownable
合约:
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0));
OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
所以Ownable 合约基本都会这么干:
-
合约创建,构造函数
先行
,将其owner
设置为msg.sender
(其部署者) -
为它加上一个修饰符
onlyOwner
,它会限制陌生人的访问,将访问某些函数的权限锁定在owner
上。 -
允许将合约所有权转让给他人。
Gas
在 Solidity 中,你的用户想要每次执行你的 DApp 都需要支付一定的 gas,gas 可以用以太币购买,因此,用户每次跑 DApp 都得花费以太币。
一个 DApp 收取多少 gas 取决于功能逻辑的复杂程度。在以太坊中代码的编程语言,比其他任何编程语言都更强调优化。
为什么要用 gas 来驱动?
以太坊就像一个巨大、缓慢、但非常安全的电脑。当你运行一个程序的时候,网络上的每一个节点都在进行相同的运算,以验证它的输出 —— 这就是所谓的”去中心化“ 由于数以千计的节点同时在验证着每个功能的运行,这可以确保它的数据不会被被监控,或者被刻意修改。
可能会有用户用无限循环堵塞网络,抑或用密集运算来占用大量的网络资源,为了防止这种事情的发生,以太坊的创建者为以太坊上的资源制定了价格,想要在以太坊上运算或者存储,你需要先付费。
省 gas 的招数:结构封装 (Struct packing)
如果一个 struct
中有多个 uint
,则尽可能使用较小的 uint
, Solidity
会将这些 uint
打包在一起,从而占用较少的存储空间。例如:
struct NormalStruct {
uint a;
uint b;
uint c;
}
struct MiniMe {
uint32 a;
uint32 b;
uint c;
}
// 因为使用了结构打包,`mini` 比 `normal` 占用的空间更少
NormalStruct normal = NormalStruct(10, 20, 30);
MiniMe mini = MiniMe(10, 20, 30);
把同样类型的变量放一起(即在 struct 中将把变量按照类型依次放置),这样 Solidity 可以将存储空间最小化。例如,有两个 struct
:
uint c; uint32 a; uint32 b; 和 uint32 a; uint c; uint32 b;
前者比后者需要的gas更少,因为前者把uint32
放一起了。
时间单位
Solidity 使用自己的本地时间单位。变量 now 将返回当前的unix时间戳
Solidity
还包含秒(seconds)
,分钟(minutes)
,小时(hours)
,天(days)
,周(weeks)
和 年(years)
等时间单位。它们都会转换成对应的秒数放入 uint
中。
uint lastUpdated;
// 将‘上次更新时间’ 设置为 ‘现在’
function updateTimestamp() public {
lastUpdated = now;
}
// 如果到上次`updateTimestamp` 超过5分钟,返回 'true'
// 不到5分钟返回 'false'
function fiveMinutesHavePassed() public view returns (bool) {
return (now >= (lastUpdated + 5 minutes));
}
公有函数和安全性
你必须仔细地检查所有声明为 public
和 external
的函数,一个个排除用户滥用它们的可能,谨防安全漏洞。请记住,如果这些函数没有类似 onlyOwner
这样的函数修饰符,用户能利用各种可能的参数去调用它们。