forked from AmazingAng/WTF-Solidity
-
Notifications
You must be signed in to change notification settings - Fork 126
/
Copy pathNFTSwap.sol
124 lines (99 loc) · 3.52 KB
/
NFTSwap.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
import "../../../34_ERC721/IERC721.sol";
import "../../../34_ERC721/IERC721Receiver.sol";
import "../../../34_ERC721/WTFApe.sol";
contract NFTSwap is IERC721Receiver {
event List(
address indexed seller,
address indexed nftAddr,
uint256 indexed tokenId,
uint256 price
);
event Purchase(
address indexed buyer,
address indexed nftAddr,
uint256 indexed tokenId,
uint256 price
);
event Revoke(
address indexed seller,
address indexed nftAddr,
uint256 indexed tokenId
);
event Update(
address indexed seller,
address indexed nftAddr,
uint256 indexed tokenId,
uint256 newPrice
);
struct Order {
address owner;
uint256 price;
}
mapping(address => mapping(uint256 => Order)) public nftList;
fallback() external payable {}
function list(address _nftAddr, uint256 _tokenId, uint256 _price) public {
require(_price > 0, "Price must be greater than 0");
IERC721 _nft = IERC721(_nftAddr);
require(
_nft.ownerOf(_tokenId) == msg.sender,
"Only the owner can list the NFT"
);
require(
_nft.getApproved(_tokenId) == address(this),
"Contract is not approved to transfer this NFT"
);
nftList[_nftAddr][_tokenId] = Order(msg.sender, _price);
_nft.safeTransferFrom(msg.sender, address(this), _tokenId);
emit List(msg.sender, _nftAddr, _tokenId, _price);
}
function purchase(address _nftAddr, uint256 _tokenId) public payable {
Order memory order = nftList[_nftAddr][_tokenId];
require(order.price > 0, "NFT is not listed for sale");
require(msg.value >= order.price, "Insufficient ETH to purchase NFT");
IERC721 _nft = IERC721(_nftAddr);
require(
_nft.ownerOf(_tokenId) == address(this),
"NFT is not in the contract"
);
delete nftList[_nftAddr][_tokenId];
_nft.safeTransferFrom(address(this), msg.sender, _tokenId);
payable(order.owner).transfer(order.price);
if (msg.value > order.price) {
payable(msg.sender).transfer(msg.value - order.price);
}
emit Purchase(msg.sender, _nftAddr, _tokenId, order.price);
}
function revoke(address _nftAddr, uint256 _tokenId) public {
Order memory order = nftList[_nftAddr][_tokenId];
require(order.owner == msg.sender, "You are not the owner of this NFT");
IERC721 _nft = IERC721(_nftAddr);
require(
_nft.ownerOf(_tokenId) == address(this),
"NFT is not in the contract"
);
delete nftList[_nftAddr][_tokenId];
_nft.safeTransferFrom(address(this), msg.sender, _tokenId);
emit Revoke(msg.sender, _nftAddr, _tokenId);
}
function update(
address _nftAddr,
uint256 _tokenId,
uint256 _newPrice
) public {
require(_newPrice > 0, "Price must be greater than 0");
Order storage order = nftList[_nftAddr][_tokenId];
require(order.owner == msg.sender, "You are not the owner of this NFT");
order.price = _newPrice;
emit Update(msg.sender, _nftAddr, _tokenId, _newPrice);
}
function onERC721Received(
address,
address,
uint256,
bytes calldata
) external pure override returns (bytes4) {
return IERC721Receiver.onERC721Received.selector;
}
}