-
Notifications
You must be signed in to change notification settings - Fork 351
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 #972 from qiaopengjun5162/task3
task3: qiaopengjun5162
- Loading branch information
Showing
5 changed files
with
273 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,22 @@ | ||
// SPDX-License-Identifier: MIT | ||
// Compatible with OpenZeppelin Contracts ^5.0.0 | ||
pragma solidity ^0.8.20; | ||
|
||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; | ||
import "@openzeppelin/contracts/access/Ownable.sol"; | ||
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; | ||
|
||
contract MyToken is ERC20, ERC20Burnable, Ownable, ERC20Permit { | ||
constructor( | ||
address initialOwner | ||
) | ||
ERC20("MyERC20Token", "MTK") | ||
Ownable(initialOwner) | ||
ERC20Permit("MyERC20Token") | ||
{} | ||
|
||
function mint(address to, uint256 amount) public onlyOwner { | ||
_mint(to, amount); | ||
} | ||
} |
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,59 @@ | ||
// SPDX-License-Identifier: MIT | ||
// Compatible with OpenZeppelin Contracts ^5.0.0 | ||
pragma solidity ^0.8.20; | ||
|
||
import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; | ||
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; | ||
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol"; | ||
import "@openzeppelin/contracts/access/Ownable.sol"; | ||
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; | ||
|
||
contract MyToken is | ||
ERC721, | ||
ERC721URIStorage, | ||
ERC721Pausable, | ||
Ownable, | ||
ERC721Burnable | ||
{ | ||
uint256 private _nextTokenId; | ||
|
||
constructor( | ||
address initialOwner | ||
) ERC721("MyERC721Token", "MTKERC721") Ownable(initialOwner) {} | ||
|
||
function pause() public onlyOwner { | ||
_pause(); | ||
} | ||
|
||
function unpause() public onlyOwner { | ||
_unpause(); | ||
} | ||
|
||
function safeMint(address to, string memory uri) public onlyOwner { | ||
uint256 tokenId = _nextTokenId++; | ||
_safeMint(to, tokenId); | ||
_setTokenURI(tokenId, uri); | ||
} | ||
|
||
// The following functions are overrides required by Solidity. | ||
|
||
function _update( | ||
address to, | ||
uint256 tokenId, | ||
address auth | ||
) internal override(ERC721, ERC721Pausable) returns (address) { | ||
return super._update(to, tokenId, auth); | ||
} | ||
|
||
function tokenURI( | ||
uint256 tokenId | ||
) public view override(ERC721, ERC721URIStorage) returns (string memory) { | ||
return super.tokenURI(tokenId); | ||
} | ||
|
||
function supportsInterface( | ||
bytes4 interfaceId | ||
) public view override(ERC721, ERC721URIStorage) returns (bool) { | ||
return super.supportsInterface(interfaceId); | ||
} | ||
} |
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,82 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
import "@openzeppelin/contracts/interfaces/IERC20.sol"; | ||
import "@openzeppelin/contracts/interfaces/IERC721.sol"; | ||
import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; | ||
|
||
contract Market is ReentrancyGuard { | ||
struct Listing { | ||
address seller; | ||
address nftContract; | ||
uint256 tokenId; | ||
uint256 price; | ||
bool isActive; | ||
} | ||
|
||
IERC20 public paymentToken; | ||
mapping(address => mapping(uint256 => Listing)) public listings; | ||
|
||
event NFTListed( | ||
address indexed seller, | ||
address indexed nftContract, | ||
uint256 indexed tokenId, | ||
uint256 price | ||
); | ||
|
||
event NFTPurchased( | ||
address indexed buyer, | ||
address indexed nftContract, | ||
uint256 indexed tokenId, | ||
uint256 price | ||
); | ||
|
||
constructor(address _paymentToken) { | ||
paymentToken = IERC20(_paymentToken); | ||
} | ||
|
||
function listNFT( | ||
address _nftContract, | ||
uint256 _tokenId, | ||
uint256 _price | ||
) external { | ||
IERC721 nft = IERC721(_nftContract); | ||
require(nft.ownerOf(_tokenId) == msg.sender, "NFT not owned by you"); | ||
require( | ||
nft.isApprovedForAll(msg.sender, address(this)), | ||
"Not approved for this contract" | ||
); | ||
listings[_nftContract][_tokenId] = Listing( | ||
msg.sender, | ||
_nftContract, | ||
_tokenId, | ||
_price, | ||
true | ||
); | ||
emit NFTListed(msg.sender, _nftContract, _tokenId, _price); | ||
} | ||
|
||
function buyNFT( | ||
address _nftContract, | ||
uint256 _tokenId | ||
) external nonReentrant { | ||
Listing storage listing = listings[_nftContract][_tokenId]; | ||
require(listing.price > 0, "NFT not listed for sale"); | ||
require(listing.isActive, "NFT not active"); | ||
|
||
IERC721 nft = IERC721(_nftContract); | ||
|
||
require( | ||
paymentToken.transferFrom( | ||
msg.sender, | ||
listing.seller, | ||
listing.price | ||
), | ||
"payment failed" | ||
); | ||
nft.safeTransferFrom(listing.seller, msg.sender, _tokenId); | ||
listing.isActive = false; | ||
|
||
emit NFTPurchased(msg.sender, _nftContract, _tokenId, listing.price); | ||
} | ||
} |
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,30 @@ | ||
# Deploy addresses | ||
|
||
## ERC20 | ||
|
||
- 0x283C7CF39Eff3B09A8C92509825Eb4A58c96D1a7 | ||
- 0xd89C5C99B854470a3ea68b533441898Dee74B681 | ||
|
||
## ERC721 | ||
|
||
- 0xA09833270D095b51799c79a8071eA3C9A04d52Ea | ||
- 0x70a306D731d5249F5ce56EFe4FA1F625A521709C | ||
|
||
## Market | ||
|
||
- 0xB40AdaCeA1Bf2f1a181621C50D84e2f165cDBB0e | ||
- 0xa006cD3172Ef04D0199F4df9682E8297c133D69e | ||
|
||
## 浏览器查看 | ||
|
||
- <https://sepolia.etherscan.io/address/0x750Ea21c1e98CcED0d4557196B6f4a5974CCB6f5> | ||
- <https://sepolia.etherscan.io/tx/0x54ff55a4fac5ec5d61013cee2d020c9a794965cee0c5cab036513592ab463681> | ||
|
||
## 上架NFT | ||
|
||
- <https://sepolia.etherscan.io/tx/0xcce55d9c1c328cb91069d8c233a0b14159d066bfba3811a711631c17ad89cce7> | ||
- <https://sepolia.etherscan.io/tx/0xd616550d4ef3d7df17c1bcf3acc3b49976690bebe01a96b53a919e560c0dd119> | ||
|
||
## 购买NFT | ||
|
||
- <https://sepolia.etherscan.io/tx/0x1b5fa299b41c8312e6d6667b9988010e41d85bc0bf0b625f8a1eeba192bbe3e1> |
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,80 @@ | ||
# Solidity 学习笔记 | ||
|
||
## 实操 | ||
|
||
### 1. 安装 | ||
|
||
```zsh | ||
curl -L https://foundry.paradigm.xyz | bash | ||
% Total % Received % Xferd Average Speed Time Time Time Current | ||
Dload Upload Total Spent Left Speed | ||
100 167 100 167 0 0 143 0 0:00:01 0:00:01 --:--:-- 143 | ||
100 2189 100 2189 0 0 1271 0 0:00:01 0:00:01 --:--:-- 1271 | ||
Installing foundryup... | ||
|
||
Detected your preferred shell is zsh and added foundryup to PATH. | ||
Run 'source /Users/qiaopengjun/.zshenv' or start a new terminal session to use foundryup. | ||
Then, simply run 'foundryup' to install Foundry. | ||
|
||
fofoundryup | ||
|
||
|
||
|
||
.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx | ||
|
||
╔═╗ ╔═╗ ╦ ╦ ╔╗╔ ╔╦╗ ╦═╗ ╦ ╦ Portable and modular toolkit | ||
╠╣ ║ ║ ║ ║ ║║║ ║║ ╠╦╝ ╚╦╝ for Ethereum Application Development | ||
╚ ╚═╝ ╚═╝ ╝╚╝ ═╩╝ ╩╚═ ╩ written in Rust. | ||
|
||
.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx | ||
|
||
Repo : https://github.com/foundry-rs/ | ||
Book : https://book.getfoundry.sh/ | ||
Chat : https://t.me/foundry_rs/ | ||
Support : https://t.me/foundry_support/ | ||
Contribute : https://github.com/orgs/foundry-rs/projects/2/ | ||
|
||
.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx | ||
|
||
foundryup: installing foundry (version nightly, tag nightly) | ||
foundryup: downloading latest forge, cast, anvil, and chisel | ||
############################################################################################################## 100.0% | ||
foundryup: downloading manpages | ||
############################################################################################################## 100.0% | ||
foundryup: installed - forge 0.2.0 (d7eac74 2024-06-21T00:18:59.645698000Z) | ||
foundryup: installed - cast 0.2.0 (d7eac74 2024-06-21T00:18:59.579897000Z) | ||
foundryup: installed - anvil 0.2.0 (d7eac74 2024-06-21T00:18:59.673963000Z) | ||
foundryup: installed - chisel 0.2.0 (d7eac74 2024-06-21T00:18:59.642077000Z) | ||
foundryup: done! | ||
``` | ||
|
||
## Deployment steps | ||
|
||
1. 部署 `ERC20` 合约 | ||
2. 部署 `ERC721` 合约 | ||
3. 使用`ERC20` 合约地址作为初始化参数部署 `NFTMarket` 合约 | ||
4. 账户1 在 `ERC20` 合约上 mint token | ||
5. 账户1 在 `ERC721` 合约上 safeMint NFT | ||
6. 账户1 在 `ERC721` 合约上调用 `setApprovalForAll` 授权 `NFTMarket` 合约,参数为 `NFTMarket` 合约地址和 `true` | ||
7. 账户1 在 `NFTMarket` 合约上调用 `listNFT` 挂单(上架 tokenId 为 0 的 NFT) | ||
8. 账户1 在 `ERC20` 合约上调用 `transfer` 转移 10个 ERC20 token 给 账户2 | ||
9. 账户2 在 `ERC20` 合约上调用 `approve` 方法授权 `NFTMarket` 合约使用1个ERC20token,参数为 `NFTMarket` 合约地址 和数量 1,000,000,000,000,000,000 | ||
10. 账户2 在 `NFTMarket` 合约上调用 `buyNFT` 购买 tokenId 为 0 的 NFT | ||
11. 查看账户1 和账户2 的 ERC20 和 ERC721 余额 (`balanceOf`) | ||
|
||
## 学习目标 | ||
|
||
- 掌握 Solidity 语法 | ||
- 掌握 Solidity 合约开发 | ||
- 掌握 Solidity 合约部署 | ||
- 掌握 Solidity 合约调用 | ||
- 掌握 Solidity 合约测试 | ||
|
||
## 学习笔记 | ||
|
||
## 参考 | ||
|
||
- <https://getfoundry.sh/> | ||
- <https://book.getfoundry.sh/getting-started/first-steps> | ||
- <https://docs.soliditylang.org/en/v0.8.26/installing-solidity.html> | ||
- <https://learnblockchain.cn/docs/solidity/index.html> |