總是得到 Dai/insufficient-allowance
錯誤
滾動編輯
我正在使用 Solidity 0.7.5,我正在嘗試通過 UniswapRouter02 從我的帳戶將 DAI 交換為 ETH。
這是我的環境
- 混音IDE
- 帶有 KOVAN 測試網的元遮罩
- 我的關聯賬戶 (msg.sender) 上有大約 2 ETH 和 3 DAI。
我的程式碼如下
pragma solidity >=0.7.0 <0.8.0; import "https://github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/interfaces/IUniswapV2Router02.sol"; import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol"; contract UniswapExample { address internal constant UNISWAP_ROUTER_ADDRESS = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; IUniswapV2Router02 public uniswapRouter; address private kovanDAI = 0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa; address private myAccount = msg.sender; constructor() payable { uniswapRouter = IUniswapV2Router02(UNISWAP_ROUTER_ADDRESS); } function convertDAItoETH(uint daiAmountIn, uint minETHAmountToReceieve) public payable { IERC20 daiToken = IERC20(kovanDAI); require(daiToken.transferFrom(myAccount, address(this), daiAmountIn), "transferFrom failed"); require(daiToken.approve(address(uniswapRouter), daiAmountIn), "approve failed"); uint deadline = block.timestamp + 15; // using 'now' for convenience, for mainnet pass deadline from frontend! uniswapRouter.swapExactTokensForETH(daiAmountIn, minETHAmountToReceieve, getPathForDAItoETH(), myAccount, deadline); } function getPathForDAItoETH() private view returns (address[] memory) { address[] memory path = new address[](2); path[0] = kovanDAI; path[1] = uniswapRouter.WETH(); return path; } }
我從各種 YouTube 影片和 Uniswap ( https://uniswap.org/docs/v2/smart-contract-integration/trading-from-a-smart-contract/ ) 中遵循了這個例子。
我遇到2個問題。
首先,當我點擊參數為 280000,0 的 convertDAItoETH(下限為 0 ETH 的隨機數)
我得到這個消息。
當我忽略它並點擊發送交易,並通過 Metamask 確認交易時,我的交易很快就失敗了。這是我的第二個問題。
當我去 etherscan 並查看交易詳情時,它告訴我它失敗了
Failed with error 'Dai/insufficient-allowance'
。這甚至意味著什麼?如你所見,我有 3.5 DAI,所以交換 280000 DAI 應該沒問題。
請幫忙。剛開始學習這一點,但我只是找不到任何關於如何調試此類錯誤的好資源。
謝謝!
編輯
我把我的網路搬到了 Ropsten。
我創建了一個函式
function setSmartContractAllownace(uint daiAmountIn) public { daiToken.approve(address(this), daiAmountIn); }
當我執行它時,它成功執行(tx:https ://ropsten.etherscan.io/tx/0x1a3b29699f353938f7e8b1825ff69aa44e262d90165e87b107131fc5813d05e3 )
然後我去https://ropsten.etherscan.io/address/0xaD6D458402F60fD3Bd25163575031ACDce07538D#readContract檢查津貼。
_owner (address) 0x548F97658C6acb9a5A0B034116E79bcF98B9a15a -> (my account) _spender (address) 0x99941f04C4a1cba96c237e02F1B2f2b3C5Bae5ea -> (my contract)
返回 0。
但是,如果我同時輸入 _owner 和 _spender 作為我的契約地址,我會得到我設置的地址。
我認為
approve(spender, amountIn)
批准所有者(帳戶)的令牌以供支出者(在這種情況下為契約)支出。我有什麼誤解?
所以,我對已經發布的代幣和我正在寫的代幣合約有一個誤解。
我最終沒有使用 REMIX 和我自己的智能合約。
我使用Web3js並通過此程式碼載入發布 DAI 合約
let token = new web3.eth.Contract(erc20ABI.abi, daiContractAddress) token.methods.approve(uniswapRouter02Address, tokenAmountIn) .send({ from: web3.eth.defaultAccount, gas: gasLimit }) ... // some listeners
使用相同的方法,我能夠載入我需要的其他合約並使用它們。
我不明白或仍然不知道的問題是
- 我無法批准已通過 REMIX 發布的代幣
- 如果我
approve
從契約中呼叫,契約會批准將資金用於支出者- 那些關於為 ERC20 代幣編寫合約的 YouTube 影片是我自己的代幣,所以如果我不打算發布自己的代幣,我不應該這樣做。
謝謝你的耐心和幫助我。
在評論中進行了一些討論後,我猜您的問題是該帳戶具有正確的 DAI 餘額,但您的契約沒有。
讓我們列舉一些事情:
- 答:您的帳戶
- B:您的自定義契約
- C:代幣合約(DAI)
- D:Uniswap 路由器合約
所以鏈條是這樣的:
- A 用 向 B 發送一定數量的 C,用這樣
transfer
的方式呼叫 C :transfer``transfer(B, amount)
- 在一個單獨的事務中,A 呼叫 B 的
convertDAItoETH
- 在
convertDAItoETH
B 呼叫 C 批准 D 花費 B 的 C 代幣。所以它看起來像這樣:C.approve(D, amount)
- 在
convertDAItoETH
B 呼叫 D 執行交易時,D 執行從 C 撤出並施展魔法所以你應該做的是將一些代幣轉移到你的合約中,這樣它就可以執行
approve
. 一旦合約有了代幣,你就可以通過鏈,它應該可以工作。如果您對批准有疑問,您應該始終檢查令牌是否有批准 - 如果不是,您知道您的批准有問題(或者契約沒有要批准的令牌)。