《Solidity 简易速速上手小册》第3章:Solidity 语法基础(2024 最新版)

news2025/1/16 18:55:50

在这里插入图片描述

文章目录

  • 3.1 变量和类型
    • 3.1.1 基础知识解析
      • 详细解析变量类型
      • 深入数据类型
      • 理解变量可见性
    • 3.1.2 重点案例:创建一个简单的存储合约
      • 案例 Demo:编写一个简单的数字存储合约
      • 案例代码:SimpleStorage.sol
      • 在 Remix 中进行交互:
      • 拓展操作:
    • 3.1.3 拓展案例 1:使用不同类型的变量
      • 案例 Demo:创建一个管理用户余额的合约
      • 案例代码:BalanceManager.sol
      • 在 Remix 或 Truffle 中进行交互
      • 拓展操作
    • 3.1.4 拓展案例 2:结构体和数组的使用
      • 案例 Demo:创建一个管理用户信息的合约
      • 案例代码:UserManagement.sol
      • 在 Remix 或 Truffle 中进行测试
      • 拓展操作
  • 3.2 函数和控制结构
    • 3.2.1 基础知识解析
      • 深入理解函数
      • 掌握控制结构
      • 使用函数修饰符
    • 3.2.2 重点案例:创建有条件逻辑的合约
      • 案例 Demo:编写一个基于条件逻辑的积分管理合约
      • 案例代码:PointsManager.sol
      • 在 Remix 或 Truffle 中进行测试
      • 拓展实践
    • 3.2.3 拓展案例 1:循环遍历用户
      • 案例 Demo:使用循环来更新用户信息
      • 案例代码:UserUpdater.sol
      • 在 Remix 或 Truffle 中进行测试
      • 拓展实践
    • 3.2.4 拓展案例 2:使用函数修饰符
      • 案例 Demo:使用函数修饰符限制访问
      • 案例代码:OwnerContract.sol
      • 在 Remix 或 Truffle 中进行测试
      • 拓展实践
  • 3.3 事件和继承
    • 3.3.1 基础知识解析
      • 深入理解事件
      • 继承的概念和应用
      • 使用场景和最佳实践
    • 3.3.2 重点案例:创建一个发出事件的合约
      • 案例 Demo:编写一个记录用户活动的合约
      • 案例代码:ActivityLogger.sol
      • 在 Remix 或 Truffle 中进行测试
      • 拓展实践
    • 3.3.3 拓展案例 1:使用继承来组织合约
      • 案例 Demo:构建基于继承的多层次用户管理系统
      • 案例代码
        • BaseContract.sol
        • AdminContract.sol
        • UserContract.sol
      • 测试和部署
      • 拓展实践
    • 3.3.4 拓展案例 2:多重继承和接口
      • 案例 Demo:创建一个集成多个功能的智能合约
      • 案例代码
        • Logger.sol
        • Authenticator.sol
        • ComprehensiveContract.sol
      • 测试和部署
      • 拓展实践

3.1 变量和类型

在 Solidity 的世界里,变量和类型是构建智能合约的基石,就像是为你的区块链冒险准备的基础装备一样。

3.1.1 基础知识解析

进入 Solidity 的世界,变量和类型就像是你的基本工具箱。理解它们就像是学会了如何在区块链上搭建房屋的基本技能。

详细解析变量类型

  1. 状态变量(State Variables):

    • 存储在区块链上,是合约的永久部分。
    • 类似于传统编程中的全局变量,但它们的生命周期与合约相同。
  2. 局部变量(Local Variables):

    • 在函数内声明和使用。
    • 生命周期仅限于函数的执行期间。
  3. 全局变量(Global Variables):

    • Solidity 提供的特殊变量,提供区块链的信息,如 msg.sender(函数调用者的地址)。

深入数据类型

  1. 值类型(Value Types):

    • 直接持有数据,包括:
      • 整数类型(如 uintint)。
      • 布尔型(bool)。
      • 地址类型(address)。
    • 这些类型在赋值或传递时被复制。
  2. 引用类型(Reference Types):

    • 指向数据存储位置的类型,包括:
      • 数组(固定大小和动态大小)。
      • 结构体(struct)。
      • 映射(mapping)。
    • 它们不是复制值,而是引用存储位置。
  3. 特殊数据类型:

    • bytes:固定大小或动态大小的字节序列。
    • enum:用户定义的类型,用于创建具名常量。

理解变量可见性

  1. 公共(public):

    • 对所有人可见,自动生成 getter 函数。
  2. 私有(private):

    • 仅在定义它们的合约内可见。
  3. 内部(internal):

    • 类似于私有,但对继承合约也可见。
  4. 外部(external):

    • 只能通过外部调用访问。

