solidity基础 -- 存储类型

server/2025/1/24 8:00:09/

        在Solidity智能合约开发中,存储类型是一个至关重要的概念。它不仅影响合约的性能,还决定了数据的存储位置和生命周期。Solidity提供了三种主要的存储类型:storagememorycalldata。本文将结合给定的代码示例,并通过更多实例详细介绍 这三种储存类型的区别。

  • storage:用于合约状态变量,数据持久保存在区块链上,对其修改会影响合约的长期状态。
  • memory:用于局部变量,仅在函数执行期间存在,函数结束后数据消失,可修改,但不会影响 storage 中的数据。
  • calldata:专门用于函数参数,是只读的,存储在调用数据中,在函数执行期间不可变。

 

1. Storage:状态变量与持久化存储

        storage是Solidity中最持久的存储类型,它用于存储合约的状态变量。这些变量会永久存储在区块链上,直到被显式修改或删除。storage变量的生命周期与合约的生命周期相同,这意味着它们在合约部署后一直存在。

        在我们的示例合约中,myStructs是一个storage类型的映射,它存储了每个地址对应的MyStruct结构体。当我们通过myStructs[msg.sender]访问或修改它时,实际上是在操作区块链上的持久化数据。

myStructs[msg.sender] = MyStruct({foo: 123, text: "bar"});

        这行代码将一个MyStruct实例存储到myStructs映射中,它会永久保存在区块链上,直到被覆盖或删除。

使用场景

  • 存储合约的状态变量,如用户余额、配置参数等。

  • 在函数中引用和修改状态变量。

注意事项

  • storage变量的读写操作成本较高,因为它们需要与区块链交互。

  • 修改storage变量会消耗更多的Gas。

2. Memory:临时存储与局部变量

        memory是Solidity中用于临时存储数据的存储类型。它用于存储函数内部的局部变量,这些变量仅在函数执行期间存在,函数执行结束后,存储在memory中的数据会被销毁。

        在示例合约中,readOnly是一个memory类型的变量,它是myStructs[msg.sender]的一个副本。对readOnly的修改不会影响原始的storage变量:

MyStruct memory readOnly = myStructs[msg.sender];
readOnly.foo = 456;

这行代码将myStructs[msg.sender]的内容复制到memory中,并修改了副本的foo属性。然而,这个修改不会反映到链上的storage变量中。

使用场景

  • 存储函数内部的临时变量。

  • 创建数据的副本进行操作,而不影响原始数据。

注意事项

  • memory变量的生命周期仅限于函数执行期间。

  • 创建memory变量需要消耗Gas,但比storage操作更高效。

3. Calldata:函数参数的只读存储

        calldata是Solidity中一种特殊的存储类型,它用于存储函数的输入参数。calldata变量是只读的,不能被修改。它们存储在内存中,但与memory不同,calldata变量不能被分配或重新赋值。

在示例合约中,yscalldata类型的参数:

function examples(uint[] calldata y, string calldata s) external returns (uint[] memory)

这行代码声明了两个calldata参数。y是一个uint数组,s是一个字符串。这些参数在函数调用时由调用者提供,并且在函数内部只能被读取,不能被修改。

使用场景

  • 存储函数的输入参数。

  • 用于传递大量数据,如数组或结构体,而不需要复制到memory

注意事项

  • calldata变量是只读的,不能被修改。

  • calldata变量不能被分配或重新赋值。

 

4.示例合约:DataLocations

在我们开始之前,先来看一个简单的Solidity合约,它展示了这三种存储类型的使用:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract DataLocations {struct MyStruct {uint foo;string text;}mapping (address => MyStruct) public myStructs;function examples(uint[] calldata y, string calldata s) external returns (uint[] memory) {myStructs[msg.sender] = MyStruct({foo: 123, text: "bar"});MyStruct storage myStruct = myStructs[msg.sender];myStruct.text = "foo";// 修改存储在`storage`中的状态变量MyStruct memory readOnly = myStructs[msg.sender];readOnly.foo = 456;// 修改存储在`memory`中的副本,不影响链上数据_internal(y);uint[] memory memArr = new uint[](3);memArr[0] = 234;return memArr;}function _internal(uint[] calldata y) private {uint x = y[0];}
}

其他实例:深入理解存储类型

为了进一步理解这三种存储类型的区别,我们再来看一个简单的示例合约:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract StorageTypes {uint public storageVar = 10; // 存储在`storage`中的状态变量function example() public pure returns (uint memoryVar) {uint memory memoryVar = 20; // 存储在`memory`中的局部变量return memoryVar;}function example2(uint calldataVar) public pure returns (uint) {return calldataVar; // `calldata`变量,只读}
}

总结

  • storage:用于合约状态变量,数据持久保存在区块链上,对其修改会影响合约的长期状态。
  • memory:用于局部变量,仅在函数执行期间存在,函数结束后数据消失,可修改,但不会影响 storage 中的数据。
  • calldata:专门用于函数参数,是只读的,存储在调用数据中,在函数执行期间不可变。

        通过深入理解这三种储存类型的区别,开发者可以更好地优化智能合约的性能和资源使用,确保合约的正确性和稳定性。

 


http://www.ppmy.cn/server/160971.html

相关文章

Java 大视界 -- Java 大数据中的数据脱敏技术与合规实践(60)

💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…

翻译:How do I reset my FPGA?

文章目录 背景翻译:How do I reset my FPGA?1、Understanding the flip-flop reset behavior2、Reset methodology3、Use appropriate resets to maximize utilization4、Many options5、About the author 背景 在写博客《复位信号的同步与释放(同步复…

MyBatis最佳实践:动态 SQL

第一章:MyBatis 映射文件 SQL 深入 配置 log4j.properrties 配置文件 该配置文件可打印输出 SQL 查询的日志 #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码 log4j.rootLoggerDEBUG,console,file#控制台输出…

爬虫基础之爬取某站视频

目标网址:为了1/4螺口买小米SU7,开了一个月,它值吗?_哔哩哔哩_bilibili 本案例所使用到的模块 requests (发送HTTP请求)subprocess(执行系统命令)re (正则表达式操作)json (处理JSON数据) 需求分析: 视频的名称 F12 打开开发者工具 or 右击…

Formality:时序变换(二)(不可读寄存器移除)

相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482https://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 一、引言 时序变换在Design Compiler的首次综合和增量综合中都可能发生&a…

0基础跟德姆(dom)一起学AI 自然语言处理21-fasttext模型架构

1 Fasttext模型架构 FastText 模型架构和 Word2Vec 中的 CBOW 模型很类似, 不同之处在于, FastText 预测标签, 而 CBOW 模型预测中间词. FastText的模型分为三层架构: 输入层: 是对文档embedding之后的向量, 包含N-gram特征隐藏层: 是对输入数据的求和平均输出层: 是文档对应…

c++ 与 Matlab 程序的数据比对

文章目录 背景环境数据保存数据加载 背景 ***避免数据精度误差&#xff0c;快速对比变量 *** 环境 c下载 https://github.com/BlueBrain/HighFive 以及hdf5库 在vs 中配置库 数据保存 #include <highfive/highfive.hpp> using namespace HighFive;std::string fil…

mysql 学习3 SQL语句--整体概述。SQL通用语法,SQL语句分类

SQL通用语法 SQL语句分类 DDL data definition language : 用来创建数据库&#xff0c;创建表&#xff0c;创建表中的字段&#xff0c;创建索引。因此成为 数据定义语言 DML data manipulation language 有了数据库和表以及字段后&#xff0c;那么我们就需要给这个表中 添加数…