我正在为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 ,那么?
发布于 2022-05-23 13:51:59
在ERC721上有两种方法可以实现这一点。
您可以使用approve方法;
approve(address to, uint256 tokenId)它批准另一个地址来传输给定的令牌ID --零地址表示没有被批准的地址。在给定的时间内,每个令牌只能有一个已批准的地址。只能由令牌所有者或已批准的运算符调用。
..。或者您可以使用setApprovalForAll方法;
setApprovalForAll(address to, bool approved)它设置或取消对给定运算符的批准,允许运算符代表它们传输发送方的所有令牌。
您可以在这里查看详细信息:OpenZeppelin
https://stackoverflow.com/questions/71869681
复制相似问题