• Solidity智能合约开发 — 4.3-合约的事件和继承


    1. 事件

    Solidity中的事件(event)是EVM上日志的抽象,它具有两个特点:

    • 响应:应用程序(ether.js)可以通过RPC接口订阅和监听这些事件,并在前端做响应。
    • 经济:事件是EVM上比较经济的存储数据的方式,每个大概消耗2,000-5,000 gas不等。相比之下,存储一个新的变量至少需要20,000 gas

    事件的声明由event关键字开头,然后跟事件名称,括号里面写好事件需要记录的变量类型和变量名。以ERC20代币合约的Transfer事件为例:

    event Transfer(address indexed from, address indexed to, uint256 value);

     每个事件最多有3个带indexed的变量,Transfer事件共记录了3个变量fromtovalue,分别对应代币的转账地址,接收地址和转账数量。同时fromto前面带着indexed关键字,表示很重要,程序可以轻松的筛选出特定转账地址和接收地址的转账事件

    1. // 定义_transfer函数,执行转账逻辑
    2. function _transfer(
    3. address from,
    4. address to,
    5. uint256 amount
    6. ) external {
    7. _balances[from] = 10000000; // 给转账地址一些初始代币
    8. _balances[from] -= amount; // from地址减去转账数量
    9. _balances[to] += amount; // to地址加上转账数量
    10. // 释放事件
    11. emit Transfer(from, to, amount);
    12. }

    2. 继承

    继承(inheritance),包括简单继承,多重继承,以及修饰器(modifier)和构造函数(constructor)的继承。

    virtual: 父合约中的函数,如果希望子合约重写,需要加上virtual关键字

    override:子合约重写了父合约中的函数,需要加上override关键。

    简单继承

    1. contract Yeye {
    2. event Log(string msg);
    3. // 定义3个function: hip(), pop(), man(),Log值为Yeye。
    4. function hip() public virtual{
    5. emit Log("Yeye");
    6. }
    7. function pop() public virtual{
    8. emit Log("Yeye");
    9. }
    10. function yeye() public virtual {
    11. emit Log("Yeye");
    12. }
    13. }

    我们再定义一个合约Baba 

    1. contract Baba is Yeye{
    2. // 继承两个function: hip()和pop(),输出改为Baba。
    3. function hip() public virtual override{
    4. emit Log("Baba");
    5. }
    6. function pop() public virtual override{
    7. emit Log("Baba");
    8. }
    9. function baba() public virtual{
    10. emit Log("Baba");
    11. }
    12. }

    多重继承

    1. 继承时要按辈分最高到最低的顺序排。比如我们写一个Erzi合约,继承Yeye合约和Baba合约,那么就要写成contract Erzi is Yeye, Baba,而不能写成contract Erzi is Baba, Yeye,不然就会报错。
    2. 如果某一个函数在多个继承的合约里都存在,比如例子中的hip()pop(),在子合约里必须重写,不然会报错。
    3. 重写在多个父合约中重名函数时,override关键字后面要加上父合约名字,例如override(Yeye, Baba)
    1. contract Erzi is Yeye, Baba{
    2. // 继承两个function: hip()和pop(),输出值为Erzi。
    3. function hip() public virtual override(Yeye, Baba){
    4. emit Log("Erzi");
    5. }
    6. function pop() public virtual override(Yeye, Baba) {
    7. emit Log("Erzi");
    8. }

    修饰器的继承

    Solidity中的修饰器(Modifier)同样可以继承,用法与函数继承类似,在相应的地方加virtualoverride关键字即可。

    构造函数的继承

    子合约有两种方法继承父合约的构造函数。举个简单的例子,父合约A里面有一个状态变量a,并由构造函数的参数来确定:

    1. // 构造函数的继承
    2. abstract contract A {
    3. uint public a;
    4. constructor(uint _a) {
    5. a = _a;
    6. }
    7. }
    1. 在继承时声明父构造函数的参数,例如:contract B is A(1)
    2. 在子合约的构造函数中声明构造函数的参数,例如:
    1. contract C is A {
    2. constructor(uint _c) A(_c * _c) {}
    3. }

    调用父合约的函数

    子合约有两种方式调用父合约的函数,直接调用和利用super关键字。

    • 直接调用:子合约可以直接用父合约名.函数名()的方式来调用父合约函数,例如Yeye.pop()
    1. function callParent() public{
    2. Yeye.pop();
    3. }
    • super关键字:子合约可以利用super.函数名()来调用最近的父合约函数。solidity继承关系按声明时从右到左的顺序是:contract Erzi is Yeye, Baba,那么Baba是最近的父合约,super.pop()将调用Baba.pop()而不是Yeye.pop()
    1. function callParentSuper() public{
    2. // 将调用最近的父合约函数,Baba.pop()
    3. super.pop();
    4. }
  • 相关阅读:
    [博弈论][思维]Bragging Dice 2022杭电多校第5场 1010
    ROS2自学笔记:launch文件完整编写流程
    【Python 零基础入门】Pandas
    使用Go env命令设置Go的环境
    Spring Boot 手写starter!!!
    局域网如何进行内网连接和外网连接
    Mac搭建Jmeter分布式加压步骤
    2023Jenkins连接k8s
    reactHook实现EventBus
    python指针参数学习笔记
  • 原文地址:https://blog.csdn.net/qincheng168/article/details/128071484