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