Solidity学习02 函数、存储位置、作用域、单位
函数输出
关键字
retuens:在函数名后面,定义返回值
return:在函数体中,将返回值返回
// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;
contract MyContract {
int public number = 2;
// return返回
function add(int _num) public view returns (int, int) {
return (number + _num, number * _num);
}
// 命名式返回
function addL2(int _num) public view returns (int res1, int res2) {
res1 = number + _num;
res2 = number * _num;
}
// 读取返回值后 使用解构赋值,获取返回值中需要的值
function readReturn() public view {
int _res1;
int _res2;
(_res1, _res2) = add(3);
(_res1, ) = add(4);
}
}
数据存储位置与Gas费
Data location can only be specified for array, struct or mapping types
不用存储位置消耗gas不一样。
storage | 存储在链上。gas多。 |
memory | 存储在内存中。gas少。 |
calldata | 存储在内存中,但是变量不能修改。常用于函数参数。不消耗gas。 |
隐式默认数据位置 | 状态变量默认都存在storage。对于函数参数和返回变量,默认位置是calldata。对于函数内部的局部变量,默认位置是memory。 |
在 Solidity 中,
calldata
数据位置并不存储在内存中。calldata
是一种特殊的数据位置,用于存储外部函数调用时传递的参数数据。它是一个只读的数据区域,存储在调用数据区域中,并且只能在函数执行期间访问。合约只能读取calldata
中的数据,但不能修改它。因此,与内存不同,calldata
不会消耗合约的存储空间,并且在函数执行结束后会被销毁,不会在合约状态中留下任何痕迹。
赋值本质上是创建引用指向本体,因此修改本体或者是引用,变化可以被同步
contract MyContract1 {
uint256[] public x = [1, 2, 3]; // 状态变量:数组 x
//声明一个storage类型的变量指向storage的状态变量。修改后影响状态变量
function fStorage() public {
uint256[] storage xStorage = x;
xStorage[0] = 100;
}
//声明一个memory类型的变量指向storage的状态变量。修改后,“不会”影响状态变量
function fMemory() public view {
uint256[] memory xStorage = x;
xStorage[0] = 100;
}
// 在函数内部声明memory类型的成员变量a、b,b指向a,需要b后a的值就会变更
function fMemoryL2() public view returns (uint256) {
uint256[] memory xStorage = x;
uint256[] memory xStorage2 = xStorage;
xStorage2[0] = 100;
return xStorage[0];
}
}
变量的作用域
状态变量 | 数据存在链上。所有合约内的函数都可以访问。gas高。 |
局部变量 | 数据在内存中。只在函数执行过程中有效。gas低。 |
全局变量 | 都是预留的关键字。 |
部分全局变量
msg.sender:调用方
msg.data:请求数据
block.number:区块高度
eth单位
由于eth最小单位到小数点后18个零,方便起见,solidity中有3中eth单位
wei:1wei(最小单位)
gwei:1e9 wei
ether:1e18 wei(即1eth)
contract EthUnitContract {
function TestEthUnit() public pure returns (bool) {
bool a = 1 wei == 1;
bool b = 1 gwei == 1e9;
bool c = 1 ether == 1e18;
return a && b && c;
}
}
时间单位
由于合约可以规定一个操作必须在一定时间内完成。(这通常涉及使用时间戳和时间单位来跟踪时间,并设置一个截止日期。)
合约可以检查当前时间是否在规定的时间范围内,以确定是否执行某些操作。
pragma solidity ^0.8.0;
contract DeadlineExample {
uint public deadline;
constructor() {
// 设置截止日期为一周后的时间戳
deadline = block.timestamp + 1 weeks;
}
function performAction() public {
require(block.timestamp <= deadline, "Action deadline has passed");
// 在截止日期之前执行操作
// 在此添加操作的代码
}
}
上面的合约中,构造函数设置了一个截止日期,即当前时间加上一周的时间(以秒为单位)。在performAction函数中,使用require语句来检查当前时间是否在截止日期之前。如果超过了截止日期,合约将拒绝执行操作,并返回错误消息。
其中使用到了时间单位。
时间单位有以下几种:
seconds:1
minutes: 60 seconds = 60
hours: 60 minutes = 3600
days: 24 hours = 86400
weeks: 7 days = 604800