制定NFT合同并接收外部交易
我正在开发用于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)
这是因为交易的发件人不是合同的所有者,我明白了这一点,但是您如何接受付款和转让令牌? 如果从合同所有者可以调用
?
I'm developing simple app for nft contracts.
Got stucked at receving external transactions.
Contract:
// 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];
}
}
Compiling and minting to a local hardhat node(working fine) and then trying to send transaction from another wallet.
Receiving error:
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)
It's happenging because the sender of transaction is not an owner of a contract, I understand that, but how you can accept payments and transfere token then?
If transferFrom
can be called only by the owner of the contract?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
ERC721上有两种方法可以实现这一目标。
您可以使用
批准
方法;批准另一个地址传输给定令牌ID零地址表示没有批准的地址。在给定时间,每个令牌只能有一个批准的地址。只能由令牌所有者或批准的运营商来调用。
...或者您可以使用
setAppRovalForall
方法;这将设定或安排给定操作员的批准,允许操作员代表其转移所有发件人的代币。
您可以在此处查看详细信息: openzeppelin
There are two methods on ERC721 to achieve this.
You can use
approve
method;that approves another address to transfer the given token ID The zero address indicates there is no approved address. There can only be one approved address per token at a given time. Can only be called by the token owner or an approved operator.
... or you can use
setApprovalForAll
method;that sets or unsets the approval of a given operator An operator is allowed to transfer all tokens of the sender on their behalf.
You can check the details in here: OpenZeppelin