1

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

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

如果我仍然发送交易,元掩码会产生“交易 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;
  }

}

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

4

1 回答 1

0

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

假设您的合同是合同A,链接合同是合同B

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

现在在内部这个函数调用合约 B 上的批准,这里合约 A 是 msg.sender,因为合约是调用函数的人

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

于 2022-01-14T18:56:57.150 回答