在 NFT Mint 函数中燃烧已部署的 ERC 代币 - 编译,但交易失败

Burning Deployed ERC Tokens In an NFT Mint Function - Compiles, but Transaction Fails

我是 Solidity 的新手,最近一直在努力学习技巧。作为参考,在完成基本的加密货币僵尸教程系列后,我一直使用此视频 (https://www.youtube.com/watch?v=tBMk1iZa85Y) 中的代码作为入门。

我一直在尝试调整此视频中提供的 Solidity 合约代码(我运行得很好!),以要求在铸造 NFT 之前销毁指定数量的 ERC-20 代币作为练习我。我认为我应该有一个有效的实现,它在 Remix 中编译,然后部署到 Rinkeby。在部署到 Rinkeby 之后,我在 Remix 中调用了 allowAccess 函数,并且成功了。但是,当我使用这两个参数调用 mint 函数时,我得到:“gas estimation errored with the following message (see below). 交易执行可能会失败。你想强制发送吗?执行已恢复。”

如果我仍然发送交易,metamask 会产生“交易 xx 失败!交易遇到错误。”。

我肯定它与“require(paymentToken.transfer(burnwallet, amounttopay),”transfer Failed”);有关,但我不确定哪里出了问题。以下是我的整个合同代码。我目前只是与 Rinkeby 上的 Chainlink 合约进行交互,因为他们有一个方便的令牌水龙头。

pragma solidity ^0.8.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Counters.sol";

contract myNFTwithBurn is ERC721, Ownable  {
    address externalTokenAddress = 0x01BE23585060835E02B77ef475b0Cc51aA1e0709; //Token Type to burn on minting
      uint256 amounttopay = 5; //number of these tokens to burn
          IERC20 paymentToken = IERC20(externalTokenAddress); //my code: create an interface of the external token
        address burnwallet = 0x000000000000000000000000000000000000dEaD; //burn wallet

  using Counters for Counters.Counter;
  Counters.Counter private _tokenIds;
        using Strings for uint256;
        
        // Optional mapping for token URIs
        mapping (uint256 => string) private _tokenURIs;

        // Base URI
        string private _baseURIextended;
        
    constructor() ERC721("NFTsWithBurn","NWB") {
    }
        function setBaseURI(string memory baseURI_) external onlyOwner() {
            _baseURIextended = baseURI_;
        }
        
        function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
            require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
            _tokenURIs[tokenId] = _tokenURI;
        }
        
        function _baseURI() internal view virtual override returns (string memory) {
            return _baseURIextended;
        }
        
        function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
            require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

            string memory _tokenURI = _tokenURIs[tokenId];
            string memory base = _baseURI();
            
            // If there is no base URI, return the token URI.
            if (bytes(base).length == 0) {
                return _tokenURI;
            }
            // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
            if (bytes(_tokenURI).length > 0) {
                return string(abi.encodePacked(base, _tokenURI));
            }
            // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
            return string(abi.encodePacked(base, tokenId.toString()));
        }
function allowAccess() public
{
    paymentToken.approve(address(this), 5000000); //This is my attempt to allow the contract access to the user's external tokens, in this case Chainlink (paymentToken)
}
function mintItem(address to, string memory tokenURI)
      public
      onlyOwner
      returns (uint256)
  {
    require(paymentToken.transfer(burnwallet, amounttopay),"transfer Failed"); //Try to transfer 5 chainlink to the burn wallet

      _tokenIds.increment();

      uint256 id = _tokenIds.current();
      _mint(to, id);
      _setTokenURI(id, tokenURI);

      return id;
  }

}

如果有人至少可以指出我在添加的代码中做错了什么,请指出! TIA!

我不确定你为什么要刻录 link 以便铸造和 nft 但首先检查 link 代码是否没有要求检查目标地址是否是刻录地址如果已经刻录 link 是不可能的,你应该使用任何其他 erc20 也许你自己的 erc20,而且你的合同可能没有任何 link 如果你想转移 link 从用户那里你应该在合同中这样做 paymentToken.transferFrom(msg.sender,destinationAddress,amount) 如果用户之前批准你的合同你将能够发送令牌,我想 allowAccess 功能的目的是让用户批准合同移动永远不会工作的代币,批准函数让任何调用它的人批准任何地址移动一定数量的代币,关键是要知道谁批准让其他人移动函数使用的代币msg.sender 来解释这项工作如何看这个例子

假设你的合约是合约A,link合约是合约B

现在用户在合约A中调用了allowAccess,所以这里的msg.sender是用户,因为他们调用了函数

现在这个函数内部调用了合约B的approve,这里的合约A是msg.sender,因为合约是谁调用了函数

所以 allowAccess 真正做的是让合约批准自己移动我认为它没有的自己的代币