合約轉賬/存入乙太幣失敗
我正在嘗試將乙太幣存入智能合約。查看文件,我的方法首先看起來像這樣:
// SPDX-License-Identifier: MIT pragma solidity ^0.0.8; contract SendEther { function deposit(uint256 amount) public payable { require(msg.value == amount); } }
但是,失敗並顯示以下錯誤消息:
$$ vm $$ 來自:0x5c6…21678
至:SendEther.deposit(uint256) 0xe63…4ddf5
值:0 wei
數據:0xb6b…03039
日誌:0
雜湊:0x50c…acc83
狀態 false 交易已開採但執行失敗
事務雜湊 0x50cb8aab1042aef79e8bf285346213a1edfa106b2a7421ee159da82b693acc83
從 0x5c6B0f7Bf3E7ce046039Bd8FABdfD3f9F5021678
to SendEther.deposit(uint256) 0xe63D12C600b87F5da3C32C7cB3C1b1A84944ddf5 gas 3000000 gas 交易成本 21614 gas 執行成本 21614 gas input 0xb6b…03039 解碼輸入 { “uint256 amount”: “12345” } 解碼輸出 {} logs
$$ $$val 0 衛 交易到 SendEther.deposit 錯誤:VM 錯誤:還原。
revert 事務已恢復到初始狀態。
注意:如果您發送值並且您發送的值應該小於您目前的餘額,則呼叫的函式應該是應付的。
調試事務以獲取更多資訊。
然後我嘗試使用 transfer 或 call 方法發送 Ether。
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract SendEther { receive() external payable {} function sendViaTransfer(address payable to, uint256 amount) public payable { to.transfer(amount); } }
這導致了這個錯誤:
$$ vm $$ 來自:0x147…C160C
至:SendEther.sendViaTransfer(address,uint256) 0x70c…a304B
值:0 wei
數據:0xd27…004d2
日誌:0
雜湊:0xc29…0cf23
狀態 false 交易已開採但執行失敗
交易雜湊 0xc296ba642bca2e19c304a9e28381b3b523fdb86a94fcbc19e14ad5847a20cf23
從 0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C
to SendEther.sendViaTransfer(address,uint256) 0x70c001c84C723e3EfbF852D3e6AdaEb69A8a304B
氣體 3000000 氣體
交易成本 29070 gas
執行成本 29070 gas
輸入 0xd27…004d2
解碼輸入{
“地址”:“0x70c001c84C723e3EfbF852D3e6AdaEb69A8a304B”,
“uint256 數量”:“1234”
}
解碼輸出{}
日誌
$$ $$ val 0 衛
交易到 SendEther.sendViaTransfer 錯誤:VM 錯誤:還原。
revert 事務已恢復到初始狀態。
嘗試使用“呼叫”或“發送”會導致相同的錯誤。
我究竟做錯了什麼?
日誌顯示消息值為 0。請確保在點擊功能之前在 remix 中設置 VALUE,以便發送值
首先,對於第一個範例,我認為您不需要
require(msg.value == amount)
.msg.value
是發送到該合約的 eth 值。該amount
參數在那裡沒有做太多。如果msg.value
發送的與amount
. 但無論如何,這樣做是多餘的。但是要確保如果你發送一個amount
參數5
,那麼你也應該發送5
weis,這樣這個函式就不會失敗。function deposit(uint256 amount) public payable { require(msg.value == amount); }
第二個例子看起來不錯。但是你的合約至少需要有
amount
balance 或者你應該發送一個與參數msg.value
相同的 balance ( )amount
。function sendViaTransfer(address payable to, uint256 amount) public payable { to.transfer(amount); }
我用你可以接收和發送乙太的所有方式編寫了一些程式碼,並附上了一些評論,這可能對你有幫助。所有範例工作。請記住,在嘗試將乙太幣發送到另一個地址之前,乙太幣在您的合約中有足夠的餘額
SendEther
,或者向該合約發送足夠的乙太幣,以便它可以使用msg.value
並發送該金額。//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Receiver { receive() external payable {} fallback() external payable {} function receiveBalance() public payable {} function getBalance() public view returns(uint256) { return address(this).balance; } //.. Other functionalities here (withdraw, etc). } contract SendEther { address public owner = msg.sender; // Maybe you want to control who can withdraw the balance from this contract. modifier onlyOnwer() { require(msg.sender == owner); _; } function deposit(uint256 amount) public payable { require(msg.value == amount); // No need to send or check an amount here. } function deposit_v2() public payable { // We have the option to do nothing here. As long as the function is `payable`, we receive the eth. } // If you want to only receive eth without doing any special logic, then you can use `receive` and/or `fallback`. receive() external payable {} fallback() external payable {} // This function is `payable`, so this contract is receving some amount and sending `amount` to another address function sendViaTransfer(address payable to, uint256 amount) public payable onlyOnwer { // Maybe you want to check that this contract has enough balance to send the requested amount. require(address(this).balance >= amount, "Not enough balance in the contract."); to.transfer(amount); } // This function is `payable`, so this contract is receving some amount and sending that same amount (msg.value) to another address function sendViaTransfer_v2(address payable to) public payable onlyOnwer { to.transfer(msg.value); } // This function is `payable`, so this contract is receving some amount and sending `amount` to another address function sendViaSend(address payable to, uint256 amount) public payable onlyOnwer { // Maybe you want to check that this contract has enough balance to send the requested amount. require(address(this).balance >= amount, "Not enough balance in the contract."); bool success = to.send(amount); require(success, "Error sending eth"); } // This function is `payable`, so this contract is receving some amount and sending that same amount (msg.value) to another address function sendViaSend_v2(address payable to) public payable onlyOnwer { bool success = to.send(msg.value); require(success, "Error sending eth"); } // This function is `payable`, so this contract is receving some amount and sending `amount` to another address function sendViaCall(address payable to, uint256 amount) public payable onlyOnwer { // Maybe you want to check that this contract has enough balance to send the requested amount. require(address(this).balance >= amount, "Not enough balance in the contract."); (bool success, ) = to.call{value: amount}(""); require(success, "Error sending eth"); } // This function is `payable`, so this contract is receving some amount and sending that same amount (msg.value) to another address function sendViaCall_v2(address payable to) public payable onlyOnwer { (bool success, ) = to.call{value: msg.value}(""); require(success, "Error sending eth"); } // This function is `payable`, so this contract is receving some amount and sending `amount` to another address function sendViaCustomFunction(address payable to, uint256 amount) public payable onlyOnwer { // Maybe you want to check that this contract has enough balance to send the requested amount. require(address(this).balance >= amount, "Not enough balance in the contract."); Receiver(to).receiveBalance{value: amount}(); } // This function is `payable`, so this contract is receving some amount and sending that same amount (msg.value) to another address function sendViaCustomFunction_v2(address payable to) public payable onlyOnwer { Receiver(to).receiveBalance{value: msg.value}(); } function getBalance() public view returns(uint256) { return address(this).balance; } }