Contract · NFT
NFT Marketplace
List, buy and cancel NFT offers with EIP-2981 royalty enforcement.
NFT
~2.2M gas
Ethereum
Post-deploy checklist
- Deploy (or select) an ERC721 that implements ERC2981 if you need royalties
- Verify marketplace source so traders can audit fee paths
- Approve the marketplace on each NFT before listing
- Smoke-test list → buy → cancel on a testnet
Configure & deploy
No constructor fields
This marketplace deploys with an empty constructor. Configure listings, fees, and NFT approvals after deploy — there is nothing to fill in on this form by design.
Use cases
- Simple in-app NFT marketplace
- Royalty-enforced secondary sales
- Gated community marketplace
NFTMarketplace.solsolidity
// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.0 (Wizard / Contracts MCP patterns)
// Compiled with Solidity ^0.8.24 — Ethereum Toolset browser solc
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/interfaces/IERC2981.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
// Minimal on-chain NFT listing marketplace with EIP-2981 royalty payout.
contract NFTMarketplace is ReentrancyGuard {
struct Listing { address seller; uint256 price; }
mapping(address => mapping(uint256 => Listing)) public listings;
event Listed(address indexed nft, uint256 indexed id, address seller, uint256 price);
event Sold(address indexed nft, uint256 indexed id, address buyer, uint256 price);
event Cancelled(address indexed nft, uint256 indexed id);
function list(address nft, uint256 id, uint256 price) external {
require(price > 0, "price=0");
require(IERC721(nft).ownerOf(id) == msg.sender, "not owner");
require(IERC721(nft).getApproved(id) == address(this) || IERC721(nft).isApprovedForAll(msg.sender, address(this)), "approve first");
listings[nft][id] = Listing(msg.sender, price);
emit Listed(nft, id, msg.sender, price);
}
function cancel(address nft, uint256 id) external {
require(listings[nft][id].seller == msg.sender, "not seller");
delete listings[nft][id];
emit Cancelled(nft, id);
}
function buy(address nft, uint256 id) external payable nonReentrant {
Listing memory l = listings[nft][id];
require(l.seller != address(0), "not listed");
require(msg.value == l.price, "bad price");
delete listings[nft][id];
// pay royalty if supported
uint256 sellerAmount = msg.value;
try IERC2981(nft).royaltyInfo(id, msg.value) returns (address rcv, uint256 royalty) {
if (royalty > 0 && rcv != address(0)) {
sellerAmount -= royalty;
payable(rcv).transfer(royalty);
}
} catch {}
payable(l.seller).transfer(sellerAmount);
IERC721(nft).safeTransferFrom(l.seller, msg.sender, id);
emit Sold(nft, id, msg.sender, msg.value);
}
}
