回顧 3 個底層呼叫call()
,delegatecall()
,callcode()
和 3 個轉幣函式call.value()()
,send()
,transfer()
:
- call()
call()
用於 solidity 進行外部呼叫,例如呼叫外部合約函式.call(bytes4(keccak("somefunc(params)"), params))
,外部呼叫call()
返回乙個 bool 值來表明外部呼叫成功與否:
除了delegatecall()
會將外部**作直接作用於合約上下文以外,其他與call()
一致,同樣也是只能獲取乙個 bool 值來表示呼叫成功或者失敗(發生異常)。
- callcode()
callcode()
其實是delegatecall()
之前的乙個版本,兩者都是將外部**載入到當前上下文中進行執行,但是在msg.sender
和msg.value
的指向上卻有差異。
例如 alice 通過callcode()
呼叫了 bob 合約裡同時delegatecall()
了 wendy 合約中的函式,這麼說可能有點抽象,看下面的**:
如果還是不明白callcode()
與delegatecall()
的區別,可以將上述**在 remix-ide 裡測試一下,觀察兩種呼叫方式在msg.sender
和msg.value
上的差異。
- call.value()()
在合約中直接發起 tx 的函式之一(相當危險),
- send()
通過send()
函式傳送 ether 失敗時直接返回 false;這裡需要注意的一點就是,send()
的目標如果是合約賬戶,則會嘗試呼叫它的 fallbcak() 函式,fallback() 函式中執行失敗,send()
同樣也只會返回 false。但由於只會提供 2300 gas 給 fallback() 函式,所以可以防重入漏洞(惡意遞迴呼叫)。
- transfer()
transfer()
也可以發起 ether 交易,但與send()
不同的時,transfer()
是乙個較為安全的轉幣操作,當傳送失敗時會自動回滾狀態,該函式呼叫沒有返回值。同樣的,如果transfer()
的目標是合約賬戶,也會呼叫合約的 fallback() 函式,並且只會傳遞 2300 gas 用於 fallback() 函式執行,可以防止重入漏洞(惡意遞迴呼叫)。
這裡以乙個簡單的示例來說明嚴格驗證底層呼叫返回值的重要性:
function withdraw(uint256 _amount) public
上面給出的提幣流程中使用send()
函式進行轉賬,因為這裡沒有驗證send()
返回值,如果 msg.sender 為合約賬戶 fallback() 呼叫失敗,則 send() 返回 false,最終導致賬戶餘額減少了,錢卻沒有拿到。
後續會有更多有關細節方面的介紹......
solidity智慧型合約程式設計基礎
基礎語法 一 1 函式定義 function 函式名 引數型別 引數1,引數型別 引數2 訪問許可權 讀取資料型別函式 returns 返回資料型別 訪問許可權 public private 一般private許可權的話,引數命名前面加乙個 例如 name 讀取資料型別函式 view函式 唯讀且不可...
solidity智慧型合約重要特性
solidity智慧型合約的一些重要特性,如變長陣列中的storage和memory變數,storage和memory的儲存位置以及字串陣列string使用。區塊鏈開發 以太坊 fabric bcos 密碼技術 共識演算法 位元幣 其他鏈 string,bytes 對於變長陣列,在初始化分配空間前不...
solidity 智慧型合約之間的呼叫
在智慧型合約的編譯過程中,有兩種情況 呼叫者和被呼叫者在乙個sol檔案中和分別在不同的檔案中。在下面的智慧型合約中,demo1和demo在同乙個檔案中,可進行同時編譯,然後逐個發布。pragma solidity 0.5.10 contract demo1 contract demo2 當發布完成,...