forked from spradhip/dscryptocommerce-astradb
/
NFT.sol
135 lines (116 loc) · 4.73 KB
/
NFT.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
125
126
127
128
129
130
131
132
133
134
135
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
/// @custom:security-contact shlok.mange@outlook.com
contract NFT is ERC721, ERC721Enumerable, ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private _tokenIdCounter;
struct SaleData {
address payable seller_address;
address payable buyer_address;
uint256 price;
uint256 status;
uint256 seller_collateral;
uint256 buyer_collateral;
}
mapping(uint256 => SaleData) public saleDetails;
constructor() ERC721("MyToken", "MTK") {}
event ListedItem(uint256 time, uint256 tokenId);
event BidItem(uint256 time, uint256 tokenId);
event ShippedItem(uint256 time, uint256 tokenId);
event ReceivedItem(uint256 time, uint256 tokenId);
function safeMint(address to, string memory uri) public returns(uint256){
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(to, tokenId);
_setTokenURI(tokenId, uri);
return tokenId;
}
modifier isNotListed(uint256 tokenId){
require(saleDetails[tokenId].status == 0);
_;
}
modifier isListed(uint256 tokenId){
require(saleDetails[tokenId].status == 1);
_;
}
modifier isBid(uint256 tokenId){
require(saleDetails[tokenId].status == 2);
_;
}
modifier isShipped(uint256 tokenId){
require(saleDetails[tokenId].status == 3);
_;
}
// seller lists nft
function listNft(uint256 _price, string memory _productId) public payable returns(uint256){
require(msg.value >= ((_price / 4)),"Please lockin 25% of selling price");
uint256 tokenId = safeMint(msg.sender, _productId);
saleDetails[tokenId].seller_address = payable(msg.sender);
saleDetails[tokenId].price = _price;
saleDetails[tokenId].seller_collateral = msg.value;
saleDetails[tokenId].status = 1;
emit ListedItem(block.timestamp, tokenId);
return tokenId;
}
// buyer places bid on nft
function bidNft(uint256 tokenId) public payable isListed(tokenId){
require(msg.value >= (saleDetails[tokenId].price + saleDetails[tokenId].price / 4));
saleDetails[tokenId].buyer_address = payable(msg.sender);
saleDetails[tokenId].status = 2;
saleDetails[tokenId].buyer_collateral = msg.value;
emit BidItem(block.timestamp, tokenId);
}
// seller ships nft
function shipNft(uint tokenId) payable public isBid(tokenId){
require(saleDetails[tokenId].seller_address == msg.sender);
(bool sent, ) = saleDetails[tokenId].seller_address.call{value: saleDetails[tokenId].seller_collateral }("");
require(sent, "Failed to send Ether");
saleDetails[tokenId].seller_collateral = 0;
safeTransferFrom(msg.sender, saleDetails[tokenId].buyer_address, tokenId);
saleDetails[tokenId].status = 3;
emit ShippedItem(block.timestamp, tokenId);
}
// buyer receives nft
function receiveNft(uint tokenId) payable public isShipped(tokenId){
require(saleDetails[tokenId].buyer_address == msg.sender);
uint256 buyer_collateral = (saleDetails[tokenId].price / 4);
uint256 sell_price = saleDetails[tokenId].buyer_collateral - buyer_collateral;
(bool sent, ) = saleDetails[tokenId].seller_address.call{value: sell_price}("");
require(sent, "Failed to send Ether");
(bool sentBuyer, ) = msg.sender.call{value: buyer_collateral}("");
require(sentBuyer, "Failed to send Ether");
saleDetails[tokenId].buyer_collateral = 0;
saleDetails[tokenId].status = 4;
emit ReceivedItem(block.timestamp, tokenId);
}
// The following functions are overrides required by Solidity.
function _beforeTokenTransfer(address from, address to, uint256 tokenId)
internal
override(ERC721, ERC721Enumerable)
{
super._beforeTokenTransfer(from, to, tokenId);
}
function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}