1// SPDX-License-Identifier: Apache License2pragma solidity >=0.8.0;3import "../api/UniqueNFT.sol";45// Inline6interface ERC20Events {7 event Transfer(address indexed from, address indexed to, uint256 value);8 event Approval(9 address indexed owner,10 address indexed spender,11 uint256 value12 );13}1415interface ERC20 is Dummy, ERC165, ERC20Events {16 // Selector: name() 06fdde0317 function name() external view returns (string memory);1819 // Selector: symbol() 95d89b4120 function symbol() external view returns (string memory);2122 // Selector: totalSupply() 18160ddd23 function totalSupply() external view returns (uint256);2425 // Selector: decimals() 313ce56726 function decimals() external view returns (uint8);2728 // Selector: balanceOf(address) 70a0823129 function balanceOf(address owner) external view returns (uint256);3031 // Selector: transfer(address,uint256) a9059cbb32 function transfer(address to, uint256 amount) external returns (bool);3334 // Selector: transferFrom(address,address,uint256) 23b872dd35 function transferFrom(36 address from,37 address to,38 uint256 amount39 ) external returns (bool);4041 // Selector: approve(address,uint256) 095ea7b342 function approve(address spender, uint256 amount) external returns (bool);4344 // Selector: allowance(address,address) dd62ed3e45 function allowance(address owner, address spender)46 external47 view48 returns (uint256);49}5051interface UniqueFungible is Dummy, ERC165, ERC20 {}5253contract MarketPlace {54 struct Order {55 uint256 idNFT;56 address currencyCode; // UNIQ tokens as address address (1); wKSM57 uint256 price;58 uint256 time;59 address idCollection;60 address ownerAddr;61 uint8 flagActive;62 string name;63 string symbol;64 string tokenURI;65 }66 Order[] public orders;67 uint256 test;68 mapping(address => uint256) public balanceKSM; // [ownerAddr][currency] => [KSMs]69 mapping(address => mapping(uint256 => uint256)) public asks; // [buyer][idCollection][idNFT] => idorder7071 mapping(address => uint256[]) public asksbySeller; // [addressSeller] =>idorder7273 address escrow;74 address owner;75 address nativecoin;7677 constructor(address _escrow) {78 escrow = _escrow;79 owner = msg.sender;8081 orders.push(82 Order(0, address(0), 0, 0, address(0), address(0), 0, "", "", "")83 );84 }8586 function setowner(address _newEscrow) public onlyOwner {87 escrow = _newEscrow;88 }8990 function setEscrow(address _newEscrow) public onlyOwner {91 escrow = _newEscrow;92 }9394 function setNativeCoin(address _coin) public onlyOwner {95 nativecoin = _coin;96 }9798 modifier onlyEscrow() {99 require(msg.sender == escrow, "Only escrow can");100 _;101 }102103 modifier onlyOwner() {104 require(msg.sender == owner, "Only owner can");105 _;106 }107108 /**109 * Make bids (orders) to sell NFTs110 */111112 receive() external payable {113 revert(114 "Can't accept payment without collection and IDs, use dApp to send"115 );116 }117118 fallback() external payable {119 revert("No such function");120 }121122 event AddedAsk(123 uint256 _price,124 address _currencyCode,125 address _idCollection,126 uint256 _idNFT,127 uint256 orderId128 );129 event EditedAsk(130 uint256 _price,131 address _currencyCode,132 address _idCollection,133 uint256 _idNFT,134 uint8 _active,135 uint256 orderId136 );137138 event CanceledAsk(address _idCollection, uint256 _idNFT, uint256 orderId);139140 event DepositedKSM(uint256 _amount, address _sender);141142 event BoughtNFT4KSM(143 address _idCollection,144 uint256 _idNFT,145 uint256 orderID,146 uint256 orderPrice147 );148149 event BoughtNFT(150 address _idCollection,151 uint256 _idNFT,152 uint256 orderID,153 uint256 orderPrice154 );155156 event WithdrawnAllKSM(address _sender, uint256 balance);157158 event Withdrawn(uint256 _amount, address _currencyCode, address _sender);159160 function addAsk(161 uint256 _price,162 address _currencyCode,163 address _idCollection,164 uint256 _idNFT165 ) public {166 //167 address ownerNFT = UniqueNFT(_idCollection).ownerOf(_idNFT);168 require(ownerNFT == msg.sender, "Only token owner can make ask");169 string memory nameNFT;170 string memory symbolNFT;171 string memory uriNFT;172 try UniqueNFT(_idCollection).name() returns (string memory name_) {173 nameNFT = name_;174 } catch {175 nameNFT = "";176 }177 try UniqueNFT(_idCollection).symbol() returns (string memory symbol_) {178 symbolNFT = symbol_;179 } catch {180 symbolNFT = "";181 }182 try UniqueNFT(_idCollection).tokenURI(_idNFT) returns (183 string memory uri_184 ) {185 uriNFT = uri_;186 } catch {187 uriNFT = "";188 }189 orders.push(190 Order(191 _idNFT,192 _currencyCode,193 _price,194 block.timestamp,195 _idCollection,196 msg.sender,197 1, // 1 = is active198 nameNFT,199 symbolNFT,200 uriNFT201 )202 );203204 uint256 orderId = orders.length - 1;205 asks[_idCollection][_idNFT] = orderId;206 asksbySeller[msg.sender].push(orderId);207 UniqueNFT(_idCollection).transferFrom(208 msg.sender,209 address(this),210 _idNFT211 );212 emit AddedAsk(_price, _currencyCode, _idCollection, _idNFT, orderId);213 }214215 function editAsk(216 uint256 _price,217 address _currencyCode,218 address _idCollection,219 uint256 _idNFT,220 uint8 _active221 ) public {222 uint256 orderID = asks[_idCollection][_idNFT];223224 require(225 orders[orderID].ownerAddr == msg.sender,226 "Only token owner can edit ask"227 );228 require(orders[orderID].flagActive != 0, "This ask is closed");229 if (_price > 0) {230 orders[orderID].price = _price;231 }232233 if (_currencyCode != address(0)) {234 orders[orderID].currencyCode = _currencyCode;235 }236237 orders[orderID].time = block.timestamp;238 orders[orderID].flagActive = _active;239240 emit EditedAsk(241 _price,242 _currencyCode,243 _idCollection,244 _idNFT,245 _active,246 orderID247 );248 }249250 function cancelAsk(address _idCollection, uint256 _idNFT) public {251 uint256 orderID = asks[_idCollection][_idNFT];252253 require(254 orders[orderID].ownerAddr == msg.sender,255 "Only token owner can edit ask"256 );257 require(orders[orderID].flagActive != 0, "This ask is closed");258259 orders[orderID].time = block.timestamp;260 orders[orderID].flagActive = 0;261 UniqueNFT(_idCollection).transferFrom(262 address(this),263 orders[orderID].ownerAddr,264 _idNFT265 );266 emit CanceledAsk(_idCollection, _idNFT, orderID);267 }268269 function depositKSM(uint256 _amount, address _sender) public onlyEscrow {270 balanceKSM[_sender] = balanceKSM[_sender] + _amount;271 emit DepositedKSM(_amount, _sender);272 }273274 function buyKSM(275 address _idCollection,276 uint256 _idNFT,277 address _buyer,278 address _receiver279 ) public {280 Order memory order = orders[asks[_idCollection][_idNFT]];281 require(msg.sender == escrow || msg.sender == _buyer, "Only escrow or buyer can call buyKSM" );282 //1. reduce balance283 balanceKSM[_buyer] = balanceKSM[_buyer] - order.price;284 balanceKSM[order.ownerAddr] = balanceKSM[order.ownerAddr] + order.price;285 // 2. close order286 orders[asks[_idCollection][_idNFT]].flagActive = 0;287 // 3. transfer NFT to buyer288 UniqueNFT(_idCollection).transferFrom(address(this), _receiver, _idNFT);289 emit BoughtNFT4KSM(290 _idCollection,291 _idNFT,292 asks[_idCollection][_idNFT],293 order.price294 );295 }296297 function buy(address _idCollection, uint256 _idNFT)298 public299 payable300 returns (bool result)301 {302 //buing for UNQ like as ethers303304 Order memory order = orders[asks[_idCollection][_idNFT]];305 //1. check sent amount and send to seller306 require(307 msg.value == order.price,308 "Not right amount sent, have to be equal price"309 );310 // 2. close order311 orders[asks[_idCollection][_idNFT]].flagActive = 0;312313 // 3. transfer NFT to buyer314 UniqueNFT(_idCollection).transferFrom(315 address(this),316 msg.sender,317 _idNFT318 );319 //uint balance = address(this).balance;320 result = payable(order.ownerAddr).send(order.price);321 emit BoughtNFT(322 _idCollection,323 _idNFT,324 asks[_idCollection][_idNFT],325 order.price326 );327 }328329 /*330 function buyOther (address _idCollection, uint256 _idNFT, address _currencyCode, uint _amount ) public { //buy for sny token if seller wants331332 Order memory order = orders[ asks[_idCollection][_idNFT]];333 //1. check sent amount and transfer from buyer to seller334 require (order.price == _amount && order.currencyCode == _currencyCode, "Not right amount or currency sent, have to be equal currency and price" );335 // !!! transfer have to be approved to marketplace!336 IERC20(order.currencyCode).transferFrom(msg.sender, address(this), order.price); //to not disclojure buyer's address337 IERC20(order.currencyCode).transfer(order.ownerAddr, order.price);338 // 2. close order339 orders[ asks[_idCollection][_idNFT]].flagActive = 0;340 // 3. transfer NFT to buyer341 IERC721ext(_idCollection).transferFrom(address(this), msg.sender, _idNFT);342343344 }345 */346347 function withdrawAllKSM(address _sender)348 public349 onlyEscrow350 returns (uint256 lastBalance)351 {352 lastBalance = balanceKSM[_sender];353 balanceKSM[_sender] = 0;354 emit WithdrawnAllKSM(_sender, lastBalance);355 }356357 function withdraw(358 uint256 _amount,359 address _currencyCode,360 address payable _sender361 ) public onlyOwner returns (bool result) {362 if (_currencyCode != nativecoin) {363 //erc20 compat. tokens on UNIQUE chain364 // uint balance = IERC20(_currencyCode).balanceOf(address(this));365 UniqueFungible(_currencyCode).transfer(_sender, _amount);366 } else {367 // uint balance = address(this).balance;368369 result = (_sender).send(_amount); // for UNQ like as ethers370 }371 emit Withdrawn(_amount, _currencyCode, _sender);372 return result;373 }374375 // event GettedOrder(uint , Order);376 function getOrder(address _idCollection, uint256 _idNFT)377 public378 view379 returns (Order memory)380 {381 uint256 orderId = asks[_idCollection][_idNFT];382 Order memory order = orders[orderId];383 // emit GettedOrder (orderId, order);384 return order;385 }386387 function getOrdersLen() public view returns (uint256) {388 return orders.length;389 }390}