首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

【区块链安全 | 第三十篇】合约(四)

  • 25-04-24 13:42
  • 2995
  • 14098
blog.csdn.net

文章目录

  • 合约
    • 继承
      • 函数重写(Function Overriding)
      • 修饰符重写(Modifier Overriding)
      • 构造函数(Constructors)
      • 基合约构造函数的参数
      • 多重继承与线性化
      • 继承相同名称的不同成员类型

在这里插入图片描述

合约

继承

Solidity 支持多重继承,并且具有多态性特性。

多态性意味着函数调用(无论是内部调用还是外部调用)始终会执行继承体系中最底层合约中具有相同名称和参数类型的函数。为了启用多态性,必须在继承体系中的每个函数上显式使用 virtual 和 override 关键字。

我们可以通过显式指定合约名来调用继承体系中更高层次的函数,例如:ContractName.functionName(),或者使用 super.functionName() 来调用继承结构中的上一级函数(参考下文“扁平化继承结构”)。

当一个合约继承其他合约时,区块链上只会创建一个合约实例,所有父合约的代码会被编译到这个实例中。这意味着对父合约函数的所有内部调用实际上是普通的内部函数调用(例如,super.f(…) 会使用 JUMP 操作码,而不是消息调用)。

状态变量遮蔽(shadowing)会被视为错误:如果某个父合约中已经声明了变量 x,子合约中不能再声明同名变量。

Solidity 的继承系统在整体上类似于 Python 的继承,尤其是在处理多重继承时,但也存在一些差异。

具体示例如下:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

contract Owned {
    address payable owner;
    constructor() { owner = payable(msg.sender); }
}

// 使用 `is` 关键字派生自另一个合约。
// 派生合约可以访问所有非 private 的成员,包括 internal 函数和状态变量。
// 这些成员无法通过 `this` 关键字从外部访问。
contract Emittable is Owned {
    event Emitted();

    // 使用 `virtual` 关键字表示该函数可以被子类重写。
    function emitEvent() virtual public {
        if (msg.sender == owner)
            emit Emitted();
    }
}

// 这些抽象合约只是为了让编译器知道接口。注意没有函数体的声明。
// 如果一个合约未实现所有函数,就只能作为接口使用。
abstract contract Config {
    function lookup(uint id) public virtual returns (address adr);
}

abstract contract NameReg {
    function register(bytes32 name) public virtual;
    function unregister() public virtual;
}

// 支持多重继承。注意:`Owned` 同时是 `Emittable` 的父类,
// 但在最终合约中只会有一个 `Owned` 实例(类似 C++ 的虚继承)。
contract Named is Owned, Emittable {
    constructor(bytes32 name) {
        Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);
        NameReg(config.lookup(1)).register(name);
    }

    // 函数可以通过相同的名称和参数类型进行重写。
    // 如果返回值类型不一样,将导致编译错误。
    // 无论是内部调用还是消息调用,都会考虑重写关系。
    // 如果我们要重写函数,必须使用 `override` 关键字。
    // 如果这个函数还需要被其他合约重写,则还需要再次声明 `virtual`。
    function emitEvent() public virtual override {
        if (msg.sender == owner) {
            Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);
            NameReg(config.lookup(1)).unregister();
            // 仍然可以调用被重写的父类函数。
            Emittable.emitEvent();
        }
    }
}

// 如果构造函数需要参数,则必须在派生合约的构造器中提供,
// 可以在构造函数声明中传参,也可以通过修饰器风格传参。
contract PriceFeed is Owned, Emittable, Named("GoldFeed") {
    uint info;

    function updateInfo(uint newInfo) public {
        if (msg.sender == owner) info = newInfo;
    }

    // 这里只声明 `override` 而不是 `virtual`,
    // 意味着继承自 PriceFeed 的合约不能再重写 emitEvent。
    function emitEvent() public override(Emittable, Named) { 
        Named.emitEvent(); 
    }

    function get() public view returns
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
注:本文转载自blog.csdn.net的的文章"https://blog.csdn.net/2301_77485708/article/details/147039870"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

128
网络空间安全
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top