-
-
Save littletanggg/e5bf723d2484b94cd0d1192c051fd6ed to your computer and use it in GitHub Desktop.
Simple NFT Marketplace including listing, selling and buying NFT item on the Marketplace
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
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.9; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; | |
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | |
contract MCrossMarketplace is Ownable { | |
IERC20 private token; | |
enum ListingStatus {Active, Sold, Cancelled} | |
address nftContract; | |
address creatorWallet; | |
uint256 itemCount = 0; | |
uint256 rateServiceFee = 3; | |
uint256 rateCreatorFee = 10; | |
uint256 creatorFee; | |
uint256 sellerRecieve; | |
uint256 serviceFee; | |
struct MarketItem { | |
address nftContract; | |
uint256 tokenId; | |
address owner; | |
uint256 price; | |
ListingStatus status; | |
} | |
uint256[] private marketitems; | |
mapping(uint256 => MarketItem) private tokenIdMarketItems; | |
event List( | |
address nftContract, | |
uint256 tokenId, | |
address owner, | |
uint256 price, | |
ListingStatus status | |
); | |
event Sale( | |
address nftContract, | |
uint256 tokenId, | |
address owner, | |
address buyer, | |
uint256 price, | |
ListingStatus status | |
); | |
event Cancel( | |
uint256 tokenId, | |
address owner | |
); | |
constructor( | |
address _nftContract, | |
address _creatorWallet, | |
address _tokenContract | |
){ | |
nftContract = _nftContract; | |
creatorWallet = _creatorWallet; | |
token = IERC20(_tokenContract); | |
} | |
function listItems(uint _tokenId, uint256 price) external { | |
require(price > 0, "price must be at least 1 wei"); | |
require(_tokenId > 0, "token id must greater than 0"); | |
MarketItem memory item = tokenIdMarketItems[_tokenId]; | |
if(item.tokenId == _tokenId || item.status == ListingStatus.Sold){ | |
tokenIdMarketItems[_tokenId].price = price; | |
tokenIdMarketItems[_tokenId].owner = msg.sender; | |
tokenIdMarketItems[_tokenId].status = ListingStatus.Active; | |
} else { | |
item = MarketItem( | |
nftContract, | |
_tokenId, | |
msg.sender, | |
price, | |
ListingStatus.Active | |
); | |
marketitems.push(_tokenId); | |
tokenIdMarketItems[_tokenId] = item; | |
itemCount++; | |
} | |
IERC721(nftContract).transferFrom(item.owner, address(this), item.tokenId); | |
emit List(item.nftContract, _tokenId, msg.sender, price, item.status); | |
} | |
function getAllMarketItems() external view returns(MarketItem[] memory){ | |
MarketItem[] memory items = new MarketItem[](itemCount); | |
for(uint256 i = 0; i < marketitems.length; i++) { | |
uint256 _tokenId = marketitems[i]; | |
items[i] = tokenIdMarketItems[_tokenId]; | |
} | |
return items; | |
} | |
function getMyMarketplace(address _owner) external view returns(MarketItem[] memory) { | |
MarketItem[] memory items = new MarketItem[](itemCount); | |
for(uint i = 0; i < marketitems.length; i++) { | |
uint256 _tokenId = marketitems[i]; | |
if( | |
tokenIdMarketItems[_tokenId].owner == _owner && | |
tokenIdMarketItems[_tokenId].status == ListingStatus.Active | |
){ | |
items[i] = tokenIdMarketItems[_tokenId]; | |
} | |
} | |
return items; | |
} | |
function cancelListItem(uint _tokenId) external { | |
require(tokenIdMarketItems[_tokenId].tokenId > 0, "item not exists"); | |
MarketItem storage item = tokenIdMarketItems[_tokenId]; | |
require(item.status == ListingStatus.Active, "item must be active"); | |
require(msg.sender == item.owner, "cancel not allow"); | |
tokenIdMarketItems[_tokenId].status = ListingStatus.Cancelled; | |
IERC721(item.nftContract).transferFrom(address(this), item.owner, item.tokenId); | |
emit Cancel (_tokenId, item.owner); | |
} | |
function calculateItemFee(uint256 price) public view returns(uint256, uint256) { | |
uint _serviceFee = price * rateServiceFee / 100; | |
uint _creatorFee = (price - _serviceFee) * rateCreatorFee / 100; | |
uint _sellerRecieve = price - _serviceFee - _creatorFee; | |
return (_creatorFee, _sellerRecieve); | |
} | |
function buyMarketItem(uint _tokenId) external payable { | |
require(tokenIdMarketItems[_tokenId].tokenId > 0, "item not exists"); | |
MarketItem storage item = tokenIdMarketItems[_tokenId]; | |
require(msg.sender != item.owner, "buy own item not allow"); | |
require(item.status == ListingStatus.Active, "item status is not active"); | |
require(item.price <= token.balanceOf(msg.sender), "balance is low"); | |
IERC721(nftContract).safeTransferFrom(address(this), msg.sender, item.tokenId); | |
(creatorFee, sellerRecieve) = calculateItemFee(item.price); | |
token.transferFrom(msg.sender, creatorWallet, creatorFee); | |
token.transferFrom(msg.sender, item.owner, sellerRecieve); | |
emit Sale( | |
item.nftContract, | |
item.tokenId, | |
item.owner, | |
msg.sender, | |
item.price, | |
item.status | |
); | |
tokenIdMarketItems[_tokenId].status = ListingStatus.Sold; | |
tokenIdMarketItems[_tokenId].owner = msg.sender; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment