Solidity

總是得到 Dai/insufficient-allowance 錯誤

  • December 18, 2020

滾動編輯

我正在使用 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 的隨機數) 輸入

我得到這個消息。

混音 IDE 錯誤

當我忽略它並點擊發送交易,並通過 Metamask 確認交易時,我的交易很快就失敗了。這是我的第二個問題。

當我去 etherscan 並查看交易詳情時,它告訴我它失敗了 Failed with error 'Dai/insufficient-allowance'

這甚至意味著什麼?如你所見,我有 3.5 DAI,所以交換 280000 DAI 應該沒問題。 我擁有的 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

使用相同的方法,我能夠載入我需要的其他合約並使用它們。

我不明白或仍然不知道的問題是

  1. 我無法批准已通過 REMIX 發布的代幣
  2. 如果我approve從契約中呼叫,契約會批准將資金用於支出者
  3. 那些關於為 ERC20 代幣編寫合約的 YouTube 影片是我自己的代幣,所以如果我不打算發布自己的代幣,我不應該這樣做。

謝謝你的耐心和幫助我。

在評論中進行了一些討論後,我猜您的問題是該帳戶具有正確的 DAI 餘額,但您的契約沒有。

讓我們列舉一些事情:

  • 答:您的帳戶
  • B:您的自定義契約
  • C:代幣合約(D​​AI)
  • D:Uniswap 路由器合約

所以鏈條是這樣的:

  • A 用 向 B 發送一定數量的 C,用這樣transfer的方式呼叫 C :transfer``transfer(B, amount)
  • 在一個單獨的事務中,A 呼叫 B 的convertDAItoETH
  • convertDAItoETHB 呼叫 C 批准 D 花費 B 的 C 代幣。所以它看起來像這樣:C.approve(D, amount)
  • convertDAItoETHB 呼叫 D 執行交易時,D 執行從 C 撤出並施展魔法

所以你應該做的是將一些代幣轉移到你的合約中,這樣它就可以執行approve. 一旦合約有了代幣,你就可以通過鏈,它應該可以工作。

如果您對批准有疑問,您應該始終檢查令牌是否有批准 - 如果不是,您知道您的批准有問題(或者契約沒有要批准的令牌)。

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