Skip to content

Instantly share code, notes, and snippets.

@littletanggg
Last active June 14, 2022 04:03
Show Gist options
  • Save littletanggg/e5bf723d2484b94cd0d1192c051fd6ed to your computer and use it in GitHub Desktop.
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
// 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