在 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 真正做的是让合约批准自己移动我认为它没有的自己的代币
我是 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 真正做的是让合约批准自己移动我认为它没有的自己的代币