当前位置: 首页 > news >正文

Function Modifier

本节是《Solidity by Example》的中文翻译与深入讲解,专为零基础或刚接触区块链开发的小白朋友打造。我们将通过“示例 + 解说 + 提示”的方式,带你逐步理解每一段 Solidity 代码的实际用途与背后的逻辑。

Solidity 是以太坊等智能合约平台使用的主要编程语言,就像写网页要用 HTML 和 JavaScript,写智能合约就需要会 Solidity。

如果你从没写过区块链代码也没关系,只要你了解一点点编程概念,比如“变量”“函数”“条件判断”,我们就能从最简单的例子开始,一步步建立你的 Solidity 编程思维。

Function Modifier

函数修饰器
修饰器是一段可以在函数调用之前和/或之后运行的代码。

修饰器可用于:

  • 限制访问权限
  • 验证输入
  • 防止重入攻击

什么是 Solidity 函数修饰器?

函数修饰器(Modifier)是 Solidity 中一种代码复用机制,允许在函数执行前后插入逻辑,用于检查条件或执行额外操作。

  • 比喻:修饰器像门禁系统,在你进入房间(调用函数)前检查身份或条件,离开时可能清理现场。
  • 修饰器通过 _; 占位符指示函数主体的执行位置,_; 前后分别运行前置和后置逻辑。

修饰器的用途

  • 限制访问权限:如 onlyOwner 修饰器,确保只有合约拥有者能调用函数。
  • 验证输入:如 validAddress 修饰器,检查输入地址是否有效。
  • 防止重入攻击:如 noReentrancy 修饰器,锁定函数防止重复调用(重入)。
// SPDX-License-Identifier: MIT
// 使用 MIT 许可证,允许自由使用、修改和分发代码。pragma solidity ^0.8.26;
// 指定 Solidity 编译器版本,必须为 0.8.26 或更高(但低于 0.9.0)。contract FunctionModifier {// 定义一个名为 FunctionModifier 的智能合约,展示函数修饰器的用法。// We will use these variables to demonstrate how to use// modifiers.// 我们将使用这些变量来展示如何使用修饰器。address public owner;// 声明一个公共状态变量 owner,存储合约拥有者的地址(storage)。// public 自动生成 getter 函数(owner())。uint256 public x = 10;// 声明一个公共状态变量 x,初始值为 10(storage),用于测试修饰器效果。bool public locked;// 声明一个公共状态变量 locked,初始值为 false(storage),用于防止重入攻击。constructor() {// Set the transaction sender as the owner of the contract.// 将交易发送者设置为合约的拥有者。owner = msg.sender;// 在合约部署时,将调用者的地址(msg.sender)赋给 owner。// msg.sender 是部署合约的账户地址。}// Modifier to check that the caller is the owner of// the contract.// 检查调用者是否为合约拥有者的修饰器。modifier onlyOwner() {require(msg.sender == owner, "Not owner");// 使用 require 检查调用者(msg.sender)是否为 owner。// 如果不是,抛出错误“Not owner”,交易回滚。// Underscore is a special character only used inside// a function modifier and it tells Solidity to// execute the rest of the code.// 下划线是修饰器中使用的特殊字符,指示 Solidity 执行后续代码。_;// _; 表示执行被修饰函数的主体代码。// 本修饰器只有前置逻辑(检查权限),无后置逻辑。}// Modifiers can take inputs. This modifier checks that the// address passed in is not the zero address.// 修饰器可以接受输入参数。此修饰器检查传入的地址不是零地址。modifier validAddress(address _addr) {require(_addr != address(0), "Not valid address");// 使用 require 检查输入地址 _addr 是否为零地址(address(0))。// 如果是,抛出错误“Not valid address”,交易回滚。_;// _; 表示执行被修饰函数的主体代码。// 本修饰器只有前置逻辑(检查地址有效性)。}function changeOwner(address _newOwner) public onlyOwner validAddress(_newOwner){// 定义一个公共函数 changeOwner,接受新拥有者地址 _newOwner。// public:可被外部和内部调用。// 应用 onlyOwner 和 validAddress 修饰器:// - onlyOwner:确保只有当前 owner 能调用。// - validAddress:确保 _newOwner 非零地址。owner = _newOwner;// 将 owner 更新为 _newOwner,修改 storage,消耗 Gas。}// Modifiers can be called before and / or after a function.// This modifier prevents a function from being called while// it is still executing.// 修饰器可以在函数调用前和/或后执行。// 此修饰器防止函数在执行期间被再次调用。modifier noReentrancy() {require(!locked, "No reentrancy");// 使用 require 检查 locked 是否为 false。// 如果 locked 为 true(函数正在执行),抛出错误“No reentrancy”,防止重入。locked = true;// 设置 locked 为 true,表示函数进入执行状态,锁定合约。_;// _; 表示执行被修饰函数的主体代码。locked = false;// 函数执行后,设置 locked 为 false,释放锁。// 本修饰器有前置逻辑(检查锁并加锁)和后置逻辑(解锁)。}function decrement(uint256 i) public noReentrancy {// 定义一个公共函数 decrement,接受参数 i,减少状态变量 x。// 应用 noReentrancy 修饰器,防止重入攻击。x -= i;// 将状态变量 x 减去 i,修改 storage,消耗 Gas。if (i > 1) {decrement(i - 1);// 如果 i > 1,递归调用 decrement,传入 i-1。// noReentrancy 修饰器确保递归调用不会导致重入。}}
}

