區塊鏈研究實驗室 | 智慧合約如何建立和繼承

買賣虛擬貨幣

在上一篇文章中(傳送門:區塊鏈研究實驗室 | 手把手教你使用Solidity開發智慧合約(五)),我們瞭解瞭如何使用函式,並應用了到目前為止所學到的一切來構建一個多功能簽名錢包。

在本文中,我們將看到如何從另一個合同中建立一個合同,以及如何定義抽象合同和介面。

合同建立

可以透過以太坊交易或在Solidity合約中使用new關鍵字建立合約,該關鍵字將部署該合約的新例項並返回其地址。

透過檢查Solidity文件中給出的示例,讓我們仔細看一下它是如何工作的。我建立了name變數,public以便我們可以檢查其值並建立一個事件以讀取該createToken函式的返回值(我們將在事件的另一篇文章中介紹):

// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.4.22 <0.8.0;

contract OwnedToken { TokenCreator creator; address owner; bytes32 public name; constructor(bytes32 _name) { owner = msg.sender; creator = TokenCreator(msg.sender); name = _name; }
function changeName(bytes32 newName) public { if (msg.sender == address(creator)) name = newName; }
function transfer(address newOwner) public { if (msg.sender != owner) return;
if (creator.isTokenTransferOK(owner, newOwner)) owner = newOwner; }}

contract TokenCreator { event TokenCreated(bytes32 name, address tokenAddress);
function createToken(bytes32 name) public returns (OwnedToken tokenAddress){ tokenAddress = new OwnedToken(name); emit TokenCreated(name, address(tokenAddress)); }
function changeName(OwnedToken tokenAddress, bytes32 name) public {
tokenAddress.changeName(name); }
function isTokenTransferOK(address currentOwner, address newOwner) public pure returns (bool ok){
return keccak256(abi.encodePacked(currentOwner, newOwner))[0] == 0x7f; }}

這次,我將使用Tuffle框架——您可以按照他們製作的快速入門指南對其進行學習。

首先,我們將建立一個新專案並透過執行以下命令對其進行初始化:

> mkdir token> cd token> truffle init

開啟專案,然後更新truffle-config.js檔案以使用您將在其中部署合同的網路IP和埠以及您正在使用的Solidity編譯器的版本。就我而言,我正在使用Ganache執行網路。

現在,我們可以在contracts資料夾中建立合同。複製並貼上程式碼後,您需要在migrations資料夾中建立一個遷移檔案以部署TokenCreator合同。將其命名為2_deploy_token.js,然後複製並貼上以下程式碼。

const TokenCreator = artifacts.require("TokenCreator");module.exports = function (deployer) { deployer.deploy(TokenCreator);};

現在返回命令列,然後鍵入truffle console以啟動Truffle控制檯-您可以在其中編譯和部署合同:

我們現在要做的是檢索TokenCreator已部署例項的例項。然後,我們將呼叫該createToken函式兩次,並儲存每個新建立合約的地址。

如果使用的是Ganache,則可以看到兩個代表合同呼叫的交易新增到了交易列表中,其中資料欄位設定為函式選擇器的四個位元組,並傳遞了引數。如果您想知道真正發生了什麼以及如何建立這些合同,請繼續關注我。

正如我們所知,合同只是另一種型別的帳戶,那麼到底發生了什麼,當我們所謂的createToken功能狀態資料庫進行了更新,包括與四個變數,每個帳戶儲存(新建立的帳戶nonce,balance,storage_root,code_hash)正確初始化。

如果現在返回到Truffle控制檯,則可以檢查每個事務的日誌以獲取每個合同的地址,然後可以呼叫名稱getter來驗證它們確實是兩個單獨的實體。

建設者宣言

合同的建構函式在建立合同時被呼叫,並且不會與其餘的合同程式碼一起儲存在區塊鏈上。
建構函式是可選的。只允許一個建構函式,這意味著不支援過載。

使用constructor關鍵字宣告建構函式:

contract A { uint a; bool b; constructor(uint _a, bool _b){ a = _a; b = _b; } ...}

抽象合約

需要將合同標記為abstract未執行其至少一項功能時。abstract即使實現了所有功能,合同也可能被標記為。

這可以使用abstract合同的關鍵字來完成,未實現的功能應具有virtual允許多型的關鍵字。

abstract contract A { function f() public pure virtual;}

即使所有功能都已實現,抽象協定也無法直接例項化。它們可以用作定義其他合同繼承的特定行為的基本合同。已實現的功能應具有override關鍵字。

abstract contract A { function f() public pure virtual;}abstract contract B is A { function f() public pure override { //function body }}

如果派生合同未實現所有未實現的功能,則也需要對其進行標記abstract。

介面

介面類似於抽象協定,但是不能實現任何功能。還有其他限制:

  • 它們不能從其他合同繼承,但是可以從其他介面繼承

  • 所有宣告的函式必須是外部的

  • 他們不能宣告建構函式

  • 他們不能宣告狀態變數

介面使用interface關鍵字宣告。

interface A { function f() external pure;}

介面中宣告的所有函式都是隱式的virtual。

結論

至此,我們對智慧合約的建立與繼承講完了。下次,我們將研究工廠模式以及如何在Solidity中使用它們。

作者:鏈三豐,來源:區塊鏈研究實驗室

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读