掌握 Solidity 中的变量和类型就像是在区块链的建筑工地上熟悉每一件工具。了解它们的不同特性和用途,可以帮助你更有效地构建和维护你的智能合约。就像是一个优秀的工匠,知道什么时候该用锤子,什么时候该用螺丝刀。准备好了吗?让我们拿起工具,开始构建吧!

3.1.2 重点案例:创建一个简单的存储合约

假设你是一名热心的 Solidity 开发者,希望创建一个基础但实用的合约,让用户能够存储和检索一个数字。这个案例就像是在学习建筑时制作的第一个模型房子一样,基础但至关重要。

案例 Demo:编写一个简单的数字存储合约

  1. 初始化环境:

    • 选择一个合适的开发环境,比如 Remix IDE 或本地配置的 Truffle 项目。
  2. 编写合约:

    • 创建一个新的 Solidity 文件,命名为 SimpleStorage.sol
    • 在文件中定义一个合约 SimpleStorage,包含一个可以设置和获取值的状态变量。
  3. 定义状态变量和函数:

    • 使用 uint 类型定义一个状态变量来存储一个数字。
    • 编写一个函数来设置这个数字。
    • 编写另一个函数来检索这个数字。
  4. 编译和部署合约:

    • 在 Remix 或 Truffle 中编译合约。
    • 部署合约到 Ethereum 测试网络或本地开发环境。
  5. 测试合约功能:

    • 通过调用设置和获取函数,测试合约的存储和检索功能。

案例代码:SimpleStorage.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SimpleStorage {
    uint private storedNumber;

    function setNumber(uint _number) public {
        storedNumber = _number;
    }

    function getNumber() public view returns (uint) {
        return storedNumber;
    }
}

在这个 SimpleStorage 合约中,我们定义了一个私有状态变量 storedNumber 来存储一个无符号整数。我们提供了 setNumber 函数来更改这个数值,以及一个 getNumber 函数来检索它。

在 Remix 中进行交互:

  • 编译并部署 SimpleStorage 合约。
  • 使用 Remix 提供的界面调用 setNumber 函数存储一个值。
  • 然后调用 getNumber 函数检查存储的值是否正确。

拓展操作:

  • 添加事件: 你可以在合约中添加事件来记录每次数字更改的操作。
  • 权限控制: 为了提高合约的安全性,你可以添加只允许合约的所有者更改数字的逻辑。

通过这个简单的存储合约案例,你不仅学会了如何创建和部署基本的智能合约,还理解了如何通过合约交互修改和读取状态变量的值。这是学习 Solidity 的重要一步,就像是学会了如何建造和使用工具箱中的基本工具一样。

3.1.3 拓展案例 1:使用不同类型的变量

设想你正在构建一个稍微复杂的智能合约,需要处理不同类型的数据。这就像是你在建造一个多功能的太空站,它不仅能存储基本的供应品,还能处理复杂的数据和交易。

案例 Demo:创建一个管理用户余额的合约

  1. 初始化环境:
    • 选择你的开发环境,比如 Remix IDE 或一个本地 Truffle 项目。
  2. 编写合约:
    • 创建一个新的 Solidity 文件 BalanceManager.sol
    • 定义一个合约 BalanceManager
  3. 定义变量和结构:
    • 使用 address 类型来存储用户地址。
    • 使用 mapping 类型来关联地址和余额。
  4. 编写函数来管理余额:
    • 编写一个函数来更新用户的余额。
    • 编写另一个函数来获取指定用户的余额。
  5. 编译和部署合约:
    • 在你选择的环境中编译合约。
    • 将合约部署到以太坊测试网络或你的本地开发环境。
  6. 测试合约功能:
    • 测试更新和获取余额的功能。

案例代码:BalanceManager.sol

solidityCopy code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract BalanceManager {
    mapping(address => uint) public balances;

    function updateBalance(uint newBalance) public {
        balances[msg.sender] = newBalance;
    }

    function getBalance(address user) public view returns (uint) {
        return balances[user];
    }
}

BalanceManager 合约中,我们使用了 mapping 类型来关联用户地址和其余额。updateBalance 函数允许用户设置自己的余额,而 getBalance 函数允许任何人查询指定用户的余额。

在 Remix 或 Truffle 中进行交互

  • 部署合约后,调用 updateBalance 函数来设置一个地址的余额。
  • 使用 getBalance 函数来验证余额是否正确更新。

拓展操作

  • 添加事件: 可以添加事件来记录每当用户余额更新时的情况。
  • 增加安全性: 实现一些安全措施,比如确保只有用户本人才能更新自己的余额。

