回退函式可以完成多少計算?
只需將 Ether 發送到合約,即可執行合約的程式碼。在 Solidity 中,此程式碼映射到它所謂的回退函式。
回退功能可以完成多少工作?
備份函式可以進行與獲得多少氣體一樣多的計算。
有 2 個案例(基本上
recipient.send
和recipient.call{value:...}("")
),案例 2 具有安全隱患,是 2016 年 6 月 17 日 DAO 如何被攻擊和利用的關鍵部分。案例一:2300氣
如果使用or
recipient
呼叫合約的備份功能,則只能獲得2300 的 gas 津貼recipient.transfer``recipient.send
。recipient
這與使用 支付的外部帳戶相同web3.eth.sendTransaction({to:recipient, gas:21000, ...})
。乙太坊部落格文章的最後一部分解釋說:
如果你想讓你的合約接收乙太幣,你必須降低它的備份功能。它只能使用 2300 gas,既不允許任何儲存寫入,也不允許沿 Ether 發送的函式呼叫。基本上,您在回退函式中唯一應該做的就是記錄一個事件,以便外部程序可以對事實做出反應。
外部程序的範例包括web3.js 過濾器和監視。
**注意:**自 2019 年 12 月起,
recipient.transfer
不再recipient.send
推薦:在伊斯坦布爾更新後 transfer() 是否仍然安全?案例2:盡可能多的氣體,注意安全
recipient.call{value:...}("")
(並使用相關功能,如.callcode
,.delegatecall
)將提供備份功能幾乎$$ 1 $$與呼叫者剩餘的氣體一樣多。 為了獲得與案例 1 相同的效果(2300 gas 津貼)和安全性,呼叫者在呼叫
recipient
by 時必須明確將 gas 限制為零:recipient.call{gas: 0, value: ...}("")
(theDAO沒有限制gas, 2016年6月17日遭遇重入攻擊。 )
腳註
$$ 1 $$解釋為什麼一個備份函式得到了幾乎所有的氣體,但不是所有的氣體。chriseth (Solidity 作者)說:
這是 EVM 的古怪之處之一。你不能只說“把我所有的汽油和電話一起送出去”,你總是必須給出一個明確的號碼。我們確實有 GAS 操作碼,它為我們提供了仍然可用的 gas 量,但問題是執行呼叫本身也會消耗一些 gas,所以我們必須從 GAS 提供的值中減去呼叫成本的 gas 量,並且我們還必須減去執行減法所需的氣體量……