-
Notifications
You must be signed in to change notification settings - Fork 353
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7f6c4a7
commit 9bd9303
Showing
49 changed files
with
160,311 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,3 @@ | ||
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID="2c01535b38b05886544b0c8c2b544d28" | ||
NEXT_PUBLIC_APP_NAME="nft collection" | ||
NEXT_PUBLIC_EVN="test" |
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,3 @@ | ||
{ | ||
"extends": "next/core-web-vitals" | ||
} |
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,51 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
.yarn/install-state.gz | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts | ||
|
||
node_modules | ||
.env | ||
|
||
# Hardhat files | ||
/cache | ||
/artifacts | ||
|
||
# TypeChain files | ||
/typechain | ||
/typechain-types | ||
|
||
# solidity-coverage files | ||
/coverage | ||
/coverage.json |
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,52 @@ | ||
## task3 介绍 | ||
|
||
1. 部署在 Sepolia 测试网上 | ||
![bind-wallet](./readme/deploy.png "deploy") | ||
2. 提交全部合约文件(ERC20、ERC721、NFTMarket) | ||
在 contract 文件夹中,其他文件用来测试的,忽略掉 | ||
3. 提交上架 NFT、购买 NFT 的交易哈希 | ||
提交上架 NFT: 0x754e73598b6b0059510532a5b53dd6068dcd81ac3a7cdf9d2ed5d06b1662562d | ||
购买 NFT: 0xf937159ae007f8de3cd163752d66b33a8ad8897926f8e619c9b436c689d864e0 | ||
|
||
## 环境搭建: | ||
|
||
- Hardhat | ||
- react | ||
|
||
## 钱包与合约访问 | ||
|
||
- wagmi | ||
- metamask | ||
- Ethersjs | ||
|
||
--- | ||
|
||
- 编译合约: | ||
`npx hardhat compile` | ||
- 开启本地网络: | ||
`npx hardhat node` | ||
- 在本地网络上测试合约: | ||
`npx hardhat test --network localhost` | ||
- 在本地网络上部署合约: | ||
`npx hardhat ignition deploy ./ignition/modules/ERC20Token.ts --network localhost` | ||
|
||
--- | ||
|
||
开启前端服务: | ||
`npx run dev` | ||
|
||
## 合约 | ||
|
||
# Sample Hardhat Project | ||
|
||
This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a Hardhat Ignition module that deploys that contract. | ||
|
||
Try running some of the following tasks: | ||
|
||
```shell | ||
npx hardhat help | ||
npx hardhat test | ||
REPORT_GAS=true npx hardhat test | ||
npx hardhat node | ||
npx hardhat ignition deploy ./ignition/modules/NFTMarket.ts | ||
``` |
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,67 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
pragma solidity >=0.8.2 <0.9.0; | ||
|
||
contract ERC20Token { | ||
string public name; | ||
string public symbol; | ||
uint256 public totalSupply; | ||
mapping(address => uint256) public balanceOf; | ||
mapping(address => mapping(address => uint256)) public allowance; | ||
|
||
event Transfer(address indexed from, address indexed to, uint256 value); | ||
event Approval( | ||
address indexed owner, | ||
address indexed spender, | ||
uint256 value | ||
); | ||
|
||
constructor( | ||
string memory _name, | ||
string memory _symbol, | ||
uint256 _totalSupply | ||
) { | ||
name = _name; | ||
symbol = _symbol; | ||
totalSupply = _totalSupply; | ||
balanceOf[msg.sender] = _totalSupply; | ||
} | ||
|
||
function transfer( | ||
address _to, | ||
uint256 _value | ||
) external returns (bool success) { | ||
require(balanceOf[msg.sender] >= _value, "Insufficient balance"); | ||
balanceOf[msg.sender] -= _value; | ||
balanceOf[_to] += _value; | ||
emit Transfer(msg.sender, _to, _value); | ||
return true; | ||
} | ||
|
||
function approval( | ||
address _spender, | ||
uint256 _value | ||
) external returns (bool success) { | ||
allowance[msg.sender][_spender] = _value; | ||
emit Approval(msg.sender, _spender, _value); | ||
return true; | ||
} | ||
|
||
function transferFrom( | ||
address _from, | ||
address _to, | ||
uint256 _value | ||
) external returns (bool success) { | ||
require(_value <= balanceOf[_from], "Insufficient balance"); | ||
require(_value <= allowance[_from][msg.sender], "Allowance exceeded"); | ||
balanceOf[_from] -= _value; | ||
balanceOf[_to] += _value; | ||
allowance[_from][msg.sender] -= _value; | ||
emit Transfer(_from, _to, _value); | ||
return true; | ||
} | ||
} | ||
|
||
// 0x2AF374aA4DE0559be70b254a49F1A8B7edc23689 | ||
|
||
// localhost: 0x5FbDB2315678afecb367f032d93F642f64180aa3 |
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,73 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.8.2 <0.9.0; | ||
|
||
contract ERC721Token { | ||
string public name; | ||
string public symbol; | ||
uint256 public totalSupply; | ||
|
||
mapping(uint256 => address) public ownerOf; | ||
mapping(address => uint256[]) public ownedTokens; | ||
mapping(uint256 => address) public approved; | ||
mapping(address => mapping(address => bool)) public operatorApprovals; | ||
|
||
event Transfer(address indexed from, address indexed to, uint256 tokenId); | ||
event Approval( | ||
address indexed owner, | ||
address indexed approved, | ||
uint256 tokenId | ||
); | ||
|
||
constructor(string memory _name, string memory _symbol) { | ||
name = _name; | ||
symbol = _symbol; | ||
} | ||
|
||
function mint(address _to, uint256 _tokenId) external { | ||
require(ownerOf[_tokenId] == address(0), "Token already exists"); | ||
ownerOf[_tokenId] = _to; | ||
ownedTokens[_to].push(_tokenId); | ||
totalSupply++; | ||
emit Transfer(address(0), _to, _tokenId); | ||
} | ||
|
||
function approve(address _to, uint256 _tokenId) external { | ||
require(msg.sender == ownerOf[_tokenId], "Not token owner"); | ||
approved[_tokenId] = _to; | ||
emit Approval(msg.sender, _to, _tokenId); | ||
} | ||
|
||
function transferFrom( | ||
address _from, | ||
address _to, | ||
uint256 _tokenId | ||
) external { | ||
require(ownerOf[_tokenId] == _from, "Not token owner"); | ||
require( | ||
msg.sender == _from || | ||
msg.sender == approved[_tokenId] || | ||
operatorApprovals[_from][msg.sender], | ||
"Not approved" | ||
); | ||
ownerOf[_tokenId] = _to; | ||
// Update owner's token list | ||
uint256[] storage fromTokens = ownedTokens[_from]; | ||
for (uint256 i = 0; i < fromTokens.length; i++) { | ||
if (fromTokens[i] == _tokenId) { | ||
fromTokens[i] = fromTokens[fromTokens.length - 1]; | ||
fromTokens.pop(); | ||
break; | ||
} | ||
} | ||
ownedTokens[_to].push(_tokenId); | ||
|
||
emit Transfer(_from, _to, _tokenId); | ||
} | ||
|
||
function setApprovalForAll(address _operator, bool _approved) external { | ||
operatorApprovals[msg.sender][_operator] = _approved; | ||
} | ||
} | ||
|
||
// 0x6F817c5d3ccd451fd38B4cB77E78d85FD1F0810d | ||
// localhost: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 |
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,113 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
pragma solidity >=0.8.2 <0.9.0; | ||
|
||
import "./ERC20Token.sol"; | ||
import "./ERC721Token.sol"; | ||
|
||
contract NFTMarket { | ||
ERC20Token public tokenContract; | ||
ERC721Token public nftContract; | ||
|
||
struct Listing { | ||
address seller; // 上架者地址 | ||
address nftContract; // NFT 合约地址 | ||
uint256 tokenId; // NFT的Token ID | ||
uint256 price; // 上架价格(使用ERC20代币) | ||
bool active; // 上架状态 | ||
} | ||
|
||
// 存储所有上架的NFT信息 | ||
Listing[] public listings; | ||
|
||
// 上架NFT事件 | ||
event NFTListed( | ||
uint256 indexed listingId, | ||
address indexed seller, | ||
address indexed nftContract, | ||
uint256 tokenId, | ||
uint256 price | ||
); | ||
// 购买NFT事件 | ||
event NFTSold( | ||
uint256 indexed listingId, | ||
address indexed buyer, | ||
address indexed seller, | ||
address nftContract, | ||
uint256 tokenId, | ||
uint256 price | ||
); | ||
|
||
// 合约构造函数,初始化ERC20代币合约和ERC721 NFT合约地址 | ||
constructor(address _tokenContractAddress, address _nftContractAddress) { | ||
tokenContract = ERC20Token(_tokenContractAddress); | ||
nftContract = ERC721Token(_nftContractAddress); | ||
} | ||
function getTokenContract() external view returns (ERC20Token) { | ||
return tokenContract; | ||
} | ||
|
||
function getNftContract() external view returns (ERC721Token) { | ||
return nftContract; | ||
} | ||
|
||
// 上架NFT | ||
function listNFT( | ||
address _nftContract, | ||
uint256 _tokenId, | ||
uint256 _price | ||
) external { | ||
// 确保上架者是NFT的所有者 | ||
require(nftContract.ownerOf(_tokenId) == msg.sender, "Not token owner"); | ||
// 确保上架价格大于零 | ||
require(_price > 0, "Price must be greater than zero"); | ||
|
||
// 将NFT信息添加到上架列表中 | ||
listings.push( | ||
Listing(msg.sender, _nftContract, _tokenId, _price, true) | ||
); | ||
|
||
// 触发上架NFT事件 | ||
emit NFTListed( | ||
listings.length - 1, | ||
msg.sender, | ||
_nftContract, | ||
_tokenId, | ||
_price | ||
); | ||
} | ||
|
||
// 购买NFT | ||
function buyNFT(uint256 _listingId) external { | ||
// 获取上架信息 | ||
Listing storage listing = listings[_listingId]; | ||
// 确保上架状态为激活 | ||
require(listing.active, "Listing not active"); | ||
|
||
// 确保买家拥有足够的ERC20代币用于购买 | ||
require( | ||
tokenContract.balanceOf(msg.sender) >= listing.price, | ||
"Insufficient balance" | ||
); | ||
|
||
// 从买家转移ERC20代币给卖家 | ||
tokenContract.transferFrom(msg.sender, listing.seller, listing.price); | ||
// 从卖家转移NFT给买家 | ||
nftContract.transferFrom(listing.seller, msg.sender, listing.tokenId); | ||
|
||
// 更新上架状态为非激活 | ||
listing.active = false; | ||
// 触发购买NFT事件 | ||
emit NFTSold( | ||
_listingId, | ||
msg.sender, | ||
listing.seller, | ||
listing.nftContract, | ||
listing.tokenId, | ||
listing.price | ||
); | ||
} | ||
} | ||
|
||
// 0x804D1F8eDcd0dC5F87D25F2B36D0655a7CABf50A | ||
// localhost: 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0 |
Oops, something went wrong.