通过这个案例,你不仅学会了如何在智能合约中处理不同类型的变量,还理解了如何创建更为动态和交互式的合约功能。

3.1.4 拓展案例 2:结构体和数组的使用

假设你是一位热衷于探索更高级 Solidity 特性的开发者,现在你想要创建一个合约,用于管理多个用户的信息。在这种情况下,结构体(Structs)和数组(Arrays)是完美的工具。

案例 Demo:创建一个管理用户信息的合约

  1. 定义用户结构体:

    • 创建一个结构体 User,包含用户的各种信息,比如姓名、ID 和余额。
  2. 使用数组存储结构体:

    • 定义一个 User 结构体的动态数组,用于存储多个用户信息。
  3. 编写函数来管理用户信息:

    • 实现添加新用户、获取用户信息和更新用户信息的函数。
  4. 测试合约功能:

    • 部署合约到测试网络或本地开发环境,并测试添加和获取用户信息的功能。

案例代码:UserManagement.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract UserManagement {
    struct User {
        string name;
        uint id;
        uint balance;
    }

    User[] private users;

    function addUser(string memory _name, uint _id, uint _balance) public {
        users.push(User(_name, _id, _balance));
    }

    function getUser(uint _index) public view returns (string memory, uint, uint) {
        require(_index < users.length, "User does not exist.");
        User memory user = users[_index];
        return (user.name, user.id, user.balance);
    }

    function updateUserBalance(uint _index, uint _newBalance) public {
        require(_index < users.length, "User does not exist.");
        User storage user = users[_index];
        user.balance = _newBalance;
    }
}

在这个 UserManagement 合约中,我们定义了一个 User 结构体来存储用户信息,并使用一个动态数组 users 来管理多个用户。合约提供了添加新用户、获取特定用户信息和更新用户余额的功能。

在 Remix 或 Truffle 中进行测试

  • 编译并部署 UserManagement 合约。
  • 使用合约提供的函数测试添加用户、获取用户信息和更新用户余额的功能。
  • 观察合约如何处理多个用户的信息。

拓展操作

  • 增加安全性: 可以添加权限控制,确保只有合约所有者或特定用户能够添加或更新用户信息。
  • 优化存储: 考虑使用映射(Mapping)来更高效地索引和检索用户信息。

通过这个案例,你可以看到结构体和数组在管理复杂数据方面的强大能力。它们让你能够在智能合约中以有组织和高效的方式处理大量信息,就像是为你的区块链应用构建了一个健壮而灵活的数据框架。

通过掌握 Solidity 中的变量和类型,你就能开始构建智能合约的基础结构了。记住,合适的变量和类型选择对合约的性能和安全性至关重要。就像在太空探险中选择正确的装备一样,正确的变量和类型能让你的合约在区块链的星际旅行中更加顺利。

3.2 函数和控制结构

跳进 Solidity 的世界,函数和控制结构就像是你的魔法书,里面充满了神奇的咒语和符号,帮助你操控你的智能合约。

3.2.1 基础知识解析

在 Solidity 的世界中,函数和控制结构是编织智能合约魔法的基础。它们就像是一套复杂的舞步,需要精确和逻辑来指导合约的行为。

深入理解函数

  1. 函数的本质:

    • 函数是一系列指令的集合,用于执行特定的任务。
    • 在 Solidity 中,函数可以读取和修改合约的状态。
  2. 函数类型:

    • 纯函数(pure): 不读取也不修改合约状态的函数。
    • 视图函数(view): 只读取不修改合约状态的函数。
    • 支付函数(payable): 接收以太币(ETH)的函数。
  3. 函数参数和返回值:

    • 函数可以有参数和返回值,参数用于传递数据,返回值用于输出数据。

掌握控制结构

  1. 条件语句(if, else):

    • 允许根据条件执行不同的代码路径。
    • 在 Solidity 中,这是处理决策逻辑的关键。
  2. 循环(for, while, do while):

    • 使你能够重复执行某段代码,直到满足特定条件。
    • 在处理数组或映射时特别有用。

使用函数修饰符

  1. 修饰符概念:

    • 函数修饰符是可重用的代码块,用于修改函数的行为。
    • 它们常用于访问控制和检查前置条件。
  2. 常见修饰符:

    • public:任何人都可以调用的函数。
    • private:只能在合约内部调用的函数。
    • internal:只能在合约内部及其派生合约中调用的函数。
    • external:只能从合约外部调用的函数。

