Solidity

如何使用solidity和web3從合約中退還錢包地址

  • July 7, 2019

我正在建構一個應用程序,我希望購買者能夠從契約中尋求退款。本質上,我正在嘗試將 eth 從合約轉移到錢包。當我到達退款點時,MetaMask 中的交易顯示我的錢包正在轉移到合約,而不是我想要的反之亦然。我正在使用 web3 和solidity。這是從尋求退款的帳戶呼叫的我的 js 函式:

window.resellTicket = async function () {    
// send a refund from contract to reseller
try {
 // Call resell method from contract
 const resell = TicketEvent.methods.resellTicket();
 await resell.send({'value': web3.utils.toHex(web3.utils.toWei('.1234', "ether"))});

} catch (err) {
 console.log(err);
}     
load();
}

我的契約中的 resellTicket 方法:

function resellTicket() public payable {
 msg.sender.transfer(ticketPrice);
 isHoldingValidTicket[msg.sender] = false;
 increaseInventory();
}

我在 MetaMask 中看到的: 在此處輸入圖像描述

我還嘗試像from: contract_address在我的 resellTicket js 函式中那樣對合約地址進行硬編碼,在這種情況下我會收到此錯誤:Error: Returned error: Error: WalletMiddleware - Invalid "from" address.

我完全被困在這裡,任何指導將不勝感激!

我不明白為什麼使用者在請求退款時需要或想要發送 ETH。這也意味著您的轉售功能不應該支付。

現在,要回答這個問題(即使它很老,可能仍然可以幫助某人),從您顯示的程式碼中,有幾個可能的原因導致此拒絕:

  1. 您不應該將 wei 數量轉換為十六進制,這會產生意想不到的結果,並且在某些情況下還可能導致還原。web3.utils.toWei 返回的值完全沒有問題。
  2. ticketPrice 應該在你的契約中的某個地方定義
  3. increaseInventory() 可能是罪魁禍首
  4. 合約可能沒有足夠的 ETH

使用 Remix 及其逐步調試器將有助於確定還原的精確位置。

最後,這是最重要的部分,希望能幫助其他讀者避免此類錯誤:

這個轉售功能很容易受到非常基本的攻擊,即使您require(isHoldingValidTicket[msg.sender]);在一開始就添加或作為修飾符,無論如何您都應該這樣做。

 msg.sender.transfer(ticketPrice);
 isHoldingValidTicket[msg.sender] = false;
 increaseInventory();

第一行將 ETH 發送到 msg.sender,這可能是一個惡意的智能合約。它的回退將觸發並可能再次呼叫轉售,並獲得另一次退款,一次又一次,直到耗盡所有 ETH 或耗盡所有 ETH。雖然轉移確實應該通過僅轉發很少的氣體(2300)來保護您免受這種情況的影響,但有時可以規避這樣的限制,例如通過使用其他漏洞,造成巨大的傷害;雖然在開發過程中移動一行程式碼很便宜,但在這種情況下,這只是一種可以完全避免一整類攻擊的好習慣。

你應該始終遵循 Checks-Effects-Interactions 模式,最後發送 ETH。

如果您在同一個函式中有多個外部互動,請非常小心它們的排序方式以及它們之間的相關性。

合約不能發送交易,只有賬戶可以。您需要做的是resellTicket從想要退款的帳戶呼叫函式。

引用自:https://ethereum.stackexchange.com/questions/62561