Guest User

Untitled

a guest
Aug 17th, 2021
83
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ### MAIN CONTRACT
  2.  
  3. // SPDX-License-Identifier: MIT
  4.  
  5. pragma solidity >=0.6.0 <0.8.0;
  6.  
  7. import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721BurnableUpgradeable.sol";
  8. import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
  9. import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
  10.  
  11. contract Woonkly is ERC721BurnableUpgradeable, AccessControlUpgradeable {
  12. using SafeMathUpgradeable for uint256;
  13.  
  14. mapping (uint256 => uint256) private _tokens_price;
  15. mapping (uint256 => address payable) private _tokenCreator;
  16. mapping (uint256 => address payable) private _offers_marketplace;
  17. mapping (uint256 => uint256) private _offers_closeTimestamp;
  18.  
  19. event OfferReceived(address indexed payer, uint256 tokenId, uint256 amount);
  20. event OfferAccepted(address indexed payer, uint256 tokenId);
  21. event OfferRejected(address indexed payer, uint256 tokenId);
  22. event OfferExpired(address indexed payer, uint256 tokenId);
  23. event OfferCancelled(address indexed payer, uint256 tokenId);
  24.  
  25. uint256 private constant COMMISSION_EXPONENT = 4;
  26. address payable private _platformAddress;
  27. uint256 private _platformCommissionPercent;
  28. uint256 private _extensionTimePeriod;
  29. uint256 private _offerExpirationTime;
  30.  
  31. modifier tokenExists(uint256 _tokenId) {
  32. require(_exists(_tokenId), "Woonkly: Id for this token does not exist.");
  33. _;
  34. }
  35.  
  36. modifier onlyOwner(uint256 _tokenId) {
  37. require(_tokenCreator[_tokenId] == msg.sender, "Woonkly: You are not the owner of this token.");
  38. _;
  39. }
  40.  
  41. modifier offerExist(uint256 _tokenId) {
  42. require(_offers_marketplace[_tokenId] != address(0), "Kargain: Does not exist any offer for this token.");
  43. _;
  44. }
  45.  
  46. modifier onlyAdmin() {
  47. require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "Woonkly: Caller is not a admin");
  48. _;
  49. }
  50.  
  51. function initialize(address payable _platformAddress_, uint256 _platformCommissionPercent_) public initializer {
  52. _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
  53. __AccessControl_init();
  54. _offerExpirationTime = 1 days;
  55. _platformAddress = _platformAddress_;
  56. _platformCommissionPercent = _platformCommissionPercent_;
  57. __ERC721Burnable_init();
  58. __ERC721_init("Woonkly", "WKY");
  59. }
  60.  
  61. function creatorOf(uint256 tokenId) external view returns (address payable) {
  62. require(_tokenCreator[tokenId] != address(0x0), "Woonkly: Creator query for nonexistent token");
  63. return _tokenCreator[tokenId];
  64. }
  65.  
  66. function exist(uint256 _tokenId) external view returns (bool) {
  67. return _exists(_tokenId);
  68. }
  69.  
  70. function offerExpirationTime() external view returns (uint256) {
  71. return _offerExpirationTime;
  72. }
  73.  
  74. function setOfferExpirationTime(uint256 offerExpirationTime_) external onlyAdmin {
  75. _offerExpirationTime = offerExpirationTime_;
  76. }
  77.  
  78. function platformCommissionPercent() external view returns (uint256) {
  79. return _platformCommissionPercent;
  80. }
  81.  
  82. function setPlatformCommissionPercent(uint256 platformCommissionPercent_) external onlyAdmin {
  83. _platformCommissionPercent = platformCommissionPercent_;
  84. }
  85.  
  86. function tokenPrice(uint256 _tokenId) external view tokenExists(_tokenId) returns (uint256) {
  87. return _tokens_price[_tokenId];
  88. }
  89.  
  90. function setExtensionTimePeriod(uint256 extensionTimePeriod_) external onlyAdmin {
  91. _extensionTimePeriod = extensionTimePeriod_;
  92. }
  93.  
  94. function extensionTimePeriod() public view returns(uint256){
  95. return _extensionTimePeriod;
  96. }
  97.  
  98. function setTokenPrice(uint256 _tokenId, uint256 _price) external tokenExists(_tokenId) onlyOwner(_tokenId)
  99. {
  100. require(
  101. _offers_marketplace[_tokenId] == address(0) ||
  102. _offers_closeTimestamp[_tokenId] < now,
  103. "Woonkly: An offer is already submitted, token price cannot be changed until it expires."
  104. );
  105. _tokens_price[_tokenId] = _price;
  106. }
  107.  
  108. function _refundOffer(uint256 _tokenId) private tokenExists(_tokenId) offerExist(_tokenId) {
  109. address payable buyer = _offers_marketplace[_tokenId];
  110.  
  111. delete _offers_marketplace[_tokenId];
  112. delete _offers_closeTimestamp[_tokenId];
  113.  
  114. buyer.transfer(_tokens_price[_tokenId]);
  115. }
  116.  
  117. function createOffer(uint256 _tokenId) external payable tokenExists(_tokenId)
  118. {
  119. require(ownerOf(_tokenId) != msg.sender, "Woonkly: You cannot buy your own token.");
  120. require(_offers_marketplace[_tokenId] == address(0) && _offers_closeTimestamp[_tokenId] < now, "Woonkly: An offer is already submitted.");
  121. require(msg.value == _tokens_price[_tokenId], "Woonkly: The offer amount is invalid.");
  122.  
  123. _offers_marketplace[_tokenId] = payable(msg.sender);
  124. _offers_closeTimestamp[_tokenId] = now.add(_offerExpirationTime);
  125. emit OfferReceived(msg.sender, _tokenId, msg.value);
  126. }
  127.  
  128. function acceptOffer(uint256 _tokenId) external tokenExists(_tokenId) offerExist(_tokenId) onlyOwner(_tokenId) {
  129. if (_offers_closeTimestamp[_tokenId] < now) {
  130. delete _offers_marketplace[_tokenId];
  131. delete _offers_closeTimestamp[_tokenId];
  132. emit OfferExpired(msg.sender, _tokenId);
  133. return;
  134. }
  135. address payable buyer = _offers_marketplace[_tokenId];
  136.  
  137. delete _offers_marketplace[_tokenId];
  138. delete _offers_closeTimestamp[_tokenId];
  139.  
  140. uint256 platformCommission = _tokens_price[_tokenId].mul(_platformCommissionPercent).div(10**COMMISSION_EXPONENT);
  141. _platformAddress.transfer(platformCommission);
  142.  
  143. msg.sender.transfer(_tokens_price[_tokenId].sub(platformCommission));
  144. safeTransferFrom(msg.sender, buyer, _tokenId);
  145.  
  146. emit OfferAccepted(msg.sender, _tokenId);
  147. }
  148.  
  149. function rejectOffer(uint256 _tokenId) external tokenExists(_tokenId) onlyOwner(_tokenId) offerExist(_tokenId) {
  150. _refundOffer(_tokenId);
  151. emit OfferRejected(msg.sender, _tokenId);
  152. }
  153.  
  154. function mint(uint256 _tokenId, uint256 _price) external {
  155. require(!_exists(_tokenId), "Woonkly: Id for this token already exists.");
  156. require(_price > 0, "Woonkly: Prices must be greater than zero.");
  157. _mint(msg.sender, _tokenId);
  158. _tokenCreator[_tokenId] = msg.sender;
  159. _tokens_price[_tokenId] = _price;
  160. }
  161. }
  162.  
  163.  
  164.  
  165. #### SECONDARY CONTRACT
  166.  
  167. // SPDX-License-Identifier: MIT
  168.  
  169. pragma solidity >=0.6.0 <0.8.0;
  170.  
  171. import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721HolderUpgradeable.sol";
  172. import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
  173. import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
  174. import "./IWoonkly.sol";
  175.  
  176. contract WoonklyAuction is ERC721HolderUpgradeable, AccessControlUpgradeable {
  177.  
  178. using SafeMathUpgradeable for uint256;
  179. uint8 private constant COMMISSION_EXPONENT = 4;
  180.  
  181. uint256 private _platformCommissionPercent;
  182. address payable private _platformAddress;
  183. uint256 private _extensionTimePeriod;
  184.  
  185. mapping (IWoonkly => mapping (uint256 => uint256)) private _auction_closeTimestamp;
  186. mapping (IWoonkly => mapping (uint256 => address payable)) private _auction_bidder;
  187. mapping (IWoonkly => mapping (uint256 => uint256)) private _auction_amount;
  188. mapping (IWoonkly => mapping (uint256 => bool)) private _auction_claimed;
  189. mapping (IWoonkly => mapping (uint256 => bool)) private _auction_exist;
  190. mapping (IWoonkly => mapping (uint256 => uint256)) private _auction_platformCommissionPercent;
  191. mapping (IWoonkly => mapping (uint256 => address payable)) private _auction_vendor;
  192.  
  193.  
  194. event AuctionCreated(IWoonkly indexed token, uint256 indexed tokenId, uint256 closeTimestamp);
  195. event AuctionBid(IWoonkly indexed token, uint256 indexed tokenId, address indexed bidder, uint256 amount);
  196. event AuctionClaimed(IWoonkly indexed token, uint256 indexed tokenId, address indexed bidder, uint256 amount, uint256 platformCommision);
  197.  
  198. modifier onlyAdmin() {
  199. require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "Woonkly: Caller is not a admin");
  200. _;
  201. }
  202.  
  203. function initialize(address payable _platformAddress_, uint256 _platformCommissionPercent_, uint256 extensionTimePeriod_) public initializer {
  204. _platformAddress = _platformAddress_;
  205. _platformCommissionPercent = _platformCommissionPercent_;
  206. _extensionTimePeriod = extensionTimePeriod_;
  207. __ERC721Holder_init();
  208. __AccessControl_init();
  209. _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
  210. }
  211.  
  212. function setPlatformAddress(address payable platformAddress_) external onlyAdmin {
  213. _platformAddress = platformAddress_;
  214. }
  215.  
  216. function platformAddress() public view returns(address payable){
  217. return _platformAddress;
  218. }
  219.  
  220. function setPlatformCommissionPercent(uint256 platformCommissionPercent_) external onlyAdmin {
  221. _platformCommissionPercent = platformCommissionPercent_;
  222. }
  223.  
  224. function platformCommissionPercent() public view returns(uint256){
  225. return _platformCommissionPercent;
  226. }
  227.  
  228.  
  229. function setExtensionTimePeriod(uint256 extensionTimePeriod_) external onlyAdmin {
  230. _extensionTimePeriod = extensionTimePeriod_;
  231. }
  232.  
  233. function extensionTimePeriod() public view returns(uint256){
  234. return _extensionTimePeriod;
  235. }
  236.  
  237. function ownerOfToken(IWoonkly tokenContract, uint256 tokenId) public returns(address) {
  238. return tokenContract.creatorOf(tokenId);
  239. }
  240.  
  241. function auction(IWoonkly tokenContract, uint256 tokenId, uint256 secondsToClose) external {
  242. require(!_auction_exist[tokenContract][tokenId], "Woonkly: Auction for this token already exist");
  243. require(tokenContract.creatorOf(tokenId) == msg.sender, "You are not the owner of this token.");
  244. uint256 closeTimestamp = block.timestamp + secondsToClose;
  245. _auction_closeTimestamp[tokenContract][tokenId] = closeTimestamp;
  246. _auction_vendor[tokenContract][tokenId] = tokenContract.creatorOf(tokenId);
  247. _auction_platformCommissionPercent[tokenContract][tokenId] = _platformCommissionPercent;
  248. _auction_bidder[tokenContract][tokenId] = payable(address(0));
  249. _auction_amount[tokenContract][tokenId] = 0;
  250. _auction_claimed[tokenContract][tokenId] = false;
  251. _auction_exist[tokenContract][tokenId] = true;
  252.  
  253. emit AuctionCreated(tokenContract, tokenId,closeTimestamp);
  254. }
  255.  
  256. function placeBid(IWoonkly tokenContract, uint256 tokenId) external payable {
  257. require(_auction_exist[tokenContract][tokenId], "Woonkly: Auction for this token not exist");
  258. require(!_auction_claimed[tokenContract][tokenId], "Woonkly: Auction was claimed");
  259. require(_auction_closeTimestamp[tokenContract][tokenId] >= block.timestamp,
  260. "Woonkly: Auction for this token is closed");
  261. require(msg.value > _auction_amount[tokenContract][tokenId],
  262. "Woonkly: Bid should be higher than current");
  263.  
  264. uint256 refundAmount = _auction_amount[tokenContract][tokenId];
  265. address payable refundAddress = _auction_bidder[tokenContract][tokenId];
  266.  
  267. _auction_bidder[tokenContract][tokenId] = payable(address(msg.sender));
  268. _auction_amount[tokenContract][tokenId] = msg.value;
  269.  
  270. // Extend close time if it's required
  271. uint256 bidTimeOffset = _auction_closeTimestamp[tokenContract][tokenId].sub(block.timestamp);
  272. if (bidTimeOffset < _extensionTimePeriod) {
  273. _auction_closeTimestamp[tokenContract][tokenId] = _auction_closeTimestamp[tokenContract][tokenId].add(
  274. _extensionTimePeriod.sub(bidTimeOffset)
  275. );
  276. }
  277.  
  278. refundAddress.transfer(refundAmount);
  279.  
  280. emit AuctionBid(tokenContract, tokenId, msg.sender, msg.value);
  281. }
  282.  
  283. function claimAuction(IWoonkly tokenContract, uint256 tokenId) external onlyAdmin {
  284. require(_auction_exist[tokenContract][tokenId], "Woonkly: Auction not exist");
  285. require(!_auction_claimed[tokenContract][tokenId], "Woonkly: Auction was claimed");
  286. require(_auction_closeTimestamp[tokenContract][tokenId] < block.timestamp,
  287. "Woonkly: Auction is not closed");
  288.  
  289. _auction_claimed[tokenContract][tokenId] = true;
  290.  
  291. uint256 platformCommission;
  292. if (_auction_bidder[tokenContract][tokenId] != address(0)){
  293. platformCommission = _auction_amount[tokenContract][tokenId]
  294. .mul(_auction_platformCommissionPercent[tokenContract][tokenId])
  295. .div(10** COMMISSION_EXPONENT);
  296. tokenContract.safeTransferFrom(msg.sender, _auction_bidder[tokenContract][tokenId], tokenId);
  297.  
  298. _platformAddress.transfer(platformCommission);
  299. _auction_vendor[tokenContract][tokenId].transfer(
  300. _auction_amount[tokenContract][tokenId].sub(platformCommission)
  301. );
  302. }
  303. else {
  304. tokenContract.burn(tokenId);
  305. }
  306.  
  307. emit AuctionClaimed(tokenContract, tokenId, _auction_bidder[tokenContract][tokenId],
  308. _auction_amount[tokenContract][tokenId], platformCommission);
  309. }
  310. }
  311.  
  312.  
  313. #### INTERFACE
  314.  
  315. //SPDX-License-Identifier: Unlicense
  316. pragma solidity >=0.6.0 <0.8.0;
  317.  
  318. import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
  319.  
  320. interface IWoonkly is IERC721Upgradeable {
  321. function mint(uint256 _tokenId, uint256 _price) external;
  322. function burn(uint256 tokenId) external;
  323. function creatorOf(uint256 tokenId) external view returns (address payable);
  324. }
  325.  
  326.  
RAW Paste Data