Skip to content

Instantly share code, notes, and snippets.

@KBPsystem777
Created November 17, 2024 16:49
Show Gist options
  • Save KBPsystem777/648b22fb428ac704034d5c9a9082fcf5 to your computer and use it in GitHub Desktop.
Save KBPsystem777/648b22fb428ac704034d5c9a9082fcf5 to your computer and use it in GitHub Desktop.
ManageLife's Marketplace V2 Smart Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./ManageLife.sol";
contract Marketplace is ReentrancyGuard, Pausable, Ownable {
uint256 public constant PERCENTS_DIVIDER = 10000;
uint256 public adminPercent = 200; // 2%
uint256 public adminPending;
ManageLife public mLife;
bool public allowTrading = false;
struct Offer {
uint256 tokenId;
address seller;
uint256 price;
address offeredTo;
}
struct Bid {
address bidder;
uint256 value;
address paymentToken; // Payment token address
}
mapping(uint256 => Offer) public offers;
mapping(uint256 => Bid) public bids;
mapping(address => bool) public supportedTokens; // Supported tokens mapping
event Offered(uint256 indexed tokenId, uint256 price, address indexed toAddress);
event BidEntered(uint256 indexed tokenId, uint256 value, address indexed fromAddress, address paymentToken);
event BidCancelled(uint256 indexed tokenId, uint256 value, address indexed bidder);
event Bought(uint256 indexed tokenId, uint256 value, address indexed fromAddress, address indexed toAddress, bool isInstant, address paymentToken);
event BidWithdrawn(uint256 indexed tokenId, uint256 value);
event Cancelled(uint256 indexed tokenId);
event TradingStatus(bool _isTradingAllowed);
event SupportedTokenUpdated(address token, bool status);
event Received(address, uint);
error InvalidPercent(uint256 _percent, uint256 minimumPercent);
error UnsupportedPaymentToken(address token);
constructor() {}
modifier isTradingAllowed() {
require(allowTrading, "Trading is disabled at this moment");
_;
}
function pause() external whenNotPaused onlyOwner {
_pause();
}
function unpause() external whenPaused onlyOwner {
_unpause();
}
function setTrading(bool _isTradingAllowed) external onlyOwner {
allowTrading = _isTradingAllowed;
emit TradingStatus(_isTradingAllowed);
}
function setNftContract(address nftAddress) external onlyOwner {
require(nftAddress != address(0x0), "Zero address");
mLife = ManageLife(nftAddress);
}
function setAdminPercent(uint256 _percent) external onlyOwner {
if (_percent < 500) {
revert InvalidPercent({_percent: _percent, minimumPercent: 500});
}
adminPercent = _percent;
}
function withdraw() external onlyOwner nonReentrant {
uint256 amount = adminPending;
adminPending = 0;
_safeTransferETH(owner(), amount);
}
function updateSupportedToken(address token, bool status) external onlyOwner {
supportedTokens[token] = status;
emit SupportedTokenUpdated(token, status);
}
function offerForSale(uint256 tokenId, uint256 minSalePrice) external whenNotPaused isTradingAllowed {
require(msg.sender == mLife.ownerOf(tokenId), "You do not own this MLRE");
offers[tokenId] = Offer(tokenId, msg.sender, minSalePrice, address(0x0));
emit Offered(tokenId, minSalePrice, address(0x0));
}
function offerForSaleToAddress(
uint256 tokenId,
uint256 minSalePrice,
address toAddress
) external whenNotPaused isTradingAllowed {
require(msg.sender == mLife.ownerOf(tokenId), "You do not own this MLRE");
offers[tokenId] = Offer(tokenId, msg.sender, minSalePrice, toAddress);
emit Offered(tokenId, minSalePrice, toAddress);
}
function buy(uint256 tokenId, address paymentToken) external payable whenNotPaused isTradingAllowed {
Offer memory offer = offers[tokenId];
require(offer.offeredTo == address(0x0) || offer.offeredTo == msg.sender, "This offer is not for you");
uint256 amount = offer.price;
require(amount > 0, "Invalid offer price");
if (paymentToken == address(0)) {
require(msg.value == amount, "Incorrect ETH amount");
} else {
require(supportedTokens[paymentToken], "Unsupported payment token");
IERC20(paymentToken).transferFrom(msg.sender, address(this), amount);
}
address seller = offer.seller;
require(seller != msg.sender, "Seller == msg.sender");
offers[tokenId] = Offer(tokenId, msg.sender, 0, address(0x0));
mLife.transferFrom(seller, msg.sender, tokenId);
uint256 commission = (amount * adminPercent) / PERCENTS_DIVIDER;
adminPending += commission;
if (paymentToken == address(0)) {
_safeTransferETH(seller, amount - commission);
} else {
IERC20(paymentToken).transfer(seller, amount - commission);
}
emit Bought(tokenId, amount, seller, msg.sender, true, paymentToken);
}
receive() external payable {
emit Received(msg.sender, msg.value);
}
function _safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}("");
require(success, "Transfer failed");
}
}
@KBPsystem777
Copy link
Author

Summary

image

The updated marketplace is no longer just an ETH-based platform. By integrating token payments, we've created a more versatile and inclusive ecosystem. These enhancements ensure the platform remains competitive, attracts a broader audience, and strengthens the MLIFE token's role as a key asset in the ecosystem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment