CryptoZombies學習筆記——Lesson2

沒有窗戶的小巷發表於2018-09-01

  第二課是殭屍獵食,將把app變得更像一個遊戲,新增多人模式,建立更多創造殭屍的方法。

chapter1
  依然是簡介

chapter2:對映和地址

  對映相當於一個索引,指向不同地址,不同地址儲存的資料不同,相當於一種特殊的儲存結構。此例中用來儲存每個殭屍的上一級。

mapping(address=>uint) public accountBalance;

  key是address,value是uint。

 

chapter3: msg.sender

  指向呼叫函式的使用者地址。注意:智慧合約部署在區塊鏈上,只有當一個外部賬戶呼叫智慧合約的函式時才會執行合約,所以msg.sender總是存在的。

  一個例子:

mapping (address => uint) favoriteNumber;

function setMyNumber(uint _myNumber) public {
  // Update our `favoriteNumber` mapping to store `_myNumber` under `msg.sender`
  favoriteNumber[msg.sender] = _myNumber;
  // ^ The syntax for storing data in a mapping is just like with arrays
}

function whatIsMyNumber() public view returns (uint) {
  // Retrieve the value stored in the sender`s address
  // Will be `0` if the sender hasn`t called `setMyNumber` yet
  return favoriteNumber[msg.sender];
}

  相對於其他儲存方式,運用_msg.sender更為安全,只有當你的私鑰洩露時,別人才能更改你的賬戶資料。

 

chapter4:require

  使用require編輯限制條件,不滿足條件時程式會丟擲異常。

  例子:

function sayHiToVitalik(string _name) public returns (string) {
  // Compares if _name equals "Vitalik". Throws an error and exits if not true.
  // (Side note: Solidity doesn`t have native string comparison, so we
  // compare their keccak256 hashes to see if the strings are equal)
  require(keccak256(_name) == keccak256("Vitalik"));
  // If it`s true, proceed with the function:
  return "Hi!";
}

  solidity中字串不能直接比較,所以將字串進行keccak256編碼再做比較。

  注:solidity比較時對兩邊順序沒有固定要求。

 

chapter5:繼承

  類似其他面嚮物件語言的繼承,可繼承父親的public函式等。

contract Dog is Animal{}

 

chapter6:引入

  類似其他語言的庫,易於長程式碼的模組化編輯和管理。

 

chapter7:storage 和 memory

  storage 和 memory 是solidity中變數的兩種儲存方式,storage 永久儲存在區塊鏈上,而memory會在外部函式呼叫時清除,有點類似計算機的磁碟和ram。solidity預設函式外定義的狀態變數是storage儲存,而函式內定義的變數是memory形式儲存。

  當然有時需要手動定義來滿足一些需求,不過不用擔心,solidity編譯器會在你定義不恰當的時候提出warning。

contract SandwichFactory {
  struct Sandwich {
    string name;
    string status;
  }

  Sandwich[] sandwiches;

  function eatSandwich(uint _index) public {
    // Sandwich mySandwich = sandwiches[_index];

    // ^ Seems pretty straightforward, but solidity will give you a warning
    // telling you that you should explicitly declare `storage` or `memory` here.

    // So instead, you should declare with the `storage` keyword, like:
    Sandwich storage mySandwich = sandwiches[_index];
    // ...in which case `mySandwich` is a pointer to `sandwiches[_index]`
    // in storage, and...
    mySandwich.status = "Eaten!";
    // ...this will permanently change `sandwiches[_index]` on the blockchain.

    // If you just want a copy, you can use `memory`:
    Sandwich memory anotherSandwich = sandwiches[_index + 1];
    // ...in which case `anotherSandwich` will simply be a copy of the 
    // data in memory, and...
    anotherSandwich.status = "Eaten!";
    // ...will just modify the temporary variable and have no effect 
    // on `sandwiches[_index + 1]`. But you can do this:
    sandwiches[_index + 1] = anotherSandwich;
    // ...if you want to copy the changes back into blockchain storage.
  }
}

 

chapter8: Zombie Dna

chapter9: 更多關於函式可見化的問題

  除了public和private,solidity中還有internal和external來控制函式可見化。

  internal類似於private,但有一點不同,internal定義的函式可以為外部繼承合約呼叫,而private不行。

  external類似於public,但external定義的函式只能被其他合約呼叫,本合約內的函式不能呼叫。

  兩者新增定義的方法相同。

 

chapter10:殭屍吃什麼

   吃cryptoketties。估計是作者的惡作劇。實際上並不會對cryptokitties的資料產生什麼影響,只是讀取其中的資料。

  所以本章的主題就是和其他的智慧合約互動。定義一個新合約,合約只含需要呼叫的合約內的函式頭部,不含其他任何函式或者變數,且用“;”代替函式體大括號。

  比如有一個合約:

contract LuckyNumber {
  mapping(address => uint) numbers;

  function setNum(uint _num) public {
    numbers[msg.sender] = _num;
  }

  function getNum(address _myAddress) public view returns (uint) {
    return numbers[_myAddress];
  }
}

  外部合約需要呼叫getNum函式,則定義介面:

contract NumberInterface {
  function getNum(address _myAddress) public view returns (uint);
}

 

chapter11: 使用介面

contract MyContract {
  address NumberInterfaceAddress = 0xab38... 
  // ^ The address of the FavoriteNumber contract on Ethereum
  NumberInterface numberContract = NumberInterface(NumberInterfaceAddress);
  // Now `numberContract` is pointing to the other contract

  function someFunction() public {
    // Now we can call `getNum` from that contract:
    uint num = numberContract.getNum(msg.sender);
    // ...and do something with `num` here
  }
}

  定義一個介面合約地址就好

 

chapter12:多引數返回值

  例子:

function multipleReturns() internal returns(uint a, uint b, uint c) {
  return (1, 2, 3);
}

function processMultipleReturns() external {
  uint a;
  uint b;
  uint c;
  // This is how you do multiple assignment:
  (a, b, c) = multipleReturns();
}

// Or if we only cared about one of the values:
function getLastReturnValue() external {
  uint c;
  // We can just leave the other fields blank:
  (,,c) = multipleReturns();
}

  後續函式呼叫多引數返回函式時,可以只返回一個或若干個值,但要把其他返回值空出來,加逗號隔開就行。

 

chapter13:獎勵:kitty基因

   讓那些繼承自kitty的zombies有獨特的特徵,即修改定義殭屍特徵的16位數的最後兩位。

chapter14:部署合約