理解了函数和控制结构,你的智能合约就像是被精心编排的舞蹈,每个步骤都清晰、有序。这些基本元素不仅是构建合约的基石,还能确保你的合约逻辑严密、有效。

3.2.2 重点案例:创建有条件逻辑的合约

想象你是一个热心的开发者,准备创造一个智能合约来管理用户积分。这个合约将使用条件逻辑来处理不同的情景,就像是一个游戏中的关卡选择器。

案例 Demo:编写一个基于条件逻辑的积分管理合约

  1. 初始化开发环境:

    • 选择合适的开发工具,例如 Remix IDE 或本地的 Truffle 环境。
  2. 创建智能合约:

    • 新建一个 Solidity 文件,比如命名为 PointsManager.sol
    • 定义合约框架和所需的状态变量。
  3. 编写条件逻辑函数:

    • 创建函数来增加用户积分。
    • 使用 if 语句来判断用户是否达到某个积分阈值,并据此执行不同的操作。
  4. 部署和测试合约:

    • 在选定的环境中部署合约。
    • 测试不同积分阈值下的合约逻辑。

案例代码:PointsManager.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract PointsManager {
    mapping(address => uint256) public userPoints;

    function addPoints(address user, uint256 points) public {
        userPoints[user] += points;

        // 检查用户是否达到积分阈值
        if (userPoints[user] >= 100) {
            // 用户达到积分阈值的特殊逻辑
            // 例如:升级用户等级、发放奖励等
        }
    }
}

PointsManager 合约中,我们使用了一个映射来跟踪用户的积分,并创建了一个 addPoints 函数来增加用户积分。通过在函数中添加 if 语句,我们为达到特定积分阈值的用户实现了特殊的逻辑。

在 Remix 或 Truffle 中进行测试

  • 部署合约到你选择的开发环境。
  • 通过调用 addPoints 函数测试不同用户的积分情况。
  • 观察当用户达到特定积分时,合约是否按预期执行特殊逻辑。

拓展实践

  • 引入事件: 在用户达到积分阈值时触发事件,以便于跟踪和记录。
  • 更复杂的条件逻辑: 实现更多的条件判断,比如不同积分阶段提供不同的奖励。

通过这个案例,你不仅实践了 Solidity 中的条件逻辑,也学会了如何根据实际情况调整合约的行为。这就像是在编程的世界中设置了一个智能的路标,引导你的合约在不同情景下采取不同的行动。

3.2.3 拓展案例 1:循环遍历用户

设想你正在开发一个更高级的智能合约,需要处理和更新多个用户的信息。在这种情况下,使用循环来遍历用户数组将是一种高效的方法。

案例 Demo:使用循环来更新用户信息

  1. 设置开发环境:

    • 选择一个开发工具,比如 Remix IDE 或本地的 Truffle 环境。
  2. 编写智能合约:

    • 创建一个新的 Solidity 文件,命名为 UserUpdater.sol
    • 定义一个包含用户信息的结构体和一个存储多个用户的数组。
  3. 编写循环逻辑:

    • 创建一个函数,使用 for 循环遍历用户数组,并对每个用户执行特定操作。
  4. 部署和测试合约:

    • 在所选环境中部署合约。
    • 测试循环逻辑是否正确处理每个用户的信息。

案例代码:UserUpdater.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract UserUpdater {
    struct User {
        address addr;
        uint256 score;
    }

    User[] public users;

    function addUser(address _addr, uint256 _score) public {
        users.push(User(_addr, _score));
    }

    function updateAllScores(uint256 _scoreIncrement) public {
        for (uint i = 0; i < users.length; i++) {
            users[i].score += _scoreIncrement;
        }
    }
}

UserUpdater 合约中,我们定义了一个 User 结构体和一个 users 数组来存储用户信息。addUser 函数用于添加新用户,而 updateAllScores 函数使用 for 循环来更新所有用户的分数。

在 Remix 或 Truffle 中进行测试

  • 编译并部署 UserUpdater 合约。
  • 使用 addUser 函数添加几个用户。
  • 调用 updateAllScores 函数并检查是否所有用户的分数都正确更新。

拓展实践

  • 引入条件检查: 在循环中添加条件语句,以实现更复杂的业务逻辑。
  • 优化性能: 考虑合约的 Gas 成本,特别是当处理大量数据时。

通过这个案例,你不仅学会了如何在 Solidity 中使用循环来有效处理多个元素,还掌握了结构体和数组的使用。这些技能将帮助你建立更复杂和动态的智能合约,就像是在区块链的世界中搭建了一座多功能的建筑。

3.2.4 拓展案例 2:使用函数修饰符

