解释这些 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));}
}

生命周期阶段总结

  1. 编译:Solidity 代码编译为字节码
  2. 部署:字节码部署到区块链
  3. 初始化:构造函数执行
  4. 运行:接收交易和函数调用
  5. 销毁:通过 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));}
}

总结

合约生命周期

  1. 编译部署初始化运行销毁

事件的作用

  • 记录重要状态变化
  • 提供链下监听接口
  • 比存储状态变量更便宜

Modifier 的优势

  • 代码复用
  • 权限控制
  • 条件检查
  • 提高代码可读性

Storage vs Memory

  • Storage:永久存储,高 Gas 消耗
  • Memory:临时存储,低 Gas 消耗
  • 合理选择可以优化 Gas 消耗

这些概念共同构成了 Solidity 智能合约开发的基础,理解它们对于编写高效、安全的智能合约至关重要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/942763.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

你的项目一团糟-不是你的错-是框架的锅

GitHub 主页 你的项目一团糟?不是你的错,是框架的“锅”!📂➡️🏛️ 每个程序员都经历过那个瞬间。你加入一个新项目,或者时隔半年重新打开一个自己写的项目,然后,你感到了那种熟悉的、令人窒息的混乱。🌪…

别再猜了-开始测量吧-一份实用的Web性能指南

GitHub 主页 别再猜了,开始测量吧:一份实用的 Web 性能指南 又是一年“黑五”,凌晨三点,我的手机像疯了一样尖叫起来。😱 不是闹钟,是监控警报。我们的主打电商服务,那个我们花了半年心血构建的系统,在流量洪…

你的错误处理一团糟-是时候修复它了-️

GitHub 主页 你的错误处理一团糟,是时候修复它了!🛠️ 我还记得那个让我彻夜难眠的 bug。一个支付回调接口,在处理一个罕见的、来自第三方支付网关的异常状态码时,一个Promise链中的.catch()被无意中遗漏了。结果…

[网络] [iproute2] tc: Linux 带宽限制(Token Bucket Filter 和 HTB)使用指南

[网络] [iproute2] tc: Linux 带宽限制(Token Bucket Filter 和 HTB)使用指南$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");参考:iproute2: 网络管理利…

C++编程练习

// 阿汪面前有两只盲盒,每只盒子打开都有两种可能:或者装了 X 克狗粮,或者是一只容量为 Y 克的狗粮储蓄盒。如果是狗粮,阿汪可以快乐地吃掉;如果是空储蓄盒,那就倒霉了,阿汪必须想办法找到狗粮把这只储蓄盒装满…

newDay14

1.做了几个Java的小练习,背背单词,写了一些英语作业,时间还是不太够 2.明天课就少了,继续往下学 3.自己c++还是太差了,java学得差不多就回去补c++

L07_在RuoYI项目中添加自己的接口并实现CRUD功能(轻松+AI版)

这里是废话部分 从来没有写过如此轻松的作业,上课两个多小时就听进去了几分钟的东西,这几分钟的东西还是操作,其他是半点都没入入脑,靠着这几分钟的东西,轻松的完成了作业的1/2。 在L06中折磨的看了三天的文档,大…

大二to大三暑假大三上前半学期总结

比赛,学习,刚谈上恋爱,可是然后呢?其实心态得到了比较大的改变,比大二下的时候好受了很多,可能是逐渐接收了事实了。 比较大的事情其实也没几个,第一是和同学一起去打了一个超算比赛 是并行应用挑战赛2025,去鄂…

带权拉格朗日中值定理的证明

带权拉格朗日中值定理:设 \(f(x)\) 在 \([a, b]\) 连续,且 \(g(x)\) 在 \([a,b]\) 可积且不变号(恒大于零或恒小于零),那么存在 \(c\in [a,b]\),使得 \[\int^b_af(x)g(x)\text{d}x = f(c)\int^b_ag(x)\text{d}x …

Linux 下将程序打包为安装包

对于 Linux 下的程序打包,个人首推 FPM 构建工具。它比 dpkg、rpmbuild 要好用的多(至少 2021 年那会如此),并且它同时支持 deb、rpm 等包格式。 以下回顾一下以前写过的安装包构建脚本: #!/bin/bash#-----------…

低代码如何推动企业敏捷创新与业务赋能

在创新驱动发展的时代,企业需要更快地响应市场变化,更灵活地调整业务策略。然而,传统的软件开发模式往往无法满足这种敏捷性要求。低代码技术的出现,正在改变这一现状,成为推动企业敏捷创新的重要力量。低代码与敏…

hevc解码器下载

如果你使用的是品牌电脑,那电脑重装系统后会自动下载,无需手动安装,连机械革命都会自动安装的 如果不是,那么直接下载最新版(本文截稿于2025/10/21) Microsoft.HEVCVideoExtensions_2.4.23下载 双击打开即可安装…

低代码如何成为企业数字化转型的加速器

在当今快速变化的商业环境中,企业数字化转型已从"选择题"变成了"必答题"。然而,传统软件开发模式的高成本、长周期,让许多企业在数字化转型的道路上步履维艰。这时,低代码技术应运而生,正以其…

2025.10.18 刷题

2025.10.18 刷题1. P14253 旅行(trip) 一眼,区间肯定到结尾 然后从后面扫,随便统计一下个数即可 2. P14254 分割(divide) 刚看很难 再看诈骗 发现限制是要求同等深度,然后最小的必须有两个 然后这个是个独立问题…

[网络] [iproute2] tc命令:Linux网络异常模拟(Network Emulation, netem)指南

[网络] [iproute2] tc命令:Linux网络异常模拟(Network Emulation, netem)指南$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");目录01 简介02 前提条件2.1…

删除链表的倒数第N个结点-leetcode

题目描述 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 示例 1:输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5]示例 2: 输入:head = [1], n = 1 输出:[]示例 3: 输入:head = [1,2], n =…

NOI 八

根号分治?+吉司机/扫描线/单调栈A. 先考虑 unordered_map 暴力记录的做法,容易发现 LCM 太大了存不下,状态数也不可接受。 LCM 考虑质因数分解,发现 \(V=300\) ,\(>17\) 的质因数只会至多出现一次。 这样的质…

2025.10.21总结

今天继续看软考相关内容,今天复习了计算机网络相关知识,和程序设计语言基础,还有汇编语言,汇编语言太晦涩难懂了,看了一部分,例题跟着过了一下就过了,系统的学的话需要很长时间,这部分以做题为主吧。 目前也还…

10.18测试

T1 Bug 题目描述 A 君在机缘巧合下得到了一把养蛊神器,于是 A 君希望培养出迄今为止战斗力最强的 Bug。A 君把现有的 \(n\) 个 Bug 排成一个序列 \(a_1, a_2, \dots, a_n\),其中 \(a_i\) 表示第 \(i\) 个 Bug 的战斗…

Day1标签的关系与vs的注释

<html><head></head><body></body> </html>标签之间的关系有两种,嵌套与并列关系,也可形象对的理解为父子与兄弟 在上述代码中,head与body都是html的子标,而head与body则是并…