-
Notifications
You must be signed in to change notification settings - Fork 350
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #564 from Georgiafab/georgia
task3: Georgiafab
- Loading branch information
Showing
5 changed files
with
199 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.8.2 <0.9.0; | ||
|
||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
contract MTK is ERC20 { | ||
constructor(address owner) ERC20("MILKToken", "MTK") { | ||
_mint(owner, 21000000 * 10 ** 18); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.8.2 <0.9.0; | ||
|
||
import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; | ||
|
||
contract MILKNT is ERC721 { | ||
uint256 private _nextId; | ||
|
||
constructor() ERC721("MILKNFT", "MILKNT") {} | ||
|
||
function saftMint(address to) public { | ||
uint256 tokenId = _nextId++; | ||
_safeMint(to, tokenId); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
pragma solidity >=0.8.2 <0.9.0; | ||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; | ||
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; | ||
import "@openzeppelin/contracts/utils/math/Math.sol"; | ||
|
||
contract NFTMarket is ReentrancyGuard { | ||
IERC20 public tokenContract; | ||
using Math for uint256; | ||
|
||
struct Listing { | ||
uint256 tokenId; // NFT的Token ID | ||
address seller; // 上架者地址 | ||
address nftContract; // NFT 合约地址 | ||
uint256 price; // 上架价格(使用ERC20代币) | ||
bool active; // 上架状态 | ||
} | ||
|
||
// 存储所有上架的NFT信息 | ||
mapping(address => mapping(uint256 => Listing)) public listings; | ||
|
||
// 记录所有有上架NFT的合约地址 | ||
address[] private nftContracts; | ||
// 记录每个合约地址对应的tokenId数组 | ||
mapping(address => uint256[]) private nftTokenIds; | ||
|
||
// 上架NFT事件 | ||
event NFTListed( | ||
uint256 indexed tokenId, | ||
address indexed seller, | ||
address indexed nftContract, | ||
uint256 price | ||
); | ||
|
||
// 下架NFT事件 | ||
event NFTUnListed(uint256 indexed tokenId, address indexed seller); | ||
|
||
// 购买NFT事件 | ||
event NFTSold( | ||
uint256 tokenId, | ||
address indexed buyer, | ||
address indexed seller, | ||
address nftContract, | ||
uint256 price | ||
); | ||
|
||
// 合约构造函数,初始化ERC20代币合约地址 | ||
constructor(address _tokenContractAddress) { | ||
tokenContract = IERC20(_tokenContractAddress); | ||
} | ||
|
||
function getTokenContract() external view returns (IERC20) { | ||
return tokenContract; | ||
} | ||
|
||
// 上架NFT | ||
function listNFT( | ||
address _nftContract, | ||
uint256 _tokenId, | ||
uint256 _price | ||
) external { | ||
// 确保上架者是NFT的所有者 | ||
IERC721 nftContract = IERC721(_nftContract); | ||
require(nftContract.ownerOf(_tokenId) == msg.sender, "Not token owner"); | ||
// 确保上架价格大于零 | ||
require(_price > 0, "Price must be greater than zero"); | ||
|
||
// 将NFT信息添加到上架列表中 | ||
listings[_nftContract][_tokenId] = Listing( | ||
_tokenId, | ||
msg.sender, | ||
_nftContract, | ||
_price, | ||
true | ||
); | ||
|
||
// 如果该合约地址第一次上架NFT,则添加到nftContracts数组中 | ||
if (nftTokenIds[_nftContract].length == 0) { | ||
nftContracts.push(_nftContract); | ||
} | ||
|
||
// 将tokenId添加到该合约地址对应的tokenId数组中 | ||
nftTokenIds[_nftContract].push(_tokenId); | ||
|
||
// 触发上架NFT事件 | ||
emit NFTListed(_tokenId, msg.sender, _nftContract, _price); | ||
} | ||
|
||
// 下架NFT | ||
function unListNFT(address _nftContract, uint256 _tokenId) external { | ||
// 获取上架信息 | ||
Listing storage listing = listings[_nftContract][_tokenId]; | ||
// 确保上架状态为激活 | ||
require(listing.active, "Listing not active"); | ||
// 确保下架人是拥有者 | ||
require(listing.seller == msg.sender, "Not token owner"); | ||
|
||
// 修改上架状态为非激活 | ||
listing.active = false; | ||
|
||
emit NFTUnListed(_tokenId, msg.sender); | ||
} | ||
|
||
// 购买NFT | ||
function buyNFT( | ||
address _nftContract, | ||
uint256 _tokenId | ||
) external nonReentrant { | ||
Listing storage listing = listings[_nftContract][_tokenId]; | ||
require(listing.active, "Listing not active"); | ||
|
||
IERC721 nft = IERC721(_nftContract); | ||
// 确保买家拥有足够的ERC20代币用于购买 | ||
require( | ||
tokenContract.balanceOf(msg.sender) >= listing.price, | ||
"Insufficient balance" | ||
); | ||
// 从买家转移ERC20代币给卖家 | ||
tokenContract.transferFrom(msg.sender, listing.seller, listing.price); | ||
// 从卖家转移NFT给买家 | ||
nft.transferFrom(listing.seller, msg.sender, _tokenId); | ||
|
||
// 修改上架状态为非激活 | ||
listing.active = false; | ||
|
||
emit NFTSold( | ||
_tokenId, | ||
msg.sender, | ||
listing.seller, | ||
_nftContract, | ||
listing.price | ||
); | ||
} | ||
|
||
// 获取所有上架的NFT信息 | ||
function getAllListings() external view returns (Listing[] memory) { | ||
uint256 totalListings = 0; | ||
|
||
// 计算所有上架的NFT总数 | ||
for (uint i = 0; i < nftContracts.length; i++) { | ||
address nftContract = nftContracts[i]; | ||
totalListings += nftTokenIds[nftContract].length; | ||
} | ||
|
||
// 创建一个数组来存储所有的上架信息 | ||
Listing[] memory allListings = new Listing[](totalListings); | ||
uint256 currentIndex = 0; | ||
|
||
// 填充数组 | ||
for (uint i = 0; i < nftContracts.length; i++) { | ||
address nftContract = nftContracts[i]; | ||
uint256[] storage tokenIds = nftTokenIds[nftContract]; | ||
for (uint j = 0; j < tokenIds.length; j++) { | ||
uint256 tokenId = tokenIds[j]; | ||
Listing storage listing = listings[nftContract][tokenId]; | ||
if (listing.active) { | ||
allListings[currentIndex] = listing; | ||
currentIndex++; | ||
} | ||
} | ||
} | ||
|
||
return allListings; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
## task3 介绍 | ||
|
||
1. 部署在 Sepolia 测试网上 | ||
![bind-wallet](./readme/deploy.png "deploy") | ||
2. 提交全部合约文件(ERC20、ERC721、NFTMarket) | ||
3. 提交上架 NFT、购买 NFT 的交易哈希 | ||
提交上架 NFT: 0xc940613d9297bcef090bb2252ef9e734dffb769d570b1eafc55931ca46d7f7cd | ||
购买 NFT: 0xf937159ae007f8de3cd163752d66b33a8ad8897926f8e619c9b436c689d864e0 |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.