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

在这里插入图片描述

文章目录

  • 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.mzph.cn/news/691908.shtml

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

相关文章

数据分析案例-2023年TOP100国外电影数据可视化

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

MATLAB环境下使用二维高分辨时频分析方法提取波状分量

MATLAB环境下使用二维高分辨时频分析方法提取波状分量&#xff08;分离混合地震数据&#xff09;。 为了得到更高的时频分辨率&#xff0c;近年来涌现出了大量的新的时频分析方法。有些以线性和非线性时频分析为基础&#xff0c;有些则另辟蹊径&#xff0c;比如Hilbert-Huang变…

高并发系统中常见的问题

在当今的高并发系统中&#xff0c;常见的问题是多种多样的&#xff0c;这些问题往往会对系统的稳定性和性能产生重大影响。本文将详细介绍高并发系统中常见的问题&#xff0c;并探讨其产生原因和解决方案。 一、高并发系统概述 高并发系统是指在同一时间内有大量用户同时访问…

对视频进行分块,断点续传

分块测试 //分块测试Testpublic void testChunk() throws IOException {//源路径File sourceFile new File("D:\\BaiduNetdiskDownload\\Day1-00.项目导学.mp4");//分块文件存储路径String chunkFilePath "D:\\develop\\chunk\\";//分块文件大小int chun…

解锁跨境电商新纪元:大数据驱动下的精准营销攻略

随着全球互联网的快速发展&#xff0c;跨境电商已经成为企业拓展国际市场的重要途径。在这个竞争激烈的环境中&#xff0c;如何有效地进行精准营销成为企业成功的关键之一。大数据技术的兴起为跨境电商提供了丰富的信息和洞察&#xff0c;为精准营销提供了坚实的基础。本文Nox聚…

【八股文】面向对象基础

【八股文】面向对象基础 面向对象和面向过程的区别 面向过程把解决问题的过程拆成一个个方法&#xff0c;通过一个个方法的执行解决问题。面向对象会先抽象出对象&#xff0c;然后用对象执行方法的方式解决问题。 创建一个对象用什么运算符?对象实体与对象引用有何不同? …

安达发|APS排产软件的机台产线任务甘特图功能详解

在现代制造业中&#xff0c;高级计划与排产是制造业运营的关键环节。为了提高生产效率、降低成本并确保产品质量&#xff0c;企业需要对生产过程进行精细化管理。APS&#xff08;高级计划与排产&#xff09;系统作为一种先进的生产计划和调度工具&#xff0c;可以帮助企业实现这…

过了30岁了,一定要专注一件事情?视频号值得尝试!

经常说视频号下载助手&#xff0c; 但发现大多数的大佬都只是先专注一件事情。 小编初6就回来了&#xff0c;和一个大佬吃饭&#xff0c;虽然人家规模并不大&#xff0c;但日引客户上千也是基本的。 这里给大家揭秘一下&#xff0c;他的做法&#xff01;&#xff01;&#x…

3ds Max视频怎么渲染 3ds Max云渲染操作

在3ds Max软件中制作视频动画本质上是逐帧生成画面&#xff0c;并将这些连续帧串联起来创造出动态连贯的视觉效果。常见的视频帧率包括25 FPS(每秒帧数)、60 FPS、以及120 FPS等&#xff0c;帧率的提升可以使视频动画更加流畅。在实质上&#xff0c;视频渲染就是动画渲染&#…

MakerPlace by Michaels:与Etsy一争高下的手工艺品新平台

Michaels是北美规模很大的专业艺术与手工艺品零售商&#xff0c;在加拿大和美国有1290家店。作为一个新的手工艺品在线交易平台——MakerPlace by Michaels 充满无限机遇&#xff01;所以各位跨境人们也不要错过这个平台&#xff0c;跟着我一起来了解一下吧&#xff01; MakerP…

探究二维码技术:连接现实与数字世界的桥梁

title: 探究二维码技术&#xff1a;连接现实与数字世界的桥梁 date: 2024/2/19 13:15:36 updated: 2024/2/19 13:15:36 tags: 二维码技术数据编码纠错算法图像处理商业应用安全验证实时交互 引言&#xff1a; 二维码已经成为现代社会中广泛应用的一种技术工具。它不仅在商业领…

牛客网 OR141 密码检查

答案&#xff1a; #include <stdio.h> #include <string.h> #include <ctype.h> int main() {int n 0;int count1 0, count2 0, count3 0;scanf("%d", &n);while (n--){char ch[100];scanf("%s", ch);int len strlen(ch);if (…

基于SSM的在线教学质量评价系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的在线教学质量评价系统&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spri…

远程办公利器,有哪些远程办公利器好用

远程办公利器&#xff0c;有哪些远程办公利器好用 有的时候需要紧急办公位&#xff0c;但是你的电脑、公司、办公室、酒店、网吧、家里的电脑等极为不方便&#xff0c;这时有远程办公利器就好了。在网上查了下&#xff0c;发下个好用的工具&#xff0c;这里分享下。 1、…

API关键词接口的应用范围说明

一、应用场景 适用商家批发选品&#xff0c;价格监控&#xff0c;品牌监控&#xff0c;实地商家进货 二、公共参数 请求地址: https://api-gw.onebound.cn/1688/item_search 三、请求参数 请求参数&#xff1a;q女装&start_price0&end_price0&page1&cat0&…

UE5 C++ UObject实例化

一.创建UObject C类 在MyObject中声明结构体FMyDataTableStruct 在MyPawn里面&#xff0c;先将头文件里包含 MyObject.h 在MyPawn中声明一个UMyObject类型的指针 TSubclassOf 是提供 UClass 类型安全性的模板类。例如您在创建一个投射物类&#xff0c;允许设计者指定伤害类型…

openai chatGPT 原理通俗介绍

引言 近年来&#xff0c;随着深度学习技术的不断发展&#xff0c;自然语言处理&#xff08;NLP&#xff09;领域取得了长足的进步。ChatGPT&#xff08;Generative Pre-trained Transformer&#xff09;作为一种先进的语言生成模型&#xff0c;在各类对话系统和智能助手中得到…

Stable Diffusion WebUI 常用命令行参数

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 大家好&#xff0c;我是水滴~~ 本文主要讲解 Stable Diffusion WebUI 的一些常用命令行参数&#xff0c;内容详细的介绍了每一种参数的使用&#xff0c;并配有截图&#xff0c;非常适合初学者…

[规章规划]国家数据局-《关于开展全国数据资源调查的通知》要点解析

去年10月份国家数据局成立以后&#xff0c;各地方省级政府数据局纷纷快速挂牌成立。 仅以2024年1月举例&#xff0c;1月5日&#xff0c;江苏省数据局&#xff08;江苏省政务服务管理办公室&#xff09;挂牌成立&#xff0c;成为国家数据局正式揭牌后&#xff0c;第一个成立的省…

Web3区块链游戏:创造虚拟世界的全新体验

随着区块链技术的不断发展&#xff0c;Web3区块链游戏正逐渐崭露头角&#xff0c;为玩家带来了全新的虚拟世界体验。传统游戏中的中心化结构和封闭经济体系已经被打破&#xff0c;取而代之的是去中心化的游戏环境和真实所有权的数字资产。本文将深入探讨Web3区块链游戏的特点、…