158 lines
4.4 KiB
Solidity
158 lines
4.4 KiB
Solidity
// SPDX-License-Identifier: MIT OR Apache-2.0
|
|
//mostly done
|
|
|
|
pragma solidity ^0.8.14;
|
|
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
|
|
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
|
|
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
|
|
import "./interfaces/ITreasury.sol";
|
|
|
|
contract Marketplace is Initializable {
|
|
//variables
|
|
uint256 currentSaleId;
|
|
uint256 fee;
|
|
ITreasury treasury;
|
|
IERC721Upgradeable nft;
|
|
IERC20Upgradeable BoM;
|
|
struct Sale {
|
|
address payable seller;
|
|
uint256 tokenId;
|
|
uint256 price;
|
|
bool bought;
|
|
bool cancelled;
|
|
}
|
|
mapping(uint256 => Sale) saleIdToSale;
|
|
|
|
//events
|
|
event SaleCreated(
|
|
uint256 indexed saleId,
|
|
address indexed seller,
|
|
uint256 price,
|
|
uint256 indexed tokenId
|
|
);
|
|
|
|
event SaleCancelled(uint256 indexed saleId);
|
|
|
|
event SaleUpdated(
|
|
uint256 indexed saleId,
|
|
uint256 oldPrice,
|
|
uint256 newPrice
|
|
);
|
|
|
|
event TokenBought(
|
|
uint256 indexed saleId,
|
|
address indexed buyer,
|
|
uint256 indexed tokenId,
|
|
uint256 price
|
|
);
|
|
|
|
event FeesChanged(address indexed admin, uint256 oldFee, uint256 newFee);
|
|
|
|
//modifiers
|
|
modifier isExistingSale(uint256 saleId) {
|
|
require(saleIdToSale[saleId].price != 0, "!exists");
|
|
_;
|
|
}
|
|
|
|
modifier onlySaleOwner(uint256 saleId) {
|
|
require(saleIdToSale[saleId].seller == msg.sender, "!seller");
|
|
_;
|
|
}
|
|
|
|
modifier onlyValidPrice(uint256 price) {
|
|
require(price > 0, "!price");
|
|
_;
|
|
}
|
|
|
|
modifier onlyAdmin() {
|
|
require(treasury.isAdmin(msg.sender), "!admin");
|
|
_;
|
|
}
|
|
|
|
// constructor(
|
|
// uint256 _fee,
|
|
// ITreasury _treasury,
|
|
// IERC721Upgradeable _nft,
|
|
// IERC20Upgradeable token
|
|
// ) {
|
|
// fee = _fee;
|
|
// treasury = _treasury;
|
|
// nft = _nft;
|
|
// BoM = token;
|
|
// }
|
|
|
|
function initialize(
|
|
uint256 _fee,
|
|
ITreasury _treasury,
|
|
IERC721Upgradeable _nft,
|
|
IERC20Upgradeable token
|
|
) public initializer {
|
|
fee = _fee;
|
|
treasury = _treasury;
|
|
nft = _nft;
|
|
BoM = token;
|
|
}
|
|
|
|
//internal functions
|
|
function _distributeFunds(uint256 amount, address seller) internal {
|
|
uint256 _fee = (amount * fee) / 10000;
|
|
uint256 goesToSeller = amount - _fee;
|
|
BoM.transferFrom(msg.sender, address(this), _fee);
|
|
BoM.transferFrom(msg.sender, seller, goesToSeller);
|
|
}
|
|
|
|
//external functions
|
|
function createSale(uint256 tokenId, uint256 price)
|
|
public
|
|
onlyValidPrice(price)
|
|
{
|
|
currentSaleId++;
|
|
Sale storage sale = saleIdToSale[currentSaleId];
|
|
sale.seller = payable(msg.sender);
|
|
sale.price = price;
|
|
sale.tokenId = tokenId;
|
|
nft.transferFrom(msg.sender, address(this), tokenId);
|
|
emit SaleCreated(currentSaleId, msg.sender, price, tokenId);
|
|
}
|
|
|
|
function cancelSale(uint256 saleId) public onlySaleOwner(saleId) {
|
|
Sale storage sale = saleIdToSale[saleId];
|
|
require(!sale.bought, "bought");
|
|
require(!sale.cancelled, "cancelled");
|
|
nft.transferFrom(address(this), msg.sender, sale.tokenId);
|
|
sale.cancelled = true;
|
|
emit SaleCancelled(saleId);
|
|
}
|
|
|
|
function updateSale(uint256 saleId, uint256 price)
|
|
public
|
|
onlySaleOwner(saleId)
|
|
onlyValidPrice(price)
|
|
isExistingSale(saleId)
|
|
{
|
|
Sale storage sale = saleIdToSale[saleId];
|
|
require(!sale.bought, "bought");
|
|
require(!sale.cancelled, "cancelled");
|
|
uint256 oldPrice = sale.price;
|
|
sale.price = price;
|
|
emit SaleUpdated(saleId, oldPrice, price);
|
|
}
|
|
|
|
function buyToken(uint256 saleId) public isExistingSale(saleId) {
|
|
Sale storage sale = saleIdToSale[saleId];
|
|
require(!sale.bought, "bought");
|
|
require(!sale.cancelled, "cancelled");
|
|
nft.transferFrom(address(this), msg.sender, sale.tokenId);
|
|
_distributeFunds(sale.price, sale.seller);
|
|
sale.bought = true;
|
|
emit TokenBought(saleId, msg.sender, sale.tokenId, sale.price);
|
|
}
|
|
|
|
//admin functions
|
|
function changeFees(uint256 _fee) public onlyAdmin {
|
|
require(_fee > 0 && _fee < 2000, "wrong arg");
|
|
emit FeesChanged(msg.sender, fee, _fee);
|
|
fee = _fee;
|
|
}
|
|
}
|