外部合約 內部合約
外部合約 Externaly Owned Account (EOA): 類似MetaMusk那種錢包,用於交易資金、初始化交易、部署智能合約、提領,並且擁有一個私鑰來管理帳戶
內部合約 Contract Account : 比較像是在區塊鏈「內」自動化運作的錢包,沒有私鑰來管理整個帳戶,程式碼決定了整個合約帳戶的運作
對於Contract Account 來說,只要沒有在程式碼上寫上Owner 或相關的操作定義,這個Contract Account 就會失去人為的控制,但反之只要我們寫上完善、完整的韓式之後,就可以透過「操控特定函式」這樣一個「發送交易」的行為來控制合約。
換句話說如果這個合約裡面有非常多供特定人士操作的合約,那麼這個合約從廣義來說便不是真正的去中心化。
在區塊鏈上只能用EOA 初始化交易,也就是說在任何的互動做成中,只要原點是EOA,接下來無論是Contract Account 或EOA 皆可與彼此交互運作
路徑為:EOA-> Contract Account -> EOA -> EOA
不可為:Contract Account -> …
函式與合約互動的方法
Balance
- 取得當前地址的餘額,以wei為單位
- <address>.balance()
transfer
- 有Gas限制,最大2300,這個限制可以用來防止重送攻擊(Re-Entrancy Attacks)
- <address payable>.transfer(uint256 account)
- 此韓式會從合約轉入帳號 amount 價值的以太幣,這邊需要注意的是,當我們沒有特別宣告單位時,uint的型態變數輸入值都是以wei為單位
- 如果執行失敗會拋出錯誤,接收對象若是合約需要注意其中是否有fallback function存在
- 從自容合約傳送相對數量(以wei為單位)的 ether給指定地址。在這裡和我們平常撰寫物件導向程式語言寫法的方向不太一樣,可以稍微注意一下
send
- 有Gas限制,最大2300
- <address payable>.send( uint 256 amount) returns (bool)
- 此函式會從合約轉入帳號 amount 價值,wei單位的eth
- 是一個屬於 .transfer的低階部件,如果執行.send 失敗的話不會把整個合約終止,而是會return false 不會改變任何的「狀態」
call
- 沒有Gas限制,和send一樣,如果執行失敗不會停止而是return false
- 是較為適合轉入合約的狀況使用,因爲call 可以調整Gas,也可以註明Function Signature 來與轉入合約的Function做對接
- <address>.call(bytes memory) returns ( bool, bytes memory)
- <address>.calll{value: amount} (bytes memory) 功能類似 <address>.transfer 會從合約轉入帳號 amount 價值的eth
- <address>.call{gas: amount }(byte memory)可以調整供給的Gas數量,並且return一個bool值
delegatecall
- 和call基本一樣,只是使用delegate call時不能使用 value,但可附帶註明Gas
staticcall
- 和call基本一樣,只是使用時不能改變contract的任何狀態(state)
為了保證匯款或是提款時的安全性,實作以上函式時,我們都必須不段地檢查回結果(Return 或 Console Window 的資訊)
必須要知道的是,call, delegatecall, statical 以上三者都屬於底層呼叫,可以呼叫gas參數,而且在發生錯誤時不會拋出異常,只會回傳false。此三者都是非常底層的函數,所以要勁量避免直接在我們的智能合約 hard-code gas,除非我們確定真的要這麼做