[英]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.