Web3js
具有多個合約“發送”請求的交易
最近,我們試圖創建一個應用程序,允許使用者使用 ERC-20 代幣購買 NFT(假設出於這些目的,它是像 DAI 或 USDC 這樣的穩定幣)。所以從弄清楚一切我們
public async approve(): Promise<void> { const ticketPrice = 100; // Approve the contract to transfer on your behalf const contract = new this.web3js.eth.Contract(TestUSDContract.abi, this.USD_ADDRESS); const success = await contract.methods.approve('<CONTRACT ADDRESS>', ticketPrice).send({from: '<USER ADDRESS>'}); console.log('Status ' + success); //Then purchase the item the user wants const contract2 = new this.web3js.eth.Contract(LotteryContract.abi, this.CONTRACT_ADDRESS); const value = await contract2.methods.buyItem().send({from: '<USER ADDRESS>'}); console.log('contract2 ' + value); }
為了透明起見,以下是用於測試的合約方法
function buyTicket() external returns (string memory) { testUsdContract.transferFrom(msg.sender, address(this), itemAmount); return "SUCCESS"; }
這一切都有效,然而,從使用者體驗的角度來看,使用者從使用者界面中獲得了兩個對話框,這似乎是糟糕的使用者體驗。同樣根據我的理解(並且有意義),必須從使用者的帳戶呼叫批准方法(並且不能來自契約,因為
msg.sender
ERC-20 代幣將是我們的契約)。
- 我想知道對此存在哪些解決方法以及其他應用程序如何完成接受 ERC-20 項目作為付款(最好以使用者友好的方式)。
- 這也引出了一個問題,當第一個請求成功而第二個請求失敗時會發生什麼(可能是網路錯誤或契約異常),通常在 DAPP 中如何處理(以及其他 dapps 是如何做到的?)
目前沒有辦法使用 ERC-20 代幣進行兩次
approve
交易transferFrom
。你不能直接向合約發送代幣,因為接收合約不知道交易(就像普通的 ETH 交易一樣)。大多數 dApp 預先以最大可能
uint256
值進行批准,這實質上意味著 dApp 可以轉移無限數量的代幣。這樣您就不必對每筆交易進行批准,只需一次即可讓使用者加入。然而,這樣做的缺點是你的合約現在控制了使用者的全部代幣餘額,從安全形度來看這並不是很好。有一些 EIP 試圖解決這個問題,例如:
- EIP-2711,它引入了新的交易類型,包括進行批量交易的交易類型。您可以在一個批量交易中進行審批和轉賬。如果您有興趣了解有關交易類型的更多資訊,我寫了一篇關於這些和 EIP-2711 的部落格文章,您可以在此處找到。
- EIP-3074,它允許合約在 EOA 的上下文中發送交易。這樣,合約可以使用
AUTHCALL
操作碼進行呼叫,並且msg.sender
是使用者的地址,而不是合約地址。我制定了一個可以進行任意(批量)呼叫的契約,您可以在此處找到。不幸的是,在乙太坊網路中包含其中一個(或另一個類似的 EIP)之前,沒有辦法繞過必鬚髮送兩個交易
這也引出了一個問題,當第一個請求成功而第二個請求失敗時會發生什麼(可能是網路錯誤或契約異常),通常在 DAPP 中如何處理(以及其他 dapps 是如何做到的?)
您可以事先檢查使用者是否已經批准(通過檢查 ERC-20 契約上的津貼是否足夠高)。這樣,第二次交易是否失敗並不重要。