假设你正在开发一个智能合约,需要确保某些关键功能只能由合约的所有者调用。在这种情况下,使用函数修饰符来添加权限控制是非常有效的方法。

案例 Demo:使用函数修饰符限制访问

  1. 设置开发环境:

    • 选择合适的开发环境,比如 Remix IDE 或 Truffle。
  2. 编写智能合约:

    • 创建一个新的 Solidity 文件,例如 OwnerContract.sol
    • 定义一个合约,其中包括所有者地址和需要受限制的功能。
  3. 定义函数修饰符:

    • 创建一个修饰符,用于检查调用者是否是合约的所有者。
    • 将这个修饰符应用于需要限制访问的函数。
  4. 部署和测试合约:

    • 在所选环境中部署合约。
    • 测试受限函数,确保只有所有者可以调用它们。

案例代码:OwnerContract.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract OwnerContract {
    address public owner;

    constructor() {
        owner = msg.sender; // 设置部署合约的人为所有者
    }

    // 修饰符:只有所有者可以调用
    modifier onlyOwner() {
        require(msg.sender == owner, "Only the owner can call this function.");
        _;
    }

    function changeOwner(address _newOwner) public onlyOwner {
        owner = _newOwner;
    }

    // 其他受限制的功能...
}

在这个 OwnerContract 合约中,我们定义了一个 onlyOwner 修饰符来确保只有合约的所有者可以执行某些操作。例如,changeOwner 函数允许当前所有者将所有权转移给另一个地址,但是由于 onlyOwner 修饰符的限制,只有当前所有者才能调用此函数。

在 Remix 或 Truffle 中进行测试

  • 部署 OwnerContract 合约。
  • 作为所有者尝试调用 changeOwner 函数,并观察操作是否成功。
  • 从非所有者账户尝试相同操作,并确保操作失败。

拓展实践

  • 增加多个修饰符: 对于更复杂的访问控制,可以结合多个修饰符使用。
  • 实现权限日志: 使用事件记录所有权变更或特定函数调用。

通过这个案例,你学会了如何使用函数修饰符来增加智能合约的安全性。就像是在你的数字城堡中增加了一道安全门,确保只有授权人员才能进入。

3.3 事件和继承

欢迎来到 Solidity 的另一个激动人心的章节:事件和继承。这就像学习如何给你的智能合约装上广播系统和搭建多层建筑的技术。

3.3.1 基础知识解析

在 Solidity 的世界里,事件和继承是构建复杂、高效和模块化智能合约的关键工具。就像是在一个复杂的电子设备中添加指示灯和模块化组件。

深入理解事件

  1. 事件(Events)的作用:

    • 用于在区块链上记录日志和通知订阅者(如前端应用)合约状态的改变。
    • 提供了一种低成本的数据存储方式。
  2. 事件的特性:

    • 可索引参数(indexed): 最多三个参数可以被标记为 indexed,使它们在日志中可搜索。
    • 数据存储: 事件数据存储在交易日志中,与区块链的状态分开。

继承的概念和应用

  1. 继承的基本原理:

    • 允许一个合约继承另一个合约的方法和变量,减少代码重复,提高复用性。
    • 类似于面向对象编程中的继承概念。
  2. 多重继承和接口:

    • Solidity 支持多重继承,意味着一个合约可以继承多个父合约。
    • 接口可以用于定义合约之间的标准交互方式。

使用场景和最佳实践

  1. 事件的使用场景:

    • 当合约状态改变时(如转账、状态更新)发出事件。
    • 为了节省成本,将非必要数据存储在事件而非区块链状态中。
  2. 继承的最佳实践:

    • 识别共通功能,将其放在基础合约中。
    • 通过继承扩展和定制基础合约的行为。
    • 注意合约大小限制,过多的继承可能导致部署问题。

通过深入理解事件和继承,你的智能合约开发就像是获得了额外的维度。事件让合约与外部世界沟通,而继承带来了结构清晰、易于管理的代码架构。

3.3.2 重点案例:创建一个发出事件的合约

设想你正在开发一个智能合约,旨在记录并通知用户的活动或状态变化。在这个合约中,我们将使用事件来实现这一功能,就像安装了一个广播系统,向外界发送重要通知。

案例 Demo:编写一个记录用户活动的合约

  1. 初始化开发环境:

    • 在 Remix IDE 或本地 Truffle 环境中开始你的项目。
  2. 编写智能合约:

    • 创建一个新的 Solidity 文件,例如命名为 ActivityLogger.sol
    • 在合约中定义一个事件来记录用户活动。
  3. 定义事件:

    • 创建一个事件,比如 UserActivity,用于记录用户的行为和相关数据。
  4. 触发事件:

    • 在合约的函数中,根据逻辑触发定义好的事件。
  5. 部署和测试合约:

    • 将合约部署到以太坊测试网络或本地开发环境。
    • 通过调用触发事件的函数来测试事件是否正常工作。

