solidty提升篇-智能协议-合约的所有权-gas-带参数的函数修饰符

智能协议的永固性

有几点以太坊上的 DApp 跟普通的应用程序有着天壤之别。

把智能协议传上以太坊之后,它就变得不可更改, 这种永固性意味着你的代码永远不能被调整或更新。
你编译的程序会一直,永久的,不可更改的,存在以太坊上。这就是 Solidity 代码的安全性如此重要的一个原因。如果你的智能协议有任何漏洞,即使你发现了也无法补救。你只能让你的用户们放弃这个智能协议,然后转移到一个新的修复后的合约上。

外部依赖关系

在引用外部关系的时候,不能硬编码,而要采用“函数”,以便于 DApp 的关键部分可以以参数形式修改。

指定合约的“所有权”

Ownable 合约基本都会这么干:

合约创建,构造函数先行,将其 owner 设置为msg.sender(其部署者)

为它加上一个修饰符 onlyOwner,它会限制陌生人的访问,将访问某些函数的权限锁定在 owner 上。

允许将合约所有权转让给他人。

构造函数:

function Ownable()是一个 _ constructor_ (构造函数),构造函数不是必须的,它与合约同名,构造函数一生中唯一的一次执行,就是在合约最初被创建的时候。

函数修饰符 onlyOwner-在禁止第三方修改我们的合约的同时,只允许自己去修改:

modifier onlyOwner()。 修饰符跟函数很类似,不过是用来修饰其他已有函数用的, 在其他语句执行前,为它检查下先验条件。 在这个例子中,我们就可以写个修饰符 onlyOwner 检查下调用者,确保只有合约的主人才能运行本函数。
函数修饰符看起来跟函数没什么不同,不过关键字modifier 告诉编译器,这是个modifier(修饰符),而不是个function(函数)。它不能像函数那样被直接调用,只能被添加到函数定义的末尾,用以改变函数的行为。

/**
 * @dev 调用者不是‘主人’,就会抛出异常
 */
modifier onlyOwner() {
  require(msg.sender == owner);
  _;
}
onlyOwner 函数修饰符是这么用的:

contract MyContract is Ownable {
  event LaughManiacally(string laughter);

  //注意! `onlyOwner`上场 :
  function likeABoss() external onlyOwner {
    LaughManiacally("Muahahahaha");
  }
}

Gas

一个 DApp 收取多少 gas 取决于功能逻辑的复杂程度,一次操作所需要花费的 gas 等于这个操作背后的所有运算花销的总和。
注意:如果你使用侧链,倒是不一定需要付费,比如咱们在 Loom Network 上构建的 CryptoZombies 就免费。

省 gas 的招数:结构封装 (Struct packing)

当 uint 定义在一个 struct 中的时候,尽量使用最小的整数子类型以节约空间。 并且把同样类型的变量放一起(即在 struct 中将把变量按照类型依次放置),这样 Solidity 可以将存储空间最小化。例如,有两个 struct:

uint c; uint32 a; uint32 b; 和 uint32 a; uint c; uint32 b;

前者比后者需要的gas更少,因为前者把uint32放一起了。

时间单位

Solidity 使用自己的本地时间单位。
变量 now 将返回当前的unix时间戳(自1970年1月1日以来经过的秒数)
Solidity 还包含秒(seconds),分钟(minutes),小时(hours),天(days),周(weeks) 和 年(years) 等时间单位。它们都会转换成对应的秒数放入 uint 中。所以 1分钟 就是 60,1小时是 3600(60秒×60分钟),1天是86400(24小时×60分钟×60秒),以此类推。

带参数的函数修饰符

修饰符可以像函数一样接收参数,是“宿主”函数把参数传递给它的修饰符的。
记住,修饰符的最后一行为 _;,表示修饰符调用结束后返回,并执行调用函数余下的部分。

// 存储用户年龄的映射
mapping (uint => uint) public age;

// 限定用户年龄的修饰符
modifier olderThan(uint _age, uint _userId) {
  require(age[_userId] >= _age);
  _;
}

// 必须年满16周岁才允许开车 (至少在美国是这样的).
// 我们可以用如下参数调用`olderThan` 修饰符:
function driveCar(uint _userId) public olderThan(16, _userId) {
  // 其余的程序逻辑
}

猜你喜欢

转载自blog.csdn.net/weixin_52723971/article/details/125644424