解释这些 Solidity 智能合约的核心概念
我来详细解释这些 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; // 存储在状态中,消耗更多Gas
event StateChanged(uint256 newValue); // 存储在日志中,消耗较少Gas
function 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 {
// 局部变量引用 storage
uint256 storage localValue = globalValue;
localValue = 100; // 修改会影响 globalValue
// 直接修改 storage
globalValue = 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 后赋值给 storage
storageArray = m; // 现在 storageArray 包含 memory 的修改
}
function gasOptimization() public {
// 使用 memory 减少 Gas 消耗
uint256[] memory tempArray = new uint256[](100);
for (uint256 i = 0; i < 100; i++) {
tempArray[i] = i;
}
// 一次性写入 storage
storageArray = 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 优化 Gas
function 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 智能合约开发的基础,理解它们对于编写高效、安全的智能合约至关重要。