iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 11
0
Blockchain

區塊練起來-智能合約與DApp開發系列 第 11

[區塊練起來-智能合約與DApp開發] DAY 11 - Solidity 函式庫

貼心小語

上一篇了解到在以太坊的 log 功能以及 Solidity 如何撰寫 log ,接下來會講解 Solidity 另一個重要功能 - 函式庫


何謂函式庫(Library)?

相信不論是 C 、 JAVA 、 Python 、 JavaScript 等開發者都對函式庫不陌生吧!簡單來說,函式庫就是用來幫助開發者在開發上能夠更快速、更簡潔的完成開發,更直白一點就是把許多函式打包成函式庫,讓開發者引入函式庫來使用這些函式,以減少重複的程式碼,在 Solidity 中也可以透過撰寫函式庫來減少重複的程式碼,也因為如此,可以省下反覆部署所消耗的資源、 Gas 。在 Solidity 中的函式庫可以視為物件導向程式語言中的靜態類別,不需要產生實體就可以使用!

建立 Library

物件導向語言大致上都是建立類別並寫靜態方法(Static),雖然說在 Solidity 的 library 可以視為靜態類別,但不使用 contract 建立,也不寫 static ,而是使用 library 建立,下方是一個簡單的 library 範例,是進行字串比對的:

pragma solidity ^0.5.0;

library StringLib {
  function compare(string memory str1, string memory str2) public pure returns (bool) {
    bytes memory str1_bytes = bytes(str1);
    bytes memory str2_bytes = bytes(str2);
    return keccak256(str1_bytes) == keccak256(str2_bytes);
  }
}

可以看到寫法與一般合約沒有太大的差異,基本上把 library 部署到以太坊之後,也與其他合約沒有什麼區別,但 library 其實是有些限制的:

  1. 沒有儲存的功能,意味著不可以使用狀態變數,但可以處理其他合約的狀態變數
  2. 不能使用 payable 函式
  3. 不能使用 event log
  4. 不能被繼承,但可以連接其他函式庫

如何串接合約與函式庫?

library 跟合約一樣需要被部署才能使用,與被繼承的合約不同,繼承是把程式碼 複製到繼承的合約 ,而 library 是 呼叫 library 中程式碼 ,兩者有很大的不同,因此我們可以知道合約要使用 library 就必須要先部署 library ,再拿 library 的位址來用,這大概就是串接的核心思想。

我們先寫一個簡單的合約來使用上方的函式庫:

pragma solidity ^0.5.0;

import "./StringLib.sol";

contract Str {
  function strCompare(string memory s, string memory t) public pure returns (bool) {
    return StringLib.compare(s, t);
  }
}

會發現我們 import 了 library ,但剛剛不是說要先部署 library ,然後透過位址來呼叫 library 的函式嗎?其實並沒有做錯喔!就好像透過 CDN 取得 jQuery ,然後在程式碼裡面使用 jQuery 的功能一樣。

接著我們要先進行編譯:

truffle compile

然後去看 Str.json 裡面的 bytecode ,會找到下面這個東西:

...b600073__StringLib_____________________________633a96fdd...

這個其實就是要 填入 library 的合約位址 ,但我們用 Truffle 來自動化完成這些動作會比較快!首先要先修改部署檔,順序就是先部署 library ,然後透過 link() 來自動綁定,再部署合約:

const StringLib = artifacts.require("StringLib");
const Str = artifacts.require("Str");

module.exports = function(deployer) {
  deployer.deploy(StringLib);
  deployer.link(StringLib, Str);
  deployer.deploy(Str);
};

接著用 truffle console 進行測試就好囉~

Using For

是一個特別的用法,類似原型鏈,能夠將 library 中的函式擴充到某個資料型別上,下方範例使用了 using...for 將 StringLib 的函式擴充到 string 型別,若該函式本身有參數的話,預設是以合約中呼叫 library 函式的變數作為第一個參數:

pragma solidity ^0.5.0;

import "./StringLib.sol";

contract Str {
  using StringLib for string;
  function strCompare(string memory s, string memory t) public pure returns (bool) {
    return s.compare(t);
  }
}

今日小結

了解 Solidity 如何撰寫函式庫,以減少重複的程式碼,並使用 Truffle 來自動化部署與串接。使用 Truffle 來開發智能合約真的是非常方便,只要把該定義的弄好就可以自動化完成,真的太好用了!


參考資料

Libraries in Solidity for code reusability and testing it


上一篇
[區塊練起來-智能合約與DApp開發] DAY 10 - Solidity的event log
下一篇
[區塊練起來-智能合約與DApp開發] DAY 12 - Solidity 特殊變數
系列文
區塊練起來-智能合約與DApp開發31

尚未有邦友留言

立即登入留言