solidity編寫智慧型合約的安全漏洞問題(一)

2021-08-25 16:52:39 字數 2016 閱讀 7205

回顧 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.sendermsg.value的指向上卻有差異。

例如 alice 通過callcode()呼叫了 bob 合約裡同時delegatecall()了 wendy 合約中的函式,這麼說可能有點抽象,看下面的**:

如果還是不明白callcode()delegatecall()的區別,可以將上述**在 remix-ide 裡測試一下,觀察兩種呼叫方式在msg.sendermsg.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 當發布完成,...