这个教程将讲解如何用 Solidity 来搭建 NFT 交易所的“后端”,如何开发承载交易所业务逻辑的智能合约。在代码中,我们会创建一个NftMarketplace.sol
智能合约和一个兼容 ERC-721(NFT) 标准的代币合约,然后将这个 NFT 展示在我们的交易所上。
这个交易所将会有以下的基础功能:
- 上架 NFT
- 更新和下架 NFT
- 购买 NFT
- 获取所有的上架 NFT 的信息
- 获取卖家的当前状态
以上功能都会通过交易所智能合约实现。你可以先思考一下上述的功能是什么意思,因为这些功能的代码逻辑,就是它们业务逻辑的实现。比如说,在交易所中上架一个 NFT 的时需要什么数据?需要 Token ID。因为这个交易所可以上架很多不相关的 NFT,同时也需要能够给每一个 token 加上价格。
在项目目录下,创建 contracts
文件夹。在文件夹中,然后创建 NftMarketplace.sol
文件(文件路径应该是 ../<< root >>/contracts/NftMarketplace.sol
)。
在 NftMarketplace
这个智能合约中,需要完成之前提到的不同的操作。这些方法如下所示:
function listItem(
address nftAddress,
uint256 tokenId,
uint256 price
) {}
function cancelListing(address nftAddress, uint256 tokenId){}
function buyItem(address nftAddress, uint256 tokenId){}
function updateListing(
address nftAddress,
uint256 tokenId,
uint256 newPrice
){}
function withdrawProceeds(){} // method caller should be withdrawer
function getListing(address nftAddress, uint256 tokenId){}
在实现这个交易所的逻辑时,我们需要使用下列的属性和数据架构:
- 1 个结构体:
Listing
用来存储价格和卖房资产变量 - 3 个事件:
ItemListed
,ItemCanceled
和ItemBought
。 - 2 个 mapping:
s_listings
和s_proceeds
,它们存储在区块链上的状态变量。 - 3 个函数修饰器。
让我们先声明智能合约。
代码语言:javascript复制// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract NftMarketplace is ReentrancyGuard {
// TODO…
}
实现 listItem()
让我们从 listItem()
函数开始,我们需要把它定义为一个 external
函数,因为它会被外部合约或者终端用户调用(比如说从网页前端)。我们需要 listItem()
做下面的操作:
function listItem(
address nftAddress,
uint256 tokenId,
uint256 price
)
external
notListed(nftAddress, tokenId, msg.sender)
isOwner(nftAddress, tokenId, msg.sender)
{
if (price <= 0) {
revert PriceMustBeAboveZero();
}
IERC721 nft = IERC721(nftAddress);
if (nft.getApproved(tokenId) != address(this)) {
revert NotApprovedForMarketplace();
}
s_listings[nftAddress][tokenId] = Listing(price, msg.sender);
emit ItemListed(msg.sender, nftAddress, tokenId, price);
}