Solidity 变量
Solidity 变量 Solidity 特殊变量 Solidity 变量默认值 Solidity 变量作用域 Solidity 常量Solidity 运算符
Solidity 运算符 Solidity 算术运算符 Solidity 比较运算符 Solidity 逻辑运算符 Solidity 位运算符 Solidity 赋值运算符 Solidity 条件运算符Solidity 条件语句
Solidity 条件语句 Solidity if语句 Solidity if…else 语句 Solidity if…else ifSolidity 循环语句
Solidity 循环语句 Solidity while 循环 Solidity do 循环 Solidity for 循环 break 与 continueSolidity 复杂数据
Solidity 字符串 Solidity 数组 Solidity 结构体 Solidity 映射 Solidity 枚举 Solidity 类型转换Solidity 数据位置
Solidity 数据位置 Solidity 变量数据位置 Solidity 赋值数据位置Solidity 函数
Solidity 函数 Solidity 函数返回值 Solidity pure函数 Solidity view函数 Solidity 构造函数 solidity 函数修改器 Solidity 函数重载 Solidity 数学函数 Solidity 加密函数Solidity 进阶编程
Solidity 事件 Solidity 不可变量 Solidity 日志 Solidity 继承 Solidity 多重继承 多重继承的构造函数 Solidity 调用父类函数 Solidity 异常处理 Solidity 编程风格 Solidity 访问权限 Solidity 存储位置 Solidity 引用类型 Solidity 值类型 Solidity 值类型与引用类型 Solidity 合约结构 Solidity 编写智能合约 Solidity delete Solidity 0.6 重大变化 Solidity transfer 转账 Solidity transfer send Solidity 单位 Solidity constant Solidity this & sender Solidity address Solidity 众筹智能合约 Solidity interface solidity gas使用模式 Solidity 常见编译错误 Solidity 调用合约 Solidity 支付Eth Solidity fallback Solidity receive Solidty 钱包合约 Solidity 发送Eth Solidity 自毁合约 Solidity 哈希算法 Solidity 工厂合约 Solidity 库合约 Solidity 权限控制合约 Solidity 验证签名Solidity 变量
Solidity 变量 Solidity 特殊变量 Solidity 变量默认值 Solidity 变量作用域 Solidity 常量Solidity 运算符
Solidity 运算符 Solidity 算术运算符 Solidity 比较运算符 Solidity 逻辑运算符 Solidity 位运算符 Solidity 赋值运算符 Solidity 条件运算符Solidity 条件语句
Solidity 条件语句 Solidity if语句 Solidity if…else 语句 Solidity if…else ifSolidity 循环语句
Solidity 循环语句 Solidity while 循环 Solidity do 循环 Solidity for 循环 break 与 continueSolidity 复杂数据
Solidity 字符串 Solidity 数组 Solidity 结构体 Solidity 映射 Solidity 枚举 Solidity 类型转换Solidity 数据位置
Solidity 数据位置 Solidity 变量数据位置 Solidity 赋值数据位置Solidity 函数
Solidity 函数 Solidity 函数返回值 Solidity pure函数 Solidity view函数 Solidity 构造函数 solidity 函数修改器 Solidity 函数重载 Solidity 数学函数 Solidity 加密函数Solidity 进阶编程
Solidity 事件 Solidity 不可变量 Solidity 日志 Solidity 继承 Solidity 多重继承 多重继承的构造函数 Solidity 调用父类函数 Solidity 异常处理 Solidity 编程风格 Solidity 访问权限 Solidity 存储位置 Solidity 引用类型 Solidity 值类型 Solidity 值类型与引用类型 Solidity 合约结构 Solidity 编写智能合约 Solidity delete Solidity 0.6 重大变化 Solidity transfer 转账 Solidity transfer send Solidity 单位 Solidity constant Solidity this & sender Solidity address Solidity 众筹智能合约 Solidity interface solidity gas使用模式 Solidity 常见编译错误 Solidity 调用合约 Solidity 支付Eth Solidity fallback Solidity receive Solidty 钱包合约 Solidity 发送Eth Solidity 自毁合约 Solidity 哈希算法 Solidity 工厂合约 Solidity 库合约 Solidity 权限控制合约 Solidity 验证签名Solidity modifier 函数修改器
Solidity 中关键字 modifier 用于声明一个函数修改器。
我们可以将一些通用的操作提取出来,包装为函数修改器,来提高代码的复用性,改善编码效率。
函数修改器 modifier 的作用与 Java Spring 中的切面功能很相似,当它作用于一个函数上,可以在函数执行前或后预先执行 modifier 中的逻辑,以增强其功能。
函数修改器 modifier 常用于在函数执行前检查某种前置条件。
函数修改器 modifier 是一种合约属性,可被继承,同时还可被派生的合约重写(override)。
1. 基本函数修改器
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract ModifierTest {
bool public paused;
uint public counter;
function setPaused(bool _paused) external {
paused = _paused;
}
modifier isNotPaused() {
require(!paused); // 检查前置条件:判断paused是否被设置,如果paused为true,那么终止执行。
_; // 执行被isNotPaused修饰的函数
}
function add() external isNotPaused{
counter++;
}
}
add函数被修改器isNotPaused修饰,所以先执行 require(!paused),检查前置条件,然后再执行add函数的代码。
2. _ 的作用
函数修改器中有一行代码只有下划线 _ ,我们认为下划线 _ 代表了被修饰函数的代码。
也就是说,下划线实际上帮我们标记了被 modifier 修饰函数的执行位置。如上例中:
modifier isNotPaused() {
require(!paused); // 检查前置条件:判断paused是否被设置,如果paused为true,那么终止执行。
_; // 执行被isNotPaused修饰的函数
}
下划线 _在 require(!paused) 后面,则被修饰函数 add 在此判断条件之后执行。
3. 带参数的函数修改器
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract ModifierTest {
bool public paused;
uint public counter;
function setPaused(bool _paused) external {
paused = _paused;
}
modifier isNotPaused(uint x) {
require(x > 10 ); // 检查前置条件:判断x是否大于10,如果x大于或者等于10,那么终止执行。
_; // 执行被isNotPaused修饰的函数
}
function add(uint x) external isNotPaused(x){
counter++;
}
}
4. 复杂示例
我们来看一个函数修改器经典的应用 OpenZeppelin 库中的 Ownable 合约,下面是其中关键的代码:
/// Ownable 可以判断合约的调用者是否为当前合约的owner,
/// 从而避免其他人随意的调用一些合约的关键操作。
/// 同时,owner 可以指定任何其他人为此合约新的 owner,
/// 显然,只有当前owner才能指定其他人为新的owner。
contract Ownable {
// 变量 owner 指定此合约的owner
address public owner;
// 发布事件 - 此合约owner已经换人(此逻辑与modifier无关,可以忽略)
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
// 构造函数 - 创建合约自动执行,初始化合约所有人为合约创建者
function Ownable() public {
owner = msg.sender;
}
// 定义一个函数修改器
modifier onlyOwner() {
// 判断此函数调用者是否为owner
require(msg.sender == owner);
_;
}
// owner可以用此函数将owner所有权转换给其他人,显然次函数只有owner才能调用
// 函数末尾加上onlyOwner声明,onlyOwner正是上面定义的modifier
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0));
OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
上述合约的 transferOwnership 函数用于 owner 将所有权转让给其他人,于是在末尾声明 onlyOwner 修改器,onlyOwner 将在 transferOwnership 执行前,先执行
require(msg.sender == owner);
以保证此函数的调用者为 owner ,如果不是 owner 则抛出异常。
下一章:Solidity 函数重载
Solidity的函数重载,是指同一个作用域内,相同函数名可以定义多个函数。这些函数的参数(参数类型或参数数量)必须不一样。仅仅是返回值不一样是不被允许。下面的例子展示了Solidity中的函数重载概念。示例// ...
AI 中文社