首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >制定NFT合同并接收外部事务

制定NFT合同并接收外部事务
EN

Stack Overflow用户
提问于 2022-04-14 09:52:20
回答 1查看 88关注 0票数 0

我正在为nft合同开发简单的应用程序。

在进行外部交易时被塞住了。

合同:

代码语言:javascript
复制
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
//import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract RonteNft is ERC721, ERC721URIStorage, ERC721Burnable, Ownable {
    // IERC721Receiver //IERC721Enumerable
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIdCounter;
    Counters.Counter private _soldTokenIdCounter;

    uint256 public constant BASE_PRICE = 0.001 ether;

    struct TokenList {
        uint256 tokenId;
        string tokenUri;
        address tokenOwner;
        bool sold;
    }

    TokenList[] public tokenList;
    //mapping(bool => TokenList) existingTokenList;

    address[] public addressList;
    mapping(address => bool) public WhiteList;

    constructor() ERC721("RonteNft", "RtNFT") {
        WhiteList[0x9ACdCfb9385810E0270afB5bFA5000d6Be0891ea] = true;
        WhiteList[0x2A5e5cc1dA717B1F076Ce04E0c7A814320C0Dc6A] = true;
        WhiteList[0xEdc64A63ae9dc338052CdF92fA4c80154e4559AE] = true;
        WhiteList[0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266] = true;
        WhiteList[0x70997970C51812dc3A010C7d01b50e0d17dc79C8] = true;
    }

    function totalSupply() external view returns (uint256){
        return _soldTokenIdCounter.current();
    }

    function safeMint(address to, string memory nftTokenURI) public onlyOwner {
        _safeMint(to, _tokenIdCounter.current());
        _setTokenURI(_tokenIdCounter.current(), nftTokenURI);
        tokenList.push(
            TokenList(_tokenIdCounter.current(), nftTokenURI, to, false)
        );

        _tokenIdCounter.increment();
    }

    // The following functions are overrides required by Solidity.
    function _burn(uint256 tokenId)
    internal
    override(ERC721, ERC721URIStorage)
    {
        super._burn(tokenId);
    }

    function tokenURI(uint256 tokenId)
    public
    view
    override(ERC721, ERC721URIStorage)
    returns (string memory)
    {
        return super.tokenURI(tokenId);
    }

    function currentCounter() public view returns (uint256) {
        return _tokenIdCounter.current();
    }

    function freeMint(address to, string memory nftTokenURI) public {
        _safeMint(to, _tokenIdCounter.current());
        _setTokenURI(_tokenIdCounter.current(), nftTokenURI);
        tokenList.push(
            TokenList(_tokenIdCounter.current(), nftTokenURI, to, false)
        );

        _tokenIdCounter.increment();
    }

    function getTokenList() public view returns (TokenList[] memory) {
        return tokenList;
    }

    function sellToken(address buyer) public {
        //require(msg.value == BASE_PRICE, "Incoming amount is wrong!");
        require(WhiteList[buyer] == true, "You are not in a white list!");

        uint256 tokenId = tokenList[_soldTokenIdCounter.current()].tokenId;
        transferFrom(owner(), buyer, tokenId);
        _soldTokenIdCounter.increment();
        tokenList[_soldTokenIdCounter.current()].sold = true;
    }

    function getError() public {
        require(1 == 2, "TEST ERROR");
    }

    function deposit() public payable {
        require(1 == 2, "DEPOSIT ERROR");
    }

    receive() external payable {
        require(msg.value == BASE_PRICE, "Incoming amount is wrong!");
        require(WhiteList[msg.sender] == true, "You are not in a white list!");

        uint256 tokenId = tokenList[_soldTokenIdCounter.current()].tokenId;
        approve(msg.sender,tokenId);
        transferFrom(owner(), msg.sender, tokenId);
        _soldTokenIdCounter.increment();
        tokenList[_soldTokenIdCounter.current()].sold = true;
    }

    function checkWhiteList(address _wallet) public returns (bool) {
        return WhiteList[_wallet];
    }
 
}

编译和造币到本地的草帽节点(工作正常),然后尝试从另一个钱包发送事务。接收错误:

代码语言:javascript
复制
      eth_sendRawTransaction
  Contract call:       RonteNft#<unrecognized-selector>
  Transaction:         0x5406175da512d812761b0e557ae67240987834294d51f39aa13371ff64453e57
  From:                0x70997970c51812dc3a010c7d01b50e0d17dc79c8
  To:                  0x5fbdb2315678afecb367f032d93f642f64180aa3
  Value:               0.001 ETH
  Gas used:            34976 of 91000
  Block #6:            0x12bef472185ef527d650454bb88dd69ad540cc2b5a6dbf3e33c5f928b3472867

  Error: VM Exception while processing transaction: reverted with reason string 'ERC721: approve caller is not owner nor approved for all'
      at RonteNft.approve (@openzeppelin/contracts/token/ERC721/ERC721.sol:116)
      at RonteNft.<receive> (contracts/RonteNft.sol:112)

发生这种情况是因为交易的发件人不是合同的所有者,我理解,但是你如何才能接受付款和转让令牌呢?如果只有合同的所有者才能调用transferFrom ,那么?

EN

回答 1

Stack Overflow用户

发布于 2022-05-23 13:51:59

在ERC721上有两种方法可以实现这一点。

您可以使用approve方法;

代码语言:javascript
复制
approve(address to, uint256 tokenId)

它批准另一个地址来传输给定的令牌ID --零地址表示没有被批准的地址。在给定的时间内,每个令牌只能有一个已批准的地址。只能由令牌所有者或已批准的运算符调用。

..。或者您可以使用setApprovalForAll方法;

代码语言:javascript
复制
setApprovalForAll(address to, bool approved)

它设置或取消对给定运算符的批准,允许运算符代表它们传输发送方的所有令牌。

您可以在这里查看详细信息:OpenZeppelin

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71869681

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档