Remix
無法解釋執行時錯誤
當我在 require 語句中使用變數 minimum
require(msg.value >= minimum, "Below Minimum");
我在 Remix 中收到以下錯誤。但是,如果我用 0 而不是 minimum 對 require 語句進行硬編碼,則一切正常。為什麼?
交易到 SendContractEther.sendEtherToContract 錯誤:VM 錯誤:還原。revert 事務已恢復到初始狀態。注意:如果您發送值並且您發送的值應該小於您目前的餘額,則呼叫的函式應該是應付的。調試事務以獲取更多資訊。
我正在從合約 SendContractEther 向合約 King 發送乙太幣。
感謝您對此行為的解釋。
// SPDX-License-Identifier: MIT pragma solidity 0.7.4; contract King { uint public minimum; address payable public owner; constructor() payable { owner = msg.sender; minimum = 0; } receive () external payable { require(msg.value >= minimum, "Below Minimum"); owner.transfer(msg.value); } }
// SPDX-License-Identifier: MIT pragma solidity 0.7.4; contract SendContractEther { address payable public contractAddress ; // Assign the address of the Contract constructor(address payable _contractAddress) payable { contractAddress = _contractAddress; } function sendEtherToContract() external payable { contractAddress.transfer(address(this).balance); } }
這個問題問得好!
由於從另一個合約(即,不是從外部擁有的賬戶)將 ETH 轉移到合約而執行的功能
receive
和執行時的 gas-stipend 為2300。fallback
在你的情況下:
require(msg.value >= minimum, "Below Minimum"); owner.transfer(msg.value);
- 讀取儲存變數的成本
minimum
是 800 gas- 讀取儲存變數的成本
owner
是 800 gas- 通過執行外部函式呼叫的成本
transfer
至少為 800 gas(取決於轉移的數量,以及雙方的餘額)評估表達式
msg.value >= minimum
(以及讀取局部變數msg.value
本身)所需的氣體可以忽略不計,但正如您所見,即使沒有它,您也已經超過了氣體津貼,至少使用 2400 氣體。
minimum
因此,用硬編碼替換儲存變數0
可能會讓你遠遠低於 gas-stipend(使用大約 1600 gas)並解決問題。您可以通過將 ETH 從外部擁有的賬戶轉移到該合約來驗證這一點,該賬戶不適用任何 gas-stipend,並看到它成功完成,儘管使用了儲存變數
minimum
(前提是您轉移的金額等於或大於minimum
)。或者,您可以重命名函式
receive
,然後直接從另一個合約呼叫它:contract King { ... function test() external payable { require(msg.value >= minimum, "Below Minimum"); owner.transfer(msg.value); } } contract SendContractEther { ... function sendEtherToContract() external payable { King(contractAddress).test{value: address(this).balance}(); } }
由於這裡沒有gas-stipend,因此執行
sendEtherToContract
應該成功完成。