Solidity 智能合約 Constructor 的執行順序

By @oneleo12/12/2018blockchain

1、Solidity 的 Constructor 可以讓智能合約部署前給定一初始參數(如合約創始者的地址)
而當有多個合約繼承且每個合約都需要 Constructor 時,我們可以在入口合約採直接指定(directly specify)或是採修飾詞(modifier)的方式給予初始值。

可以參考官方文件說明:
https://solidity.readthedocs.io/en/develop/contracts.html#arguments-for-base-constructors

2、但當多個合約繼承時,Constructor 的執行順序官方文件卻沒有多做說明,
本篇紀錄了測試後的執行順序,供大家參考。

註,本文參考此篇文章:
https://ethereum.stackovernet.com/cn/q/8484

(1)以最下方的合約為例,當我們部署 Derived1 合約時,並給定 _y = 10 的初始值後,其顯示的結果

a、首先會先執行 Base(_x = 7),將 x 設置為 7。
b、接著再執行 Derived1(_y = 10),此時會將 x 覆寫成 10。
c、最後透過讀取智能合約,我們最終得到 x = 10 的結果。

可參考已部署至 Rinkeby 的 Derived1 合約:
https://rinkeby.etherscan.io/address/0x15392f0179d3084a50fc550e9e4863bc49bc6533

(2)另外,當我們部署 Derived2 合約時,同樣給定 _y = 10 的初始值後

a、首先會先執行 Base(_x = 10 * 10),將 x 設置為 100。
b、接著再執行 Derived2(_y = 10),此時會將 x 覆寫成 10。
c、最後透過讀取智能合約,同樣我們最終得到 x = 10 的結果。

可參考已部署至 Rinkeby 的 Derived2 合約:
https://rinkeby.etherscan.io/address/0xeec965493764a65acde7550c7d0aa75b065b9e6e

pragma solidity >=0.5.1;

contract Base {
     uint x;
     constructor(uint _x) public { x = _x; }
}

contract Derived1 is Base(7) {
     constructor(uint _y) public {
         x = _y;
     }

     function getX() view public returns(uint){
         return x;
     }
}

contract Derived2 is Base {
     constructor(uint _y) public Base(_y * _y) {
         x = _y;
     }

     function getX() view public returns(uint){
         return x;
     }
}

(3)最後值得注意的是,被繼承的合約(且有 Constructor),若採修飾詞(modifier)的方式,無論需不需要傳入初始值,都要在入口合約將其 Constructor 加入進去!以下是範例:

pragma solidity >=0.5.1;

contract A {
     constructor(uint a) public { a; }
}

contract B is A {
     // 無傳入初始值的 Constructor
     constructor() public { }
}

contract C is B {
     constructor(uint c) public { c; }
}

contract D is C {
     // 在這邊 B 合約的 Constructor 雖然沒有傳入值,但仍然要在入口合約 D 中的 Constructor 內寫下 B(),否則 B.constructor 不會執行(不會初始化)。
     constructor() public A(1) B() C(3) { }
}

3、藉由以上的實驗我們在建立多重繼承 + 多個建構子時要當心其執行順序
不然可能會造執數值錯誤,或是安全性的疑慮


Donate ADA:
DdzFFzCqrhsup2Q4nnhKJJZ5BRuPkYUSPqDJn72t2dtHtVqsz5kQQmopMQR16Sv9qS5NC4w8Kv5P8XrDH2n2FD2akxtrntjc8hbgAmTz

2

comments