FunctionModifier 合约展示修饰器的三种主要用途:

  • 限制访问onlyOwner 修饰器确保只有合约拥有者能调用函数。
  • 验证输入validAddress 修饰器检查输入地址非零。
  • 防止重入noReentrancy 修饰器通过锁机制防止重入攻击。
  • 合约包含状态变量(ownerxlocked)和两个函数(changeOwnerdecrement),演示修饰器的实际应用。

函数修饰器的本质

  • 函数修饰器是 Solidity 中一种代码复用工具,允许在函数执行前后插入逻辑,用于检查条件、限制访问或执行清理操作。
  • 核心功能:
    • 限制访问:如 onlyOwner,确保只有特定用户(如合约拥有者)能调用函数。
    • 验证输入:如 validAddress,检查输入参数有效性(如非零地址)。
    • 防止重入:如 noReentrancy,通过锁机制防止函数被重复调用(重入攻击)。
  • 优势:
    • 代码复用:将通用逻辑(如权限检查)封装到修饰器,避免重复编写。
    • 清晰性:使函数逻辑更简洁,检查条件集中管理。
    • 安全性:防止未授权访问或重入攻击。

代码功能

  • 合约 FunctionModifier
    • 状态变量:
      • owner:存储合约拥有者地址,初始化为部署者(msg.sender)。
      • x:存储一个计数器,初始值为 10,用于测试函数效果。
      • locked:布尔值,初始为 false,用于防止重入攻击。
    • 修饰器:
      • onlyOwner:检查调用者是否为 owner,否则抛出错误“Not owner”。
      • validAddress:检查输入地址是否非零,否则抛出错误“Not valid address”。
      • noReentrancy:检查并设置锁(locked),防止函数重入,执行后解锁。
    • 函数:
      • changeOwner:更新 owner 地址,需通过 onlyOwnervalidAddress 检查。
      • decrement:减少 x,支持递归调用,noReentrancy 防止重入攻击。

函数修饰器的注意事项

  • 执行顺序:
    • 多个修饰器按声明顺序执行(如 onlyOwner validAddress 先检查权限再验证地址)。
    • _; 前为前置逻辑,后为后置逻辑(如 noReentrancy 的加锁和解锁)。
  • Gas 成本:
    • 修饰器增加检查逻辑(如 require),消耗少量 Gas。
    • 修改 storage(如 locked)消耗约 20,000+ Gas,可用瞬态存储优化(参考历史对话)。
    • 错误抛出(如“Not owner”)消耗少量 Gas,但尽早抛出节省后续计算。
  • 安全性:
    • 检查关键条件(如 msg.senderaddress(0)),避免未授权访问。
    • 重入保护(如 noReentrancy)需确保锁状态正确重置。
    • 修饰器逻辑需简单,避免引入复杂 bug。
  • 局限性:
    • 修饰器不能直接访问函数参数或返回值,需通过输入参数(如 validAddress(address _addr))。
    • 递归调用(如 decrement)需确保修饰器(如 noReentrancy)支持。
http://www.dtcms.com/a/291977.html

相关文章:

  • 动漫短剧系统开发:构建下一代沉浸式娱乐平台的架构设计与技术突破
  • 使用qt编写上位机程序,出现串口死掉无法接受数据的bug
  • Kotlin 中的单例模式(Singleton)与对象声明
  • 力扣-链表相关题 持续更新中。。。。。。
  • 手写 防抖函数、节流函数
  • 【企业APP上架小米应用商店需要做的准备】(本示例为uniapp开发)
  • LLM评测框架Ragas:SQL指标(解决了Ollama推理框架不支持的问题)
  • oracle查询数据结构滤涉及的sql语句
  • 程序是如何生成的-以c语言为例
  • 行内元素垂直边距为何失效?
  • Vite:下一代前端构建工具的革命
  • 金仓数据库风云
  • 基于JAVA实现基于“obj--html--pdf” 的PDF格式文本生成
  • C语言第二章分支与循环(下)——猜数字游戏
  • 【深度解析】从AWS re_Invent 2025看云原生技术发展趋势
  • AWS RDS 排查性能问题
  • RedisJSON 指令精讲JSON.TOGGLE 键翻转布尔值
  • 聊聊 iframe:网页中的“窗口”是怎么回事?
  • Vue3 学习教程,从入门到精通,Vue3 循环语句(`v-for`)语法知识点与案例详解(13)
  • rabbitmq 03
  • 《3D printed deformable sensors》论文解读
  • 【初识数据结构】CS61B 中的堆以及堆排序算法
  • 矩阵SVD分解计算
  • 今日Github热门仓库推荐 第八期
  • 3ds Max 云端渲染插件 - 完整 Python 解决方案
  • 锟斤拷与烫烫烫:中文编程界的独特印记
  • Go语言切片(Slice)与数组(Array)深度解析:避坑指南与最佳实践
  • Go语言实战案例-遍历目录下所有文件
  • Go 的第一类对象与闭包
  • 基于单片机智能衣柜/智能衣橱设计