最近又学习了ERC721相关的接口和合约,写一个能够简单交易NFT的交易所进行锻炼。
- 主要知识点包括:
1、ERC721合约和接口
2、ERCReceiver的接口主要用途
3、使用Openzeppelin合约库
4、Remix在线编码平台使用
目前总觉得给合约,函数,变量起名字很累,当然也包括注释和说明内容,英文表述还是困难。
- 合约代码:
看下写的NFT交易所的代码吧。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
contract NFTSwap is ERC721,IERC721Receiver {
struct NftOrder {
address owner;
uint256 price;
}
mapping(address => mapping(uint256 => NftOrder)) public nftMarket ;
event SellNft(address indexed nft, address indexed owner, uint256 id, uint256 price );
event RevokeNft(address indexed nft, address indexed owner, uint256 id);
event UpdateNft(address indexed nft, address indexed owner, uint256 id, uint256 newprice);
event BuyNft(address indexed nft, address buyer, address indexed owner, uint256 price);
constructor () ERC721("NFTSWAP", "NFTSWAP"){}
receive() payable external {
}
function sellNft (address nft, uint256 id, uint256 price) public {
require (nft != address(0), "nft address is 0");
require (price > 0 , "price can not 0");
require (IERC721(nft).getApproved(id) == address(this), "not approved");
NftOrder storage no = nftMarket[nft][id];
no.owner = msg.sender;
no.price = price;
IERC721(nft).safeTransferFrom(msg.sender, address(this), id);
emit SellNft(nft, msg.sender, id, price);
}
function revokeNft(address nft, uint256 id) public {
require (nft != address(0), "nft address is 0");
NftOrder memory no = nftMarket[nft][id];
require (no.owner == msg.sender, "not nft owner");
IERC721(nft).safeTransferFrom(address(this), no.owner, id);
delete nftMarket[nft][id];
emit RevokeNft(nft, msg.sender, id);
}
function updateNft(address nft, uint256 id, uint256 newprice) public {
require (nft != address(0), "nft address is 0");
NftOrder storage no = nftMarket[nft][id];
require (no.owner == msg.sender, "not nft owner");
no.price = newprice;
emit UpdateNft(nft, msg.sender, id, newprice);
}
function buyNft(address nft, uint256 id) public payable {
require (nft != address(0), "nft address is 0");
NftOrder storage no = nftMarket[nft][id];
require (msg.value >= no.price, "not enough eth");
require (no.owner != msg.sender, "nft owner cannot buy");
payable(no.owner).transfer(no.price);
IERC721(nft).safeTransferFrom(address(this), msg.sender, id);
emit BuyNft(nft, msg.sender, no.owner, no.price);
delete nftMarket[nft][id];
}
// 实现{IERC721Receiver}的onERC721Received,能够接收ERC721代币
function onERC721Received(
address operator,
address from,
uint tokenId,
bytes calldata data
) external pure override returns (bytes4){
return IERC721Receiver.onERC721Received.selector;
}
}
- 主要事件:
event SellNft(address indexed nft, address indexed owner, uint256 id, uint256 price );
event RevokeNft(address indexed nft, address indexed owner, uint256 id);
event UpdateNft(address indexed nft, address indexed owner, uint256 id, uint256 newprice);
event BuyNft(address indexed nft, address buyer, address indexed owner, uint256 price);
- 主要函数:
function sellNft (address nft, uint256 id, uint256 price) public;
function revokeNft(address nft, uint256 id) public;
function updateNft(address nft, uint256 id, uint256 newprice) public;
function buyNft(address nft, uint256 id) public payable;
function onERC721Received(
address operator,
address from,
uint tokenId,
bytes calldata data
) external pure override returns (bytes4);
- Remix实践截图(需要提前部署一个NFT721合约)