案例代码:ActivityLogger.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ActivityLogger {
    event UserActivity(address indexed user, string activity, uint timestamp);

    function logActivity(string memory _activity) public {
        emit UserActivity(msg.sender, _activity, block.timestamp);
    }
}

ActivityLogger 合约中,我们定义了一个 UserActivity 事件,当用户执行某个行为时,这个事件将被触发,记录下用户地址、活动内容和时间戳。

在 Remix 或 Truffle 中进行测试

  • 在 Remix 或 Truffle 中编译并部署 ActivityLogger 合约。
  • 调用 logActivity 函数并传入一个活动字符串,如 "joined a game"
  • 观察交易日志,确认 UserActivity 事件是否被正确记录和触发。

拓展实践

  • 引入更多事件: 可以为不同类型的用户活动定义不同的事件,以提供更详细的信息。
  • 前端集成: 开发一个前端应用,使用 Web3.js 或 ethers.js 监听并响应这些事件。

通过这个案例,你就学会了如何在智能合约中使用事件来记录和通知关键信息。这就像是在你的合约中安装了一个高效的通信系统,它不仅使合约与外部世界连接起来,还为数据的跟踪和反应提供了强大的支持。

3.3.3 拓展案例 1:使用继承来组织合约

假设你正在开发一个复杂的智能合约系统,需要管理不同层次的用户和权限。在这种情况下,使用继承来组织你的合约不仅可以提高代码的可重用性,还能提高整体架构的清晰度。

案例 Demo:构建基于继承的多层次用户管理系统

  1. 创建基础合约:

    • 开发一个基础合约 BaseContract,包含所有合约共有的逻辑和状态变量。
  2. 构建继承合约:

    • 创建特定功能的合约,如 AdminContractUserContract,它们从 BaseContract 继承。
  3. 实现特定功能:

    • 在继承的合约中实现特定于管理员和普通用户的功能。
  4. 部署和测试合约:

    • 在以太坊测试网络或本地开发环境部署各个合约。
    • 测试继承合约中的特定功能以确保它们按预期工作。

案例代码

BaseContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract BaseContract {
    address owner;

    constructor() {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Not the owner");
        _;
    }

    // 共有逻辑...
}
AdminContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./BaseContract.sol";

contract AdminContract is BaseContract {
    // 管理员特有的逻辑...

    function adminFunction() public onlyOwner {
        // 特定于管理员的功能
    }
}
UserContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./BaseContract.sol";

contract UserContract is BaseContract {
    // 用户特有的逻辑...

    function userFunction() public {
        // 特定于用户的功能
    }
}

在这个案例中,BaseContract 作为基础合约,包含所有类型合约共有的逻辑和状态变量,比如所有权管理。AdminContractUserContract 分别继承 BaseContract,添加了特定于管理员和用户的功能。

测试和部署

  • 在 Remix 或 Truffle 中部署这些合约。
  • 验证 AdminContractUserContract 是否正确继承了 BaseContract 的特性。
  • 测试 adminFunctionuserFunction 确保它们的访问权限和功能按预期工作。

拓展实践

  • 添加更多层次的合约: 你可以继续扩展这个体系,添加更多具有特定功能的合约。
  • 实现接口: 为了更好的模块化设计,可以定义接口并让这些合约实现特定的接口。

通过使用继承,你的智能合约架构就像是精心设计的建筑,每层都有其特定的功能和目的。这样的设计不仅使代码更加整洁,还大大提高了开发效率和可维护性。

3.3.4 拓展案例 2:多重继承和接口

假设你正在开发一个综合性智能合约,需要集成多个独立功能,例如日志记录和权限管理。在这种情况下,利用多重继承和接口可以极大地提高代码的模块化和可重用性。

案例 Demo:创建一个集成多个功能的智能合约

  1. 定义接口和基础合约:

    • 创建几个基础合约,每个合约实现特定的功能,如 LoggerAuthenticator
    • 定义接口,为合约提供标准化的功能框架。
  2. 构建多重继承合约:

    • 创建一个新合约,比如叫做 ComprehensiveContract,它继承自上述所有基础合约。
  3. 实现合约功能:

    • 在继承的合约中整合和扩展基础合约的功能。
  4. 部署和测试合约:

    • 将整合的合约部署到以太坊测试网络或本地开发环境。
    • 测试合约的集成功能以确保它们正常工作。

