簡體   English   中英

開發NFT合約並接收外部交易

[英]Developing NFT contract and receiveing external transactions

我正在為 nft 合同開發簡單的應用程序。

卡在接收外部交易中。

合同:

// 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];
    }
 
}

編譯並鑄造到本地安全帽節點(工作正常),然后嘗試從另一個錢包發送交易。 接收錯誤:

      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只能由合約所有者調用?

ERC721 上有兩種方法可以實現這一點。

您可以使用approve方法;

approve(address to, uint256 tokenId)

批准另一個地址轉移給定的代幣 ID 零地址表示沒有批准的地址。 在給定時間,每個令牌只能有一個批准的地址。 只能由代幣所有者或經批准的運營商調用。

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

setApprovalForAll(address to, bool approved)

設置或取消給定操作員的批准允許操作員代表他們轉移發件人的所有令牌。

您可以在此處查看詳細信息: OpenZeppelin

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM