Solidity教學第五集_智能合約互動
區塊鏈的應用日趨廣泛,智能合約現階段也在金融、供應鏈等領域快速發展,讓許多流程高效率自動化,同時資安管控品質也大幅提升。以下將會有五篇教學文章,讓有或沒有程式背景的讀者都能先撰寫基礎智能合約,以便繼續深造或參與區塊鏈相關項目之商業開發案時能順利溝通。
上一篇章我們介紹了buyToken、fallback與Time。忘記的朋友可以回去多加複習。
這一集我們將會教你們如何在solidity當中使用多個智能合約。
智能合約間互相呼叫、MINT
首先我會教你們如何在不同的智能合約間互相呼叫,接下來會教你們繼承(inherit)行為,子智能合約如何繼承父智能合約。
第一我會先將我之前的程式碼重新建構,並創建另一個創造token的智能合約而這個智能合約則是從先前的MyContract分離出來的,這會是一個假的ERC20 token,裡面並不會包含真正ERC-20 智能合約內的所有功能。
現在我們來建立一個token 合約
contract ERC20Token {
string name;
mapping(address => uint256) public balances;
function mint() public {
balances[msg.sender] += 1;
}
}
而讓我們來講解一下 mint()這個function是一個建造token的地方,而為什麼mint是製造token的function因為英文的mint也是製幣廠的意思。再來我們需要有一個name變數以及balances的mapping。接下來我們就可以mint我們的token並在MyContract裡面呼叫 ERC20Token這個智能合約,為了做到這件事我們需要在MyContract裡面建立一個address
contract MyContract {
address public token;
//…
}
現在我們可以在constructor中去設定我們的位置以及數值,可以將ERC20Token的參數只訂到我們的token當中
constructor(address payable _wallet, ERC20Token _token) public {
wallet = _wallet;
token = _token;
}
現在我們的address可以公開使用了,我們就可以在buyToken() 裡面呼叫 mint()
function buyToken() public payable {
ERC20Token _token = ERC20Token(address(token));
_token.mint();
wallet.transfer(msg.value);
}
接下來要講一個比較特別需要注意的部分,如果你現在想要在自己的帳號內去mint token後並查詢balances你會發現沒辦法成功那是為啥呢?我們再來重新看一下我們的程式碼部分:
function mint() public {
balances[msg.sender] += 1;
}
因為我們在function內寫的是從msg.sender,他是參照MyContract的地址的,那如果我們想要在自己的帳號裡面去mint token要怎麼做呢?我們需要將balances裡面的改成tx.origin
function mint() public {
balances[tx.origin] += 1;
}
接下來就可以在其他的智能合約mint token拉!
pragma solidity 0.5.1;
contract ERC20Token {
string name;
mapping(address => uint256) public balances;
function mint() public {
balances[tx.origin] += 1;
}
}
contract MyContract {
address public token;
address payable wallet;
constructor(address payable _wallet, address _token) public {
wallet = _wallet;
token = _token;
}
function buyToken() public payable {
ERC20Token _token = ERC20Token(address(token));
_token.mint();
wallet.transfer(msg.value);
}
}
繼承、Inherit
接下來我們來講繼承,solidity允許我們繼承不同的contract接下來我們來建立一個MyToken,並繼承之前所寫的ERC20TOKEN的contract,這樣我們的子合約就能使用父合約的功能嘍
contract MyToken is ERC20Token {
// …
}
接著我們將我們的ERC20TOKEN改寫
pragma solidity 0.5.1;
contract ERC20Token {
string public name;
mapping(address => uint256) public balances;
constructor(string memory _name) public {
name = _name;
}
function mint() public {
balances[tx.origin] ++;
}
}
我們可以在constructor中覆蓋父合約,接著我們必須建立子合約的符號以及名稱ERC20Token(_name)的作用就是使用了ERC20Token裡面的功能將token名稱設定
contract MyToken is ERC20Token {
string public symbol;
constructor(
string memory _name,
string memory _symbol
)
ERC20Token(_name)
public {
symbol = _symbol;
}
}
接著我們來客製我們的MyToken,我們先來更新一下我們的mint()function,首先我們要建立用來儲存擁有者以及擁有者數量的變數
contract MyToken is ERC20Token {
address[] public owners;
uint256 public ownerCount;
//…
}
接下來我們來更新我們的mint(),當我們要保持在父合約內行為時我們就會用到super這個方法,這樣當我們呼叫mint()時也會去呼叫到父合約的mint() function呼叫完後就會將擁有者加上1並將地址push進去owners變數當中
function mint() public {
super.mint();
ownerCount ++;
owners.push(msg.sender);
}
這樣一來我們就成功建立我們的客製token拉!,並擁有繼承父合約的特性而現在整個合約應該會像這樣
pragma solidity 0.5.1;
contract ERC20Token {
string public name;
mapping(address => uint256) public balances;
constructor(string memory _name) public {
name = _name;
}
function mint() public {
balances[tx.origin] ++;
}
}
contract MyToken is ERC20Token {
string public symbol;
address[] public owners;
uint256 public ownerCount;
constructor(
string memory _name,
string memory _symbol
)
ERC20Token(_name)
public {
symbol = _symbol;
}
function mint() public {
super.mint();
ownerCount ++;
owners.push(msg.sender);
}
}
這些我們所看到的功能以及變數,有些都是繼承所得到的結果。
如果喜歡看更多與區塊鏈技術、應用、科技新知相關的內容,記得留下您的Email並追蹤我們的粉專,那麼新文章上線時,我們將在第一時間通知您,不用再擔心錯過最新消息。