什么网站免费做简历,企业网站的设计与实现,天津市工程建设招标信息网,在线单页网站制作Solidity中的引用类型
引用类型(Reference Type)#xff1a;包括数组#xff08;array#xff09;和结构体#xff08;struct#xff09;#xff0c;由于这类变量比较复杂#xff0c;占用存储空间大#xff0c;我们在使用时必须要声明数据存储的位置。
数据位置 …Solidity中的引用类型
引用类型(Reference Type)包括数组array和结构体struct由于这类变量比较复杂占用存储空间大我们在使用时必须要声明数据存储的位置。
数据位置
Solidity数据存储位置有三类storagememory和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.senderblock.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;}
}