继承和事件是Solidity中实现代码复用和链下通知的重要特性。本文详细介绍Solidity的继承机制、事件系统,以及如何在实际开发中使用这些特性构建可维护的智能合约。
一、什么是继承
1. 基本概念
继承是Solidity中实现代码复用和模块化的重要机制,允许一个合约继承另一个合约的功能。Solidity支持多重继承,子合约可以继承多个父合约。
2. 继承的特点
代码复用
- 继承父合约的功能
- 减少重复代码
- 提高可维护性
- 模块化设计
多重继承
- 可以继承多个合约
- 使用C3线性化
- 解决钻石问题
- 灵活组合功能
函数覆盖
- 可以覆盖父合约函数
- 使用virtual和override
- 保持接口一致
- 扩展功能
二、如何实现继承
1. 单继承
基础继承
1 | |
2. 多重继承
1 | |
_;
}
1 | |
}
1 | |
}
// 可拥有合约
_;
}
}
1 | |
}
1 | |
三、什么是事件
1. 基本概念
事件(Event)是Solidity中用于记录日志和通知链下应用的机制。事件数据存储在交易日志中,可以被前端应用监听和处理。
2. 事件的特点
链下通知
- 前端可以监听
- 实时获取状态变化
- 无需轮询查询
- 提高用户体验
Gas效率
- 比存储更便宜
- 适合记录历史
- 不占用存储槽
- 优化Gas消耗
不可篡改
- 记录在区块链
- 永久保存
- 可验证
- 审计追踪
四、如何定义和使用事件
1. 事件定义
简单事件
1 | |
}
索引参数:solidity
event Transfer(
address indexed from, // indexed:可以用于过滤
address indexed to, // indexed:可以用于过滤
uint256 value // 非indexed:完整数据
);
1 | |
3. 监听事件
使用Web3.js
1 | |
// 监听所有转账事件
contract.on(“Transfer”, (from, to, value, event) => {
console.log(Transfer: ${from} -> ${to}, ${value});
});
// 过滤事件:只监听从特定地址发出的转账
const filter = contract.filters.Transfer(userAddress, null);
contract.on(filter, (from, to, value) => {
console.log(Received from ${from}: ${value});
});
1 | |
ERC20事件:
contract ERC20 {
// 标准转账事件
// 标准授权事件
1 | |
contract ERC721 {
// NFT转账事件:tokenId也是indexed
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
// NFT授权事件
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
function transferFrom(address from, address to, uint256 tokenId) public {
emit Transfer(from, to, tokenId);
1 | |
2. 状态追踪
订单状态:
contract OrderSystem {
enum OrderStatus { Created, Paid, Shipped, Delivered }
// 订单状态改变事件
event OrderStatusChanged(
uint256 indexed orderId,
OrderStatus oldStatus,
OrderStatus newStatus
);
mapping(uint256 => OrderStatus) public orders;
// 更新订单状态
function updateStatus(uint256 orderId, OrderStatus newStatus) public {
OrderStatus oldStatus = orders[orderId];
orders[orderId] = newStatus;
// 触发状态改变事件
emit OrderStatusChanged(orderId, oldStatus, newStatus);
}
1 | |
操作记录:
contract Auditable {
// 管理员操作事件
event AdminAction(
1 | |
// 用户操作事件
event UserAction(
1 | |
// 管理员函数
function adminFunction() public {
// 记录管理员操作
emit AdminAction(msg.sender, “adminFunction”, block.timestamp);
// 执行操作
1 | |
// 用户函数
function userFunction(bytes memory data) public {
// 记录用户操作
emit UserAction(msg.sender, “userFunction”, data);
1 | |
六、继承最佳实践
1. 设计模式
可拥有合约:
// 所有权转移事件
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
emit OwnershipTransferred(address(0), owner);
}
_;
}
emit OwnershipTransferred(owner, newOwner);
}可暂停合约:solidity
contract Pausable is Ownable {
// 暂停事件
event Paused(address account);
// 恢复事件
event Unpaused(address account);
_;
}
// 暂停合约:只有owner且未暂停时才能调用
function pause() public onlyOwner whenNotPaused {
emit Paused(msg.sender);
}
// 恢复合约:只有owner且已暂停时才能调用
function unpause() public onlyOwner {
require(paused, “Not paused”);
emit Unpaused(msg.sender);
}
1 | |
可重用库:
library SafeMath {
// 安全加法:检查溢出
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, “SafeMath: addition overflow”);
return c;
1 | |
contract MyContract {
// 为uint256类型使用SafeMath库
using SafeMath for uint256;
function calculate(uint256 a, uint256 b) public pure returns (uint256) {
// 使用库函数进行安全加法
return a.add(b);
1 | |
3. 接口定义
标准接口:
interface IERC20 {
function transfer(address to, uint256 amount) external returns (bool);
function balanceOf(address account) external view returns (uint256);
}
contract MyToken is IERC20 {
// 实现接口中的transfer函数
function transfer(address to, uint256 amount) external override returns (bool) {
// 实现逻辑
}
// 实现接口中的balanceOf函数
function balanceOf(address account) external view override returns (uint256) {
return 0;
}
1 | |
完整信息:
// 订单创建事件:包含所有重要信息
event OrderCreated(
1 | |
// 包含所有重要信息,便于链下处理
// 最多3个indexed参数
1 | |
2. Gas优化
替代存储:
// 不推荐:存储历史数据(消耗Gas)
mapping(uint256 => uint256) public history;
// 推荐:使用事件记录历史(更省Gas)
event ValueChanged(uint256 indexed index, uint256 oldValue, uint256 newValue);
function setValue(uint256 index, uint256 value) public {
uint256 oldValue = values[index];
values[index] = value;
// 使用事件记录,比存储更便宜
emit ValueChanged(index, oldValue, value);
}
1 | |
本文标题: Solidity继承和事件
发布时间: 2024年11月25日 00:00
最后更新: 2026年09月16日 05:40
原始链接: https://haoxiang.eu.org/eb8ae9b2/
版权声明: 本文著作权归作者所有,均采用CC BY-NC-SA 4.0许可协议,转载请注明出处!

