Solidity 智能合約 Constructor 的執行順序

in #blockchain6 years ago (edited)

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

Sort:  

Congratulations @oneleo! You received a personal award!

1 Year on Steemit

Click here to view your Board

Do not miss the last post from @steemitboard:

SteemWhales has officially moved to SteemitBoard Ranking
SteemitBoard - Witness Update

Support SteemitBoard's project! Vote for its witness and get one more award!

Thank you so much for sharing this amazing post with us!

Have you heard about Partiko? It’s a really convenient mobile app for Steem! With Partiko, you can easily see what’s going on in the Steem community, make posts and comments (no beneficiary cut forever!), and always stayed connected with your followers via push notification!

Partiko also rewards you with Partiko Points (3000 Partiko Point bonus when you first use it!), and Partiko Points can be converted into Steem tokens. You can earn Partiko Points easily by making posts and comments using Partiko.

We also noticed that your Steem Power is low. We will be very happy to delegate 15 Steem Power to you once you have made a post using Partiko! With more Steem Power, you can make more posts and comments, and earn more rewards!

If that all sounds interesting, you can:

Thank you so much for reading this message!

Congratulations @oneleo! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 2 years!

You can view your badges on your Steem Board and compare to others on the Steem Ranking

Vote for @Steemitboard as a witness to get one more award and increased upvotes!