Skip to content

Latest commit

 

History

History
136 lines (109 loc) · 4.04 KB

File metadata and controls

136 lines (109 loc) · 4.04 KB

5. 變數資料儲存與作用域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);
}

🧑‍💻 也就是說 calldata 到 function 裡面時是不可以被修改的。

Storage 範例

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

6. 引用型, array, struct

我們將介紹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});
}