Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
6.3 kB
2
Indexable
Never
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Strings.sol";

import "./NFTContract.sol";

contract marketPlace is ReentrancyGuard, Ownable {
    using Counters for Counters.Counter;

    Counters.Counter public _itemTracker;
    Counters.Counter public _soldItems;

    address payable companyAddress;

    NFTContract NFTContractInstance;

    event NFTItemListed(
        uint256 itemId,
        address indexed nft,
        uint256 tokenId,
        uint256 price,
        address indexed seller
    );

    event Bought(
        uint256 itemId,
        address indexed nft,
        uint256 tokenId,
        uint256 price,
        address indexed seller,
        address indexed buyer
    );

    struct NFTItem {
        uint256 itemId;
        IERC721 nft;
        uint256 tokenId;
        uint256 price;
        bool sold;
        address payable _companyAddress;
        address payable seller;
        address payable owner;
        address payable lastOwner;
    }
    mapping(uint256 => NFTItem) public _NFTItem;
    mapping(uint256 => address[]) public NFTItemOwners;

    function setNFTContractInstance(address _NFTContractInstance)
        external
        onlyOwner
        returns (bool)
    {
        NFTContractInstance = NFTContract(_NFTContractInstance);
        return true;
    }

    function setCompanyAddress(address _companyAddress)
        external
        onlyOwner
        returns (bool)
    {
        companyAddress = payable(_companyAddress);
        return true;
    }

    //////////////////////////////////////////////////////////////////////////////////////// NFT SECTION
    function listNFTItem(
        IERC721 _nft,
        uint256 _tokenId,
        uint256 _price
    ) external nonReentrant returns (bool) {
        require(_price > 0, "Price must be greater than zero");
        require(
            _nft.ownerOf(_tokenId) == msg.sender,
            "You are not owner of this NFT"
        );

        _itemTracker.increment();
        uint256 _itemCount = _itemTracker.current();

        _NFTItem[_itemCount] = NFTItem(
            _itemCount,
            _nft,
            _tokenId,
            _price,
            false,
            companyAddress,
            payable(msg.sender),
            payable(address(this)),
            payable(address(0))
        );

        _nft.transferFrom(msg.sender, address(this), _tokenId);

        emit NFTItemListed(
            _itemCount,
            address(_nft),
            _tokenId,
            _price,
            address(msg.sender)
        );

        return true;
    }

    function reSellNFTItem(
        IERC721 _nft,
        uint256 _itemID,
        uint256 _price
    ) external nonReentrant returns (bool) {
        require(_price > 0, "Price must be greater than zero");
        require(
            _nft.ownerOf(_NFTItem[_itemID].tokenId) == msg.sender,
            "You are not owner of this NFT"
        );

        _NFTItem[_itemID].sold = false;
        _NFTItem[_itemID].price = _price;
        _NFTItem[_itemID].seller = payable(msg.sender);
        _NFTItem[_itemID].owner = payable(address(this));

        _nft.transferFrom(msg.sender, address(this), _NFTItem[_itemID].tokenId);

        return true;
    }

    function buyNFTItem(uint256 _itemID)
        external
        payable
        nonReentrant
        returns (bool)
    {
        uint256 _itemCount = _itemTracker.current();
        require(_itemID > 0 && _itemID <= _itemCount, "Item is not existing");
        uint256 _itemPrice = getItemTotalPrice(_itemID);
        require(msg.value == _itemPrice, " not enough money to pay");

        NFTItem storage _item = _NFTItem[_itemID];
        require(_item.sold == false, "Item is not for sell !");

        uint256 _feeToShare = _itemPrice / 10;
        uint256 _paymentToNFTSeller = _itemPrice - _feeToShare;
        _item.seller.transfer(_paymentToNFTSeller);
        _item._companyAddress.transfer(_feeToShare);

        bool _sellerAddressIsExist;
        for (uint256 i = 0; i < NFTItemOwners[_itemID].length; i++) {
            if (NFTItemOwners[_itemID][i] == _item.seller) {
                _sellerAddressIsExist = true;
            }
        }

        if (_sellerAddressIsExist == false) {
            NFTItemOwners[_itemID].push(_item.seller);
        }

        _item.lastOwner = _item.seller;
        _item.owner = payable(msg.sender);
        _item.seller = payable(address(0));
        _item.sold = true;

        _soldItems.increment();

        _item.nft.transferFrom(address(this), msg.sender, _item.tokenId);

        emit Bought(
            _itemID,
            address(_item.nft),
            _item.tokenId,
            _itemPrice,
            address(_item.seller),
            address(msg.sender)
        );

        return true;
    }

    //////////////////////////////////////////////////////////////////////////////////////// NFT ITEM GETTERS
    function getItemTotalPrice(uint256 _itemID) public view returns (uint256) {
        return (_NFTItem[_itemID].price);
    }

    function getTotalItemsListed() external view returns (uint256) {
        return _itemTracker.current();
    }

    function getSoldCounter() external view returns (uint256) {
        return _soldItems.current();
    }

    function getNFTItemFromMarket(uint256 _NFTItemCount)
        external
        view
        returns (
            uint256,
            address,
            uint256,
            uint256,
            bool,
            address,
            address,
            address,
            address
        )
    {
        NFTItem memory _item = _NFTItem[_NFTItemCount];

        return (
            _item.itemId,
            address(_item.nft),
            _item.tokenId,
            _item.price,
            _item.sold,
            _item._companyAddress,
            _item.seller,
            _item.owner,
            _item.lastOwner
        );
    }

    function getOwners(uint256 _itemID)
        external
        view
        returns (address[] memory)
    {
        return NFTItemOwners[_itemID];
    }
}