Solidity:变量数据存储和作用域 storage/memory/calldata
Solidity中的引用类型
引用类型(Reference Type):包括数组(array)和结构体(struct),由于这类变量比较复杂,占用存储空间大,我们在使用时必须要声明数据存储的位置。
数据位置
Solidity数据存储位置有三类:storage,memory和calldata。不同存储位置的gas成本不同。storage类型的数据存在链上,类似计算机的硬盘,消耗gas多;memory和calldata类型的临时存在内存里,消耗gas少。大致用法:
-
storage:合约里的状态变量默认都是storage,存储在链上。 -
memory:函数里的参数和临时变量一般用memory,存储在内存中,不上链。尤其是如果返回数据类型是变长的情况下,必须加memory修饰,例如:string, bytes, array和自定义结构。 -
calldata:和memory类似,存储在内存中,不上链。与memory的不同点在于calldata变量不能修改(immutable),一般用于函数的参数。例子:function fCalldata(uint[] calldata _x) public pure returns(uint[] calldata){//参数为calldata数组,不能被修改// _x[0] = 0 //这样修改会报错return(_x); }数据位置和赋值规则
在不同存储类型相互赋值时候,有时会产生独立的副本(修改新变量不会影响原变量),有时会产生引用(修改新变量会影响原变量)。规则如下:
-
赋值本质上是创建引用指向本体,因此修改本体或者是引用,变化可以被同步:
storage(合约的状态变量)赋值给本地storage(函数里的)时候,会创建引用,改变新变量会影响原变量。例子:
uint[] x = [1,2,3]; // 状态变量:数组 xfunction fStorage() public{//声明一个storage的变量 xStorage,指向x。修改xStorage也会影响xuint[] storage xStorage = x;xStorage[0] = 100;
}
memory赋值给memory,会创建引用,改变新变量会影响原变量。-
其他情况下,赋值创建的是本体的副本,即对二者之一的修改,并不会同步到另一方
变量的作用域
Solidity中变量按作用域划分有三种,分别是状态变量(state variable),局部变量(local variable)和全局变量(global variable)
1. 状态变量
状态变量是数据存储在链上的变量,所有合约内函数都可以访问,gas消耗高。状态变量在合约内、函数外声明:
contract Variables {uint public x = 1;uint public y;string public z;
}
我们可以在函数里更改状态变量的值:
function foo() external{// 可以在函数里更改状态变量的值x = 5;y = 2;z = "0xAA";
}
2. 局部变量
局部变量是仅在函数执行过程中有效的变量,函数退出后,变量无效。局部变量的数据存储在内存里,不上链,gas低。局部变量在函数内声明:
function bar() external pure returns(uint){uint xx = 1;uint yy = 3;uint zz = xx + yy;return(zz);
}
3. 全局变量
全局变量是全局范围工作的变量,都是solidity预留关键字。他们可以在函数内不声明直接使用:
function global() external view returns(address, uint, bytes memory){address sender = msg.sender;uint blockNum = block.number;bytes memory data = msg.data;return(sender, blockNum, data);
}
在上面例子里,我们使用了3个常用的全局变量:msg.sender,block.number和msg.data,他们分别代表请求发起地址,当前区块高度,和请求数据。下面是一些常用的全局变量,更完整的列表请看这个链接:
blockhash(uint blockNumber): (bytes32) 给定区块的哈希值 – 只适用于256最近区块, 不包含当前区块。block.coinbase: (address payable) 当前区块矿工的地址block.gaslimit: (uint) 当前区块的gaslimitblock.number: (uint) 当前区块的numberblock.timestamp: (uint) 当前区块的时间戳,为unix纪元以来的秒gasleft(): (uint256) 剩余 gasmsg.data: (bytes calldata) 完整call datamsg.sender: (address payable) 消息发送者 (当前 caller)msg.sig: (bytes4) calldata的前四个字节 (function identifier)msg.value: (uint) 当前交易发送的wei值block.blobbasefee: (uint) 当前区块的blob基础费用。这是Cancun升级新增的全局变量。blobhash(uint index): (bytes32) 返回跟当前交易关联的第index个blob的版本化哈希(第一个字节为版本号,当前为0x01,后面接KZG承诺的SHA256哈希的最后31个字节)。若当前交易不包含blob,则返回空字节。这是Cancun升级新增的全局变量。
4. 全局变量-以太单位与时间单位
以太单位
Solidity中不存在小数点,以0代替为小数点,来确保交易的精确度,并且防止精度的损失,利用以太单位可以避免误算的问题,方便程序员在合约中处理货币交易。
wei: 1gwei: 1e9 = 1000000000ether: 1e18 = 1000000000000000000
function weiUnit() external pure returns(uint) {assert(1 wei == 1e0);assert(1 wei == 1);return 1 wei;
}function gweiUnit() external pure returns(uint) {assert(1 gwei == 1e9);assert(1 gwei == 1000000000);return 1 gwei;
}function etherUnit() external pure returns(uint) {assert(1 ether == 1e18);assert(1 ether == 1000000000000000000);return 1 ether;
}
时间单位
可以在合约中规定一个操作必须在一周内完成,或者某个事件在一个月后发生。这样就能让合约的执行可以更加精确,不会因为技术上的误差而影响合约的结果。因此,时间单位在Solidity中是一个重要的概念,有助于提高合约的可读性和可维护性。
seconds: 1minutes: 60 seconds = 60hours: 60 minutes = 3600days: 24 hours = 86400weeks: 7 days = 604800
function secondsUnit() external pure returns(uint) {assert(1 seconds == 1);return 1 seconds;
}function minutesUnit() external pure returns(uint) {assert(1 minutes == 60);assert(1 minutes == 60 seconds);return 1 minutes;
}function hoursUnit() external pure returns(uint) {assert(1 hours == 3600);assert(1 hours == 60 minutes);return 1 hours;
}function daysUnit() external pure returns(uint) {assert(1 days == 86400);assert(1 days == 24 hours);return 1 days;
}function weeksUnit() external pure returns(uint) {assert(1 weeks == 604800);assert(1 weeks == 7 days);return 1 weeks;
}
测试代码:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;contract DataStorage {// The data location of x is storage.// This is the only place where the// data location can be omitted.uint[] public x = [1,2,3];function fStorage() public{//声明一个storage的变量xStorage,指向x。修改xStorage也会影响xuint[] storage xStorage = x;xStorage[0] = 100;}function fMemory() public view{//声明一个Memory的变量xMemory,复制x。修改xMemory不会影响xuint[] memory xMemory = x;xMemory[0] = 100;xMemory[1] = 200;uint[] memory xMemory2 = x;xMemory2[0] = 300;}function fCalldata(uint[] calldata _x) public pure returns(uint[] calldata){//参数为calldata数组,不能被修改// _x[0] = 0 //这样修改会报错return(_x);}
}contract Variables {uint public x = 1;uint public y;string public z;function foo() external{// 可以在函数里更改状态变量的值x = 5;y = 2;z = "0xAA";}function bar() external pure returns(uint){uint xx = 1;uint yy = 3;uint zz = xx + yy;return(zz);}function global() external view returns(address, uint, bytes memory){address sender = msg.sender;uint blockNum = block.number;bytes memory data = msg.data;return(sender, blockNum, data);}function weiUnit() external pure returns(uint) {assert(1 wei == 1e0);assert(1 wei == 1);return 1 wei;}function gweiUnit() external pure returns(uint) {assert(1 gwei == 1e9);assert(1 gwei == 1000000000);return 1 gwei;}function etherUnit() external pure returns(uint) {assert(1 ether == 1e18);assert(1 ether == 1000000000000000000);return 1 ether;}function secondsUnit() external pure returns(uint) {assert(1 seconds == 1);return 1 seconds;}function minutesUnit() external pure returns(uint) {assert(1 minutes == 60);assert(1 minutes == 60 seconds);return 1 minutes;}function hoursUnit() external pure returns(uint) {assert(1 hours == 3600);assert(1 hours == 60 minutes);return 1 hours;}function daysUnit() external pure returns(uint) {assert(1 days == 86400);assert(1 days == 24 hours);return 1 days;}function weeksUnit() external pure returns(uint) {assert(1 weeks == 604800);assert(1 weeks == 7 days);return 1 weeks;}
}
相关文章:
Solidity:变量数据存储和作用域 storage/memory/calldata
Solidity中的引用类型 引用类型(Reference Type):包括数组(array)和结构体(struct),由于这类变量比较复杂,占用存储空间大,我们在使用时必须要声明数据存储的位置。 数据位置 …...
ElementUI中的el-table解决宽度问题 - 根据内容自动撑开
在使用element-ui中,会发现表格组件el-table在未指定宽度情况下,会自动计算并给表格宽度赋值。但实际开发中,有时需要根据内容实际长度自动撑开显示,由内容的多少而决定表格的宽度,而不是默认宽度为100%。在默认情况下…...
react apollo hooks
1、创建ApolloProvider来包装整个程序 <ApolloProvider client{client}><App /> <ApolloProvider> 2、useQuery查询 工作方式usequery将返回一个数组 const {要返回的对象} useQuery(传入参数) 实例 const query gqlquery name {whatever {field}} e…...
Android 10.0 SystemUI启动流程
1、手机开机后,Android系统首先会创建一个Zygote(核心进程)。 2、由Zygote启动SystemServer。 3、SystemServer会启动系统运行所需的众多核心服务和普通服务、以及一些应用及数据。例如:SystemUI 启动就是从 SystemServer 里启动的…...
洛谷 P1032 [NOIP2002 提高组] 字串变换
P1032 [NOIP2002 提高组] 字串变换 - 洛谷 | 计算机科学教育新生态 题目来源 洛谷 题目内容 [NOIP2002 提高组] 字串变换 题目背景 本题不保证存在靠谱的多项式复杂度的做法。测试数据非常的水,各种做法都可以通过,不代表算法正确。因此本题题目和…...
网络资源模板--Android Studio 外卖点餐App
目录 一、项目演示 二、项目测试环境 三、项目详情 四、完整的项目源码 原创外卖点餐:基于Android studio 实现外卖(点)订餐系统 非原创奶茶点餐:网络资源模板--基于 Android Studio 实现的奶茶点餐App报告 一、项目演示 网络资源模板--基于Android …...
【Linux】网络新手村
欢迎来到 破晓的历程的 博客 ⛺️不负时光,不负己✈️ 引言 今天,我们就开始学习Linux网络相关的内容。这篇博客作为Linux网络板块的第一篇博客看,我们首先要带着大家明白Linux网络的一些名词的概念,为之后的学习扫清障碍。然后我…...
123123
123123...
在pycharm中使用jupyter
在pycharm中使用jupyter 前置条件:你的环境中应该有juptyer ,没有的话 pip install jupyter 点击项目目录,右键->new->jupyter notebook 打开file settings 找到 jupyter server (按照默认的用代理服务器就行) P…...
MongoDB:掌握核心常用命令语句,精通数据操作
标题:MongoDB:掌握核心命令,精通数据操作 前言: MongoDB 是一种非关系型数据库,以文档为中心,使用 JSON 格式的 BSON 来存储数据。它具有高可用性、高性能和易于扩展的特点,被广泛应用于各种规模的项目中。本文将详细介绍 MongoDB 的常用命令,帮助你更好地理解和掌握…...
Redis中测试Stream的例子
当你想要测试 Redis 中的 Stream 功能时,可以通过 Redis 的命令行客户端或者使用任何支持 Redis 的编程语言来操作。下面我会给出一个简单的例子,使用 Redis 的命令行客户端 redis-cli 来测试 Stream 的基本功能。 准备工作 确保你已经安装并启动了 Re…...
28 H3C SecPath F1000 概览(主要功能是总 观看全局)
28 H3C SecPath F1000 概览(主要功能是总 观看全局) 特性简介 概览页面通过清晰的图形化模块清晰展示了设备关键数据信息及各类状态,并支持灵活排版布局,以便实时查看用户关心的数据。预定义监控默认展示了设备基础信息模块,也可以手动添加其…...
标准版视频检测终端功能有哪些? 捷顺高清视频车位引导系统怎么样?
随着城市化进程的加速,城市交通压力日益增大,停车难问题成为了许多城市居民的共同困扰。在这样的背景下,车位引导系统的出现,无疑为解决这一难题提供了一种有效的解决方案。车位引导系统利用先进的信息技术,通过实时监…...
说明本文档目录是软件开发梳理需求常见问题QA文档,方便客户看,也方便我们的售前人员,需求分析人员,ui设计师,原型绘图人员,思维导图绘图人员查看。
https://doc.youyacao.com/117/2150 说明 本文档目录是软件开发梳理需求常见问题QA文档,方便客户看,也方便我们的售前人员,需求分析人员,ui设计师,原型绘图人员,思维导图绘图人员查看。 提示 本内容客户…...
Echarts桑基图
关于Echarts的使用方法参考:vue2中echarts的使用_vue2中使用echarts-CSDN博客 实现效果: 代码: var sysT {"用采": #2D9BFF,"营销系统": #39BFFF,"ERP": #76C2FF,"财务管控": #5F57FC,"PMS&…...
wordpress网站添加一个临时维护功能
把以下代码放到functions.php文件中,主要用网站临时维护或者用于备案。事情做好了,把以下代码删除即可!!! 有时遇到一些情况,比如站点需要闭站备案、或者被要求停站等等,我们就可以使用本文的功…...
充电桩开源平台,开发流程有图有工具
慧哥充电桩开源平台产品研发流程是确保产品从概念阶段到市场推广阶段的有序进行的关键。以下是对您给出的步骤的详细解释和建议: 设计业务流程: 在这一步,团队需要确定产品的核心功能、目标用户以及如何满足用户需求。进行市场调研,了解竞争…...
数据中台设计书及建设指南(中台及大数据解决技术方案)
1. 中台概念 2. 推动企业组织模式演进 3. 建设方法 4 .中台内容 5. 数据安全体系 中台内容围绕数据中台建设评估、整体框架、数据采集,结构化、半结构化、非结构化的数据采集,数据计算能力、存储计算引擎、数据架构、数据挖掘、各种不同数据层建设、模型…...
合合信息大模型“加速器”重磅上线
大模型技术的发展和应用,预示着更加智能化、个性化未来的到来。如果将大模型比喻为正在疾驰的科技列车,语料便是珍贵的“燃料”。本次世界人工智能大会期间,合合信息为大模型打造的“加速器”解决方案备受关注。 在大模型训练的上游阶段&…...
# Sharding-JDBC 从入门到精通(10)- 综合案例(三)查询商品与测试及统计商品和总结
Sharding-JDBC 从入门到精通(10)- 综合案例(三)查询商品与测试及统计商品和总结 一、Sharding-JDBC 综合案例-查询商品-dao 1、查询商品:Dao 实现:在 ProductDao 中定义商品查询方法: //查询商…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving
地址:LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂,正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...