案例代码

Logger.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Logger {
    event Log(string message);

    function emitLog(string memory _message) internal {
        emit Log(_message);
    }
}
Authenticator.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Authenticator {
    address owner;

    constructor() {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Not authorized");
        _;
    }
}
ComprehensiveContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./Logger.sol";
import "./Authenticator.sol";

contract ComprehensiveContract is Logger, Authenticator {
    function secureAction() public onlyOwner {
        emitLog("Secure action performed");
        // 这里执行安全操作
    }
}

在这个案例中,LoggerAuthenticator 合约分别提供日志记录和权限验证的功能。ComprehensiveContract 通过继承这两个合约,集成了日志记录和权限管理的功能。

测试和部署

  • 在 Remix 或 Truffle 中部署 ComprehensiveContract 合约。
  • 作为合约所有者,尝试调用 secureAction 函数。
  • 验证是否正确记录了日志并且只有所有者可以执行该操作。

拓展实践

  • 引入更多的基础合约: 根据需要,你可以引入更多具有特定功能的基础合约。
  • 使用接口定义标准: 为了确保一致性,你可以为合约功能定义接口,并实现这些接口。

通过这个案例,你学会了如何利用多重继承和接口来构建一个功能丰富且高度模块化的智能合约。这种方式不仅提高了代码的复用性,还使得合约的维护和扩展变得更加简单。

通过掌握事件和继承,你可以让你的智能合约更加模块化和高效,就像是为它们装上了能够广播重要信息的天线,同时建立起一座座彼此连接的建筑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1458801.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【python】linux系统python报错“ssl module in Python is not available”

一、问题现象 1.1 执行pip命令报错 pip安装时遇到openssl问题&#xff0c;没办法安装第三方库 “WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available. ” 1.2 导入import ssl 报错 直接执行python&…

算法面试八股文『 模型详解篇 』

说在前面 这是本系列的第二篇博客&#xff0c;主要是整理了一些经典模型的原理和结构&#xff0c;面试有时候也会问到这些模型的细节&#xff0c;因此都是需要十分熟悉的。光看原理还不够&#xff0c;最好是能用代码试着复现&#xff0c;可以看看李沐老师深度学习的教材&#…

AT24C02(I2C总线)通信的学习

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、存储器介绍二、AT24C02芯片二、I2C总线I2C电路规范I2C时序结构I2C数据帧AT24C02数据帧 总结 前言 学习AT24C02(I2C总线)芯片 一、存储器介绍 RAM&#xf…

PostgreSQL使用session_exec和file_fdw实现失败次数锁定用户策略

使用session_exec 、file_fdw以及自定义函数实现该功能。 缺陷&#xff1a;实测发现锁用户后&#xff0c;进去解锁特定用户。只能允许一次登陆&#xff0c;应该再次登陆的时候&#xff0c;触发函数&#xff0c;把之前的日志里的错误登陆的信息也计算到登录次数里了。而且foreig…

VsCode指定插件安装目录

VsCode指定插件安装目录 VsCode安装的默认目录是在用户目录(%HomePath%)下的.vscode文件夹下的extensions目录下&#xff0c;随着安装插件越来越多会占用大量C盘空间。 指定VsCode的插件目录 Vscode安装目录&#xff1a; D:\Microsoft VS Code\Code.exeVscode插件安装目录&a…

MyBatis数据库查询

文章目录 什么是MyBatisMyBatis程序的创建MyBatis实现数据库查询传参查询插入实现添加操作获取自增ID删除实现修改实现#{}和${}SQL注入 like查询 resultMap和resultType多表查询 对于普遍的后端开发而言&#xff0c;其程序主要包含了后端主程序和数据库两个部分&#xff0c;用户…

【Java】eclipse安装JDBC连接MySQL数据库教程

1.下载JDBC 首先在官网中下载JDBC&#xff0c;下载地址&#xff1a;MySQL :: MySQL Connectors 如果无法进入官网可以点击这里下载&#xff1a;https://download.csdn.net/download/weixin_47040861/88855729 进入官网后找到Develop by MySQL一栏&#xff0c;在该栏下找到JDB…

代码随想录算法训练营DAY20 | 二叉树 (8)

一、LeetCode 701 二叉搜索树中的插入操作 题目链接&#xff1a; 701.二叉搜索树中的插入操作https://leetcode.cn/problems/insert-into-a-binary-search-tree/description/ 思路&#xff1a;见缝插针罢辽。 class Solution {public TreeNode insertIntoBST(TreeNode root, i…

数组的左旋和右旋算法

public class Test09 {public static void main(String[] args) {//右旋 数组逆序遍历&#xff0c;将尾部元素&#xff0c;不断交换至头部int[] arr {1,2,3,4,5,6,7,8};for(int i arr.length-1;i>0;i--) { //遍历一次arr[i] arr[i] ^ arr[i-1];arr[i-1] arr[i] ^ arr[i…

【EI会议征稿通知】第九届电子技术和信息科学国际学术会议(ICETIS 2024)

第九届电子技术和信息科学国际学术会议&#xff08;ICETIS 2024&#xff09; The 9th International Conference on Electronic Technology and Information Science&#xff08;ICETIS 2024&#xff09; ICETIS会议始于2016年&#xff0c;先后吸引众多来自国内外高等院校、科…

如何看待Java是一门半编译半解释型的语言(企业真题)

如何看待Java是一门半编译半解释型的语言 解答&#xff1a;可能是解释执行&#xff0c;可能是编译执行

用户空间与内核通信(二)

文章&#xff1a;用户空间与内核通信&#xff08;一&#xff09;介绍了系统调用&#xff08;System Call&#xff09;&#xff0c;内核模块参数和sysfs&#xff0c;sysctl函数方式进行用户空间和内核空间的访问。本章节我将介绍使用netlink套接字和proc文件系统实现用户空间对内…

《白话C++》第10章 STL和boost,Page101 10.4.6 std::weak_ptr

2.基本功能 “柔弱的”weak_ptr专门用来解决上述设计中必须面对的循环指向问题。 weak_ptr并不是真正的智能指针&#xff0c;它必须依附于shared_ptr存在。对应前面的C1、C2&#xff0c;我们写一个弱引用版本的C3和C4的例子&#xff1a; struct C4; struct C3 {~C3(){cout…

社区店运营方案全攻略,助你实现商业梦想

在如今竞争激烈的商业环境中&#xff0c;成功运营一家社区店需要全面的规划和策略。 作为一名在社区开鲜奶吧5年的创业者&#xff0c;我将为你提供一份全面的社区店运营方案攻略&#xff0c;帮助你实现商业梦想。 1、市场调研&#xff1a; 在选择社区店的位置之前&#xff0c…

Java使用Redis实现消息队列

近期刷Java面试题刷到了“如何使用Redis实现消息队列”&#xff0c;解答如下&#xff1a; 一般使用 list 结构作为队列&#xff0c; rpush 生产消息&#xff0c; lpop 消费消息。当 lpop 没有消息的时候&#xff0c;要适当sleep 一会再重试。若不使用sleep&#xff0c;则可以用…

【C++】STL- > string类(超详解!!!)

文章目录 前言1、string类的出现1.1 C语言中的字符串1.2 平时使用 2. 标准库中的string类2.1 string类的常用文档&#xff08;重要&#xff09;&#xff01;&#xff01;&#xff01;&#xff01;2.2 string类的常用接口说明(接口原型我这里就不展示了&#xff0c;文档中都有可…

springcloud-远程调用

微服务的远程调用 RestTemplate 在项目中&#xff0c;当我们需要远程调用一个 HTTP 接口时&#xff0c;我们经常会用到 RestTemplate 这个类。这个类是 Spring 框架提供的一个工具类。 实例化RestTemplate 创建配置类&#xff0c;实例化RestTemplate Configuration public clas…

ubuntu解决“E: Unable to locate package lrzsz“

今天在ubuntu上安装rzsz包时报错&#xff0c;提示无法定位包&#xff0c;提示如下 出现这个问题是因为apt的源没有更新&#xff0c;我们直接说解决办法 把下面的命令执行一遍即可 sudo add-apt-repository main sudo add-apt-repository universe sudo add-apt-repository re…

【漏洞复现】H3C 路由器多系列信息泄露漏洞

Nx01 产品简介 H3C路由器是一款高性能的路由器产品&#xff0c;具有稳定的性能和丰富的功能。它采用了先进的路由技术和安全机制&#xff0c;可以满足不同用户的需求&#xff0c;广泛应用于企业、运营商和数据中心等领域。 Nx02 漏洞描述 H3C路由器多系列存在信息泄露漏洞&…

“薪”的一年程序员裁员潮技术变革情况下 程序员就业机会在哪里?

引言&#xff1a;一对来自中国的工程师夫妻在美国的不幸身亡&#xff0c;疑似与谷歌的裁员有关&#xff0c;这一事件再次引发了人们对技术变革下裁员对程序员影响的关注。 一、针对裁员潮的一些看法 在我看来&#xff0c;技术变革对程序员的影响是双面的。一方面&#xff0c;…