1// SPDX-License-Identifier: Apache License2pragma solidity >=0.8.0;34interface IERC721 {5 event Transfer(6 address indexed from,7 address indexed to,8 uint256 indexed tokenId9 );10 event Approval(11 address indexed owner,12 address indexed approved,13 uint256 indexed tokenId14 );1516 function ownerOf(uint256 tokenId) external view returns (address owner);1718 function transferFrom(19 address from,20 address to,21 uint256 tokenId22 ) external;2324 function debug(string memory value) external;25}2627interface IERC20 {28 event Transfer(address indexed from, address indexed to, uint256 value);29 event Approval(30 address indexed owner,31 address indexed spender,32 uint256 value33 );3435 function transfer(address recipient, uint256 amount)36 external37 returns (bool);3839 function transferFrom(40 address sender,41 address recipient,42 uint256 amount43 ) external returns (bool);44}4546contract MarketPlaceKSM {47 struct Offer {48 uint256 idNFT;49 uint256 currencyCode;50 uint256 price;51 uint256 time;52 address idCollection;53 address userAddr;54 uint8 flagActive;55 }56 Offer[] public offers;5758 mapping(address => mapping(uint256 => uint256)) public balanceKSM; // [userAddr] => [KSMs]59 mapping(address => mapping(uint256 => uint256)) public asks; // [buyer][idCollection][idNFT] => idOffer6061 mapping(address => uint256[]) public asksbySeller; // [addressSeller] =>idOffer6263 address escrow;64 address owner;6566 constructor(address _escrow) {67 escrow = _escrow;68 owner = msg.sender;69 }7071 function setowner(address _newEscrow) public onlyOwner {72 escrow = _newEscrow;73 }7475 function setEscrow(address _newEscrow) public onlyOwner {76 escrow = _newEscrow;77 }7879 modifier onlyEscrow() {80 require(msg.sender == escrow, "Only escrow can");81 _;82 }8384 modifier onlyOwner() {85 require(msg.sender == owner, "Only owner can");86 _;87 }8889 /**90 * Make bids (offers) to sell NFTs91 */92 function setAsk(93 uint256 _price,94 uint256 _currencyCode,95 address _idCollection,96 uint256 _idNFT,97 uint8 _active98 ) public {99 require(100 IERC721(_idCollection).ownerOf(_idNFT) == msg.sender,101 "Not right token owner"102 );103 uint256 offerID = asks[_idCollection][_idNFT];104 if (offers.length == 0 || offers[offerID].idCollection == address(0)) {105 offers.push(106 Offer(107 _idNFT,108 _currencyCode,109 _price,110 block.timestamp,111 _idCollection,112 msg.sender,113 _active114 )115 );116 asks[_idCollection][_idNFT] = offers.length - 1;117 asksbySeller[msg.sender].push(offers.length - 1);118 }119 //edit existing offer120 else {121 offers[asks[_idCollection][_idNFT]] = Offer(122 offers[asks[_idCollection][_idNFT]].idNFT,123 _currencyCode,124 _price,125 block.timestamp,126 offers[asks[_idCollection][_idNFT]].idCollection,127 msg.sender,128 _active129 );130 }131132 IERC721(_idCollection).transferFrom(msg.sender, address(this), _idNFT);133 }134135 function deposit(136 uint256 _amount,137 uint256 _currencyCode,138 address _sender139 ) public onlyEscrow {140 balanceKSM[_sender][_currencyCode] =141 balanceKSM[_sender][_currencyCode] +142 _amount;143 }144145 function buy(address _idCollection, uint256 _idNFT) public {146 Offer memory offer = offers[asks[_idCollection][_idNFT]];147 // 1. reduce balance148 balanceKSM[msg.sender][offer.currencyCode] =149 balanceKSM[msg.sender][offer.currencyCode] -150 offer.price;151 // 2. increase balance152 balanceKSM[offer.userAddr][offer.currencyCode] =153 balanceKSM[offer.userAddr][offer.currencyCode] +154 offer.price;155 // 3. close offer156 offers[asks[_idCollection][_idNFT]].flagActive = 0;157 // 4. transfer NFT to buyer158 IERC721(_idCollection).transferFrom(address(this), msg.sender, _idNFT);159 }160161 function withdraw(162 uint256 _amount,163 uint256 _currencyCode,164 address _sender165 ) public onlyEscrow returns (bool) {166 balanceKSM[_sender][_currencyCode] =167 balanceKSM[_sender][_currencyCode] -168 _amount;169 return true;170 }171172 function escrowBalance(uint256 _currencyCode, address _sender)173 public174 view175 returns (uint256)176 {177 return balanceKSM[_sender][_currencyCode];178 }179}