-
-
Save pguso/802890442a9aa2f1d3d6d76bb3f0a91d to your computer and use it in GitHub Desktop.
Basic NFT Marketplace with Price Feed (MATIC to USD)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.0; | |
| import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; | |
| import "@openzeppelin/contracts/utils/Counters.sol"; | |
| import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; | |
| import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; | |
| import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; | |
| contract NFT is ERC721URIStorage { | |
| using Counters for Counters.Counter; | |
| Counters.Counter private _tokenIds; | |
| address contractAddress; | |
| constructor(address marketplaceAddress) ERC721("Digital Marketplace", "DMP") { | |
| contractAddress = marketplaceAddress; | |
| } | |
| function createToken(string memory tokenURI) public returns (uint) { | |
| _tokenIds.increment(); | |
| uint256 newItemId = _tokenIds.current(); | |
| _safeMint(msg.sender, newItemId); | |
| _setTokenURI(newItemId, tokenURI); | |
| setApprovalForAll(contractAddress, true); | |
| return newItemId; | |
| } | |
| } | |
| contract PriceConsumerV3 { | |
| AggregatorV3Interface internal priceFeed; | |
| /** | |
| * Network: Polygon Testnet (Mumbai) | |
| * Aggregator: MATIC/USD | |
| * Address: 0xd0D5e3DB44DE05E9F294BB0a3bEEaF030DE24Ada | |
| */ | |
| constructor() { | |
| priceFeed = AggregatorV3Interface(0xd0D5e3DB44DE05E9F294BB0a3bEEaF030DE24Ada); | |
| } | |
| /** | |
| * Returns the latest price | |
| */ | |
| function getLatestPrice() public view returns (uint256) { | |
| ( | |
| ,int price,,, | |
| ) = priceFeed.latestRoundData(); | |
| return uint256(price); | |
| } | |
| } | |
| contract NFTMarket is ReentrancyGuard, PriceConsumerV3 { | |
| using Counters for Counters.Counter; | |
| Counters.Counter private _itemIds; | |
| Counters.Counter private _itemsSold; | |
| address payable owner; | |
| uint256 listingPrice = 0.1 ether; | |
| constructor() PriceConsumerV3() { | |
| owner = payable(msg.sender); | |
| } | |
| struct MarketItem { | |
| uint itemId; | |
| address nftContract; | |
| uint256 tokenId; | |
| address payable seller; | |
| address payable owner; | |
| uint256 price; | |
| } | |
| mapping(uint256 => MarketItem) private idToMarketItem; | |
| event MarketItemCreated ( | |
| uint indexed itemId, | |
| address indexed nftContract, | |
| uint256 indexed tokenId, | |
| address seller, | |
| address owner, | |
| uint256 price | |
| ); | |
| function getMarketItemById(uint256 marketItemId) public view returns (MarketItem memory) { | |
| MarketItem memory item = idToMarketItem[marketItemId]; | |
| return item; | |
| } | |
| function addItemToMarket( | |
| address nftContract, | |
| uint256 tokenId, | |
| uint256 price | |
| ) public payable nonReentrant { | |
| require(price > 0, "Price must be at least 1 wei"); | |
| require(msg.value == listingPrice, "Price must be equal to listing price"); | |
| _itemIds.increment(); | |
| uint256 itemId = _itemIds.current(); | |
| idToMarketItem[itemId] = MarketItem( | |
| itemId, | |
| nftContract, | |
| tokenId, | |
| payable(msg.sender), | |
| payable(address(0)), | |
| price | |
| ); | |
| IERC721(nftContract).safeTransferFrom(msg.sender, address(this), tokenId); | |
| emit MarketItemCreated( | |
| itemId, | |
| nftContract, | |
| tokenId, | |
| msg.sender, | |
| address(0), | |
| price | |
| ); | |
| } | |
| function sellItemAndTransferOwnership( | |
| address nftContract, | |
| uint256 itemId | |
| ) public payable nonReentrant { | |
| uint price = idToMarketItem[itemId].price; | |
| uint tokenId = idToMarketItem[itemId].tokenId; | |
| require(msg.value == price, "Please submit the asking price in order to complete the purchase"); | |
| idToMarketItem[itemId].seller.transfer(msg.value); | |
| IERC721(nftContract).transferFrom(address(this), msg.sender, tokenId); | |
| idToMarketItem[itemId].owner = payable(msg.sender); | |
| _itemsSold.increment(); | |
| payable(owner).transfer(listingPrice); | |
| } | |
| function getUnsoldItems() public view returns (MarketItem[] memory) { | |
| uint itemCount = _itemIds.current(); | |
| uint unsoldItemCount = _itemIds.current() - _itemsSold.current(); | |
| uint currentIndex = 0; | |
| MarketItem[] memory items = new MarketItem[](unsoldItemCount); | |
| for (uint i = 0; i < itemCount; i++) { | |
| if (idToMarketItem[i + 1].owner == address(0)) { | |
| uint currentId = i + 1; | |
| MarketItem memory currentItem = idToMarketItem[currentId]; | |
| items[currentIndex] = currentItem; | |
| currentIndex += 1; | |
| } | |
| } | |
| return items; | |
| } | |
| function getItemsByOwner() public view returns (MarketItem[] memory) { | |
| uint totalItemCount = _itemIds.current(); | |
| uint itemCount = 0; | |
| uint currentIndex = 0; | |
| for (uint i = 0; i < totalItemCount; i++) { | |
| if (idToMarketItem[i + 1].owner == msg.sender) { | |
| itemCount += 1; | |
| } | |
| } | |
| MarketItem[] memory items = new MarketItem[](itemCount); | |
| for (uint i = 0; i < totalItemCount; i++) { | |
| if (idToMarketItem[i + 1].owner == msg.sender) { | |
| uint currentId = i + 1; | |
| MarketItem memory currentItem = idToMarketItem[currentId]; | |
| items[currentIndex] = currentItem; | |
| currentIndex += 1; | |
| } | |
| } | |
| return items; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
hello I have a problem when user3 tries to buy item but the token transfer call in createMarketSale fails with error ‘ERC721: transfer caller is not owner nor approved. can you help me
i use the function