我来详细解释这些 Solidity 智能合约的核心概念:
1. 合约生命周期
合约部署阶段
// 1. 合约创建
contract MyContract {// 2. 状态变量初始化uint256 public value;address public owner;// 3. 构造函数执行constructor(uint256 _initialValue) {value = _initialValue;owner = msg.sender;}// 4. 合约部署完成,可以接收交易
}
合约运行阶段
contract LifecycleExample {uint256 public state;bool public isActive;// 构造函数 - 部署时执行一次constructor() {state = 0;isActive = true;}// 普通函数 - 可被多次调用function updateState(uint256 _newValue) public {require(isActive, "Contract is not active");state = _newValue;}// 自毁函数 - 销毁合约function destroy() public {require(msg.sender == owner, "Only owner can destroy");selfdestruct(payable(owner));}
}
生命周期阶段总结
- 编译:Solidity 代码编译为字节码
- 部署:字节码部署到区块链
- 初始化:构造函数执行
- 运行:接收交易和函数调用
- 销毁:通过
selfdestruct
销毁(可选)
2. 事件 (Events)
事件定义和发出
contract EventExample {// 定义事件event Transfer(address indexed from, address indexed to, uint256 value);event Approval(address indexed owner, address indexed spender, uint256 value);mapping(address => uint256) public balances;mapping(address => mapping(address => uint256)) public allowances;function transfer(address to, uint256 amount) public {require(balances[msg.sender] >= amount, "Insufficient balance");balances[msg.sender] -= amount;balances[to] += amount;// 发出事件emit Transfer(msg.sender, to, amount);}function approve(address spender, uint256 amount) public {allowances[msg.sender][spender] = amount;// 发出事件emit Approval(msg.sender, spender, amount);}
}
事件的特点
- 日志记录:事件数据存储在区块链日志中
- 索引参数:最多3个
indexed
参数,便于搜索 - Gas 消耗:比存储状态变量便宜
- 不可修改:一旦发出,无法修改
事件 vs 状态变量
contract Comparison {uint256 public stateVariable; // 存储在状态中,消耗更多Gasevent StateChanged(uint256 newValue); // 存储在日志中,消耗较少Gasfunction updateState(uint256 _value) public {stateVariable = _value;emit StateChanged(_value); // 同时更新状态和发出事件}
}
3. Modifier(修饰符)
基本 Modifier
contract ModifierExample {address public owner;bool public paused;// 基本修饰符modifier onlyOwner() {require(msg.sender == owner, "Only owner can call this function");_; // 执行被修饰的函数}modifier whenNotPaused() {require(!paused, "Contract is paused");_;}modifier validAddress(address _addr) {require(_addr != address(0), "Invalid address");_;}// 使用修饰符function setOwner(address _newOwner) public onlyOwner validAddress(_newOwner) {owner = _newOwner;}function pause() public onlyOwner {paused = true;}function unpause() public onlyOwner {paused = false;}
}
带参数的 Modifier
contract AdvancedModifier {mapping(address => uint256) public balances;modifier hasBalance(uint256 _amount) {require(balances[msg.sender] >= _amount, "Insufficient balance");_;}modifier limitAmount(uint256 _maxAmount) {require(msg.value <= _maxAmount, "Amount exceeds limit");_;}function withdraw(uint256 _amount) public hasBalance(_amount) {balances[msg.sender] -= _amount;payable(msg.sender).transfer(_amount);}function deposit() public payable limitAmount(10 ether) {balances[msg.sender] += msg.value;}
}
Modifier 执行顺序
contract ModifierOrder {modifier first() {console.log("First modifier");_;console.log("First modifier after");}modifier second() {console.log("Second modifier");_;console.log("Second modifier after");}function test() public first second {console.log("Function body");}// 输出顺序:// First modifier// Second modifier// Function body// Second modifier after// First modifier after
}
4. Storage vs Memory
Storage(存储)
contract StorageExample {// 状态变量存储在 storage 中uint256 public globalValue;mapping(address => uint256) public balances;function storageExample() public {// 局部变量引用 storageuint256 storage localValue = globalValue;localValue = 100; // 修改会影响 globalValue// 直接修改 storageglobalValue = 200;}
}
Memory(内存)
contract MemoryExample {uint256 public globalValue;function memoryExample() public {// 局部变量存储在 memory 中uint256 memory localValue = globalValue;localValue = 100; // 不会影响 globalValue// 数组示例uint256[] memory tempArray = new uint256[](3);tempArray[0] = 1;tempArray[1] = 2;tempArray[2] = 3;// 函数执行完毕后,memory 数据被清除}
}
详细对比
特性 | Storage | Memory |
---|---|---|
位置 | 区块链状态 | 函数执行期间 |
持久性 | 永久存储 | 临时存储 |
Gas 消耗 | 高 | 低 |
访问速度 | 慢 | 快 |
作用域 | 合约级别 | 函数级别 |
实际应用示例
contract StorageMemoryExample {uint256[] public storageArray;function demonstrateDifference() public {// Storage 引用uint256[] storage s = storageArray;s.push(1); // 会影响 storageArray// Memory 复制uint256[] memory m = storageArray;m.push(2); // 不会影响 storageArray// 修改 memory 后赋值给 storagestorageArray = m; // 现在 storageArray 包含 memory 的修改}function gasOptimization() public {// 使用 memory 减少 Gas 消耗uint256[] memory tempArray = new uint256[](100);for (uint256 i = 0; i < 100; i++) {tempArray[i] = i;}// 一次性写入 storagestorageArray = tempArray;}
}
5. 综合示例:完整的合约生命周期
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract CompleteExample {// 状态变量 (Storage)address public owner;uint256 public totalSupply;mapping(address => uint256) public balances;bool public paused;// 事件event Transfer(address indexed from, address indexed to, uint256 value);event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);event Paused(address account);event Unpaused(address account);// 修饰符modifier onlyOwner() {require(msg.sender == owner, "Ownable: caller is not the owner");_;}modifier whenNotPaused() {require(!paused, "Pausable: paused");_;}// 构造函数 - 合约部署时执行constructor(uint256 _initialSupply) {owner = msg.sender;totalSupply = _initialSupply;balances[msg.sender] = _initialSupply;emit Transfer(address(0), msg.sender, _initialSupply);}// 普通函数function transfer(address to, uint256 amount) public whenNotPaused {require(balances[msg.sender] >= amount, "Insufficient balance");balances[msg.sender] -= amount;balances[to] += amount;emit Transfer(msg.sender, to, amount);}// 使用 memory 优化 Gasfunction batchTransfer(address[] memory recipients, uint256[] memory amounts) public whenNotPaused {require(recipients.length == amounts.length, "Arrays length mismatch");uint256 totalAmount = 0;for (uint256 i = 0; i < amounts.length; i++) {totalAmount += amounts[i];}require(balances[msg.sender] >= totalAmount, "Insufficient balance");balances[msg.sender] -= totalAmount;for (uint256 i = 0; i < recipients.length; i++) {balances[recipients[i]] += amounts[i];emit Transfer(msg.sender, recipients[i], amounts[i]);}}// 管理函数function pause() public onlyOwner {paused = true;emit Paused(msg.sender);}function unpause() public onlyOwner {paused = false;emit Unpaused(msg.sender);}function transferOwnership(address newOwner) public onlyOwner {require(newOwner != address(0), "Ownable: new owner is the zero address");emit OwnershipTransferred(owner, newOwner);owner = newOwner;}// 自毁函数 - 合约生命周期结束function destroy() public onlyOwner {selfdestruct(payable(owner));}
}
总结
合约生命周期
- 编译 → 部署 → 初始化 → 运行 → 销毁
事件的作用
- 记录重要状态变化
- 提供链下监听接口
- 比存储状态变量更便宜
Modifier 的优势
- 代码复用
- 权限控制
- 条件检查
- 提高代码可读性
Storage vs Memory
- Storage:永久存储,高 Gas 消耗
- Memory:临时存储,低 Gas 消耗
- 合理选择可以优化 Gas 消耗
这些概念共同构成了 Solidity 智能合约开发的基础,理解它们对于编写高效、安全的智能合约至关重要。