- 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);
}
🧑💻 也就是說 calldata 到 function 裡面時是不可以被修改的。
uint[] x = [1,2,3]; // 状态变量:数组 x
function fStorage() public{
uint[] storage xStorage = x;
xStorage[0] = 100;
}
🧑💻 上面可以看到 storage
的變數 xStorage 是指向 x 的,所以修改 xStorage 也會影響到 x。
🧑💻 如果用上鏈上資料都是很花 gas fee
Solidity中不存在小數點,以0代替為小數點
- 以太單位
- wei: 1
- gwei: 1e9 = 1000000000
- ether: 1e18 = 1000000000000000000
- 時間
- seconds: 1
- minutes: 60 秒 = 60
- hours: 60 分鐘 = 3600
- days:24小時=86400
- weeks:7天=604800
本章重點:
重點是storage,memory和calldata三個關鍵字的用法。他們出現的原因是為了節省鏈上有限的儲存空間和降低 gas
我們將介紹Solidity中兩個重要的變數類型:陣列(array)和結構體(struct)。
-
數組(Array)
固定長度陣列
// 固定長度 Array uint[8] array1; bytes1[5] array2; address[100] array3;
可變長度陣列
uint[] array4; bytes1[] array5; address[] array6; bytes array7;
注意:bytes比較特殊,是數組,但不用加[]。
另外,不能用byte[]聲明單字節數組,可以使用bytes或bytes1[]。
bytes比bytes1[]省gas。
在Solidity裡,創建數組有一些規則:
對於memory修飾的动态数组,可以用new操作符來創建,但是必須聲明長度,並且聲明後長度不能改變。例子:
// memory 動態數組 uint[] memory array8 = new uint[](5); bytes memory array9 = new bytes(9); // 賦值 uint[] memory x = new uint[](3); x[0] = 1; x[1] = 3; x[2] = 4; // length: 陣列有一個包含元素數量的length成員,memory陣列的長度在建立後是固定的。 // push():动态数组擁有push()成員,可以在陣列最後加上一個0元素,並傳回該元素的參考。 // push(x):动态数组擁有push(x)成員,可以在陣列最後加上一個x元素。 // pop():动态数组擁有pop()成員,可以移除陣列最後一個元素。
-
結構體(Struct)
example:
struct Student{
uint256 id;
uint256 score;
}
Student student; // 初始一个student 結構體
給值的方法:
// 1
function initStudent1() external{
// assign a copy of student
Student storage _student = student;
_student.id = 11;
_student.score = 100;
}
// 2
function initStudent2() external{
student.id = 1;
student.score = 80;
}
// 3
function initStudent3() external {
student = Student(3, 90);
}
// 4
function initStudent4() external {
student = Student({id: 4, score: 60});
}