简体   繁体   English

无法在 ERC721 智能合约中设置批准或转让所有权

[英]Unable to set approval nor transfer ownership in ERC721 smart contract

Can someone explain to me how I can set approval for ERC721 contract?有人可以向我解释如何设置 ERC721 合同的批准吗?

1- At first, the token once minted belongs to the marketplace 2- with buy, I need to transfer ownership of the token to the caller 1- 首先,铸造的代币属于市场 2- 通过购买,我需要将代币的所有权转移给调用者

I keep getting these errors我不断收到这些错误

X Fail with error 'ERC721: approve caller is not token owner nor approved for all' x Fail with error 'ERC721: approve to caller' X 失败并出现错误“ERC721:批准调用者不是令牌所有者,也不是所有人都批准” x 失败并出现错误“ERC721:批准调用者”

This is my smart contract: the mint buy function //The first time a token is created, it is listed here function createToken(string memory tokenURI, string memory name, uint256 price) public payable returns (uint) { uint256 currentTokenId = _tokenIds.current(); This is my smart contract: the mint buy function //The first time a token is created, it is listed here function createToken(string memory tokenURI, string memory name, uint256 price) public payable returns (uint) { uint256 currentTokenId = _tokenIds.当前的();

    //Mint the NFT with tokenId newTokenId to the address who called createToken
    _safeMint(msg.sender, currentTokenId);

    //Map the tokenId to the tokenURI (which is an IPFS URL with the NFT metadata)
    _setTokenURI(currentTokenId, tokenURI);

    //Helper function to update Global variables and emit an event
    _create(currentTokenId, tokenURI, name, listPrice);

    setApprovalForAll(address(this), true);

    //Increment the tokenId counter, which is keeping track of the number of minted NFTs
    _tokenIds.increment();
    uint256 newTokenId = _tokenIds.current(); 
    return newTokenId;
}

function _create(uint256 tokenId, string memory tokenURI, string memory name,  uint256 price) private {
    //Make sure the sender sent enough ETH to pay for listing
    require(msg.value == listPrice, "Hopefully sending the correct price");
    
    //Just sanity check
    require(price > 0, "Make sure the price isn't negative");

    //Update the mapping of tokenId's to Token details, useful for retrieval functions
    idToToken[tokenId] = Token(
        tokenId,
        tokenURI,
        name,
        payable(address(this)),
        price,
        true
    );

    _transfer(msg.sender, address(this), tokenId);
    //Emit the event for successful transfer. The frontend parses this message and updates the end user
    emit TokenListedSuccess(
        tokenId,
        address(this),
        price,
        true
    );
}
function buyNFT(uint256 tokenId) public payable {
        require(msg.value > 0, "You need to send some ether");
        require(msg.value == idToToken[tokenId].price, "Please submit the asking price in order to complete the purchase");

        approve(msg.sender, tokenId);
        setApprovalForAll(msg.sender, true);

        transferFrom(address(this), msg.sender,tokenId);
       //  safeTransferFrom(address(this), msg.sender, tokenId);
        payable(idToToken[tokenId].owner).transfer(msg.value);

        //update the details of the token
        idToToken[tokenId].owner = payable(msg.sender);
        idToToken[tokenId].isForSale = false;
        _itemsSold.increment();
   
        //Transfer the proceeds from the sale to the seller of the NFT
        payable(address(this)).transfer(msg.value);

        // emit Event
    }

this is my client app:这是我的客户端应用程序:

const buyToken = (...args) => {
            const [tokenId] = args
            return new Promise(async resolve => {
               try {
                    let transaction = await contract.buyNFT(tokenId, { 
                        gasLimit: 5500000, 
                        value: price.toString()
                    });
                    await transaction.wait();
                    resolve()
               } catch (e) {
                  console.error(e)
               }
            })
        }

I think the issue is with我认为问题在于

transferFrom(address(this), msg.sender,tokenId);

You are transferring from the contract address to the msg.sender but it should be from the nft owner or token id owner .您正在从合约地址转移到msg.sender但它应该来自 nft nft ownertoken id owner

The approve() function grants a third party the ability to transfer a single token id.批准() function 授予第三方传输单个令牌 ID 的能力。 setApprovalForAll() will grant a third party the ability to transfer all of the tokens you own for a given collection. setApprovalForAll() 将授予第三方转移您为给定集合拥有的所有令牌的能力。

When we mint the token we call setApprovalForAll() to authorize the marketplace to transfer our token.当我们铸造代币时,我们调用setApprovalForAll()来授权市场转移我们的代币。 This is the trasferFrom这是trasferFrom

function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");

        _transfer(from, to, tokenId);
    }

Before transferring it is checking if the msg.sender is already authorized for this transaction or from address is the "owner" of token.在传输之前,它会检查msg.sender是否已被授权进行此交易,或者来自地址是否是令牌的“所有者”。 To solve the issue get the owner of the tokenId .要解决此问题,请获取tokenId的所有者。 Since you are passing the "tokenId to the buyNFT`由于您将“tokenId”传递to the buyNFT`

  address owner=ERC721.ownerOf(tokenId);
  transferFrom(owner, msg.sender,tokenId);
  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM