具有支付功能的契約可以一次性接收 ERC20 代幣?
我正在嘗試使用接收 ERC20 令牌(即:DAI)的函式編寫智能合約,但呼叫此函式的事務總是失敗。
假設我首先將 ERC20 合約地址記錄在一個可以處理多個代幣的映射中,但對於這個範例,我只是將“DAI”作為 tokenName 並在 Ropsten 中分配其 DAI 合約地址:
contractAddressERC20[tokenName] = 0xaD6D458402F60fD3Bd25163575031ACDce07538D;
我也在使用 OpenZeppelin 的 ERC20 介面:
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
然後,我有這個功能來接收 ERC20 代幣。例如,我將傳遞 ‘DAI’ 作為 tokenName 和 1 DAI (1000000000000000000)
function depositERC20Token(string memory tokenName, uint256 amount) public { IERC20(contractAddressERC20[tokenName]).approve(address(this), amount); IERC20(contractAddressERC20[tokenName]).transferFrom(_msgSender(), address(this), amount); emit DepositERC20Token(tokenName, _msgSender(), amount); }
但是,呼叫此函式總是失敗。不確定使用者是否應該直接從 DAI 合約中呼叫“approve”函式,然後僅使用“transferFrom”從我的合約中呼叫“depositERC20Token”。難道不能從我的契約中進行“批准”和“轉帳”嗎?如果沒有,使用者應該執行 2 個事務,從使用者體驗的角度來看,這不是很好。
呼叫此契約時,有沒有辦法一次性完成批准和轉移?我聽說過 ERC777,但如果可能的話,我更願意保持 ERC20 標準。
*_msgSender() 等價於 msg.sender,在 OpenZeppelin 的 Context.sol 中定義
通過
approve(someAccount, someAmount)
在合約功能中執行,您正在批准從該合約someAccount
轉移至。someAmount
因此,通過
approve(address(this), someAmount)
在合約函式中執行,您正在批准該合約從其自身轉移代幣!顯然,它不允許你再執行
transferFrom(someOtherAccount, ..., ...)
,因為合約沒有被批准從someOtherAccount
.而且你無論如何都不希望它允許這樣做,因為如果它允許,那麼整個 ERC20 模型作為一個金融系統將毫無價值,因為你可以批准並從任何你想要的賬戶轉移。
簡而言之,您需要在
approve
此合約之外呼叫,使用您希望此合約從中轉移代幣的帳戶。