A production-ready, modular NFT marketplace built with Solidity and Foundry, featuring:
- Fixed-price listings
- English auctions
- Cross-collection & token-level offers
- ERC-2981 royalties
- Platform fees
- Full audit-grade safety patterns
This NFT Marketplace is a modular trading protocol supporting multiple sale types and marketplace operations across any ERC-721 collection.
The system is split into three independent components:
All modules support:
- ERC-2981 royalties
- Platform fees
- Safe ETH + NFT transfers
- Custom errors
- Pausable emergency shutdown
- CEI & reentrancy-safe execution
Each module is isolated for security, upgradeability, and gas efficiency.
Works with ANY NFT collectionβno per-collection deployment required.
- Reentrancy guards
- CEI pattern
- Pull-payment withdrawal model
- Strict validation of timestamps, approvals, and payment amounts
- Custom errors
- Tight storage
- Reduced SSTORE
- Minimal overhead in critical flows
- Auto-extending English auctions
- Offers on unlisted NFTs
- Pull-pattern bid refunds
- Proper ERC-2981 royalty routing
Perfect for demonstrating:
- DeFi-grade Solidity engineering
- Multi-contract marketplace architecture
- Secure ETH handling & settlement flows
- Advanced testing patterns
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β NFTMarketplace.sol β
β (Fixed Price Listings - Primary User Path) β
β β’ Create, update, cancel, and purchase listings β
β β’ Fee + royalty distribution β
β β’ Multi-collection support β
βββββββββββββββββ¬βββββββββββββββββββββββββββββββ¬ββββββββββββββ
β β
ββββββββββββΌβββββββββ βββββββββββΌβββββββββββ
β AuctionHouse β β OffersManager β
β (English β β (Global Offers β
β Auctions) β β System) β
β β’ Bids β β β’ Make offers β
β β’ Settlements β β β’ Accept offers β
β β’ Time extends β β β’ Cancel/Refund β
βββββββββββββββββββββ ββββββββββββββββββββββ
- Fixed-price listings
- Price updates & cancellations
- Purchase flow with royalties + fees
- SafeTransfer + CEI everywhere
- English auctions
- Minimum bid increments (default 5%)
- Auto-extend (default 15 minutes)
- Pull-based refund mechanism
- Settlement with royalties
- Collection-wide or token-specific offers
- Fully independent from listings
- Offer updates
- Automatic refund on cancellation/expiration
- Create listing
- Update price
- Cancel listing
- Buy instantly
- Create auction
- Enforce min bid increment
- Auto-extend near expiry
- Withdraw outbid bids
- Settle after expiration
- Make offers on any NFT (listed or unlisted)
- Accept offers instantly
- Update or cancel offers
- Full pull-pattern refund logic
Distribution order (OpenSea style):
- ERC-2981 royalties
- Platform fee
- Remainder β seller
| Parameter | Value |
|---|---|
| Min Listing Duration | 1 hour |
| Max Listing Duration | 180 days |
| Max Platform Fee | 10% |
| Min Auction Duration | 1 hour |
| Max Auction Duration | 30 days |
| Min Bid Increment | 5% |
| Auction Time Extension | 15 minutes |
| Max Offer Duration | 30 days |
- Reentrancy Guard on all ETH flows
- CEI pattern everywhere
- Pull-payment for all refunds
- Strict ERC-721 approval checks
- Pausable emergency mode
- Custom errors
- Graceful royalty fallback
- Reentrancy during purchases/bids
- Wrong ETH refund accounting
- Auction griefing
- Timestamp manipulation
- Royalty overflow
- Approval swapping
- Front-running of updates
nft-marketplace/
βββ docs/
β βββ DEPLOYMENT_GUIDE.md
β βββ DEPLOYMENT_QUICK.md
βββ script/
β βββ Deploy.s.sol
βββ src/
β βββ NFTMarketplace.sol
β βββ AuctionHouse.sol
β βββ OffersManager.sol
β βββ interfaces/
β β βββ INFTMarketplace.sol
β β βββ IAuctionHouse.sol
β β βββ IOffersManager.sol
β βββ libraries/
β βββ MarketplaceErrors.sol
β βββ MarketplaceTypes.sol
βββ test/
β βββ e2e/
β β βββ README.md
β β βββ QUICK_REFERENCE.md
β β βββ MarketplaceUserFlows.t.sol
β β βββ MarketplaceEdgeCases.t.sol
β βββ unit/
β β βββ NFTMarketplaceTest.t.sol
β β βββ AuctionHouseTest.t.sol
β β βββ OffersManagerTest.t.sol
β βββ integration/
β β βββ MarketplaceIntegrationTest.t.sol
β βββ mocks/
β βββ MockNFT.sol
βββ .env
βββ .gitignore
βββ README.md
Status: All tests passing β
Total Tests: 140 tests
Success Rate: 100%
| Test Suite | Tests | Purpose |
|---|---|---|
| Unit Tests | 90+ | Individual contract functions |
| Integration Tests | 20+ | Cross-contract interactions |
| E2E User Flows | 10 | Realistic user journeys |
| E2E Edge Cases | 13 | Boundary conditions |
| E2E Stress Tests | 3 | High-load scenarios |
- β First-Time Buyer Journey - Offer β Accept β Ownership
- β NFT Flipper Strategy - Buy Low β Relist High β Profit
- β Competitive Auction with Sniping - Multiple bidders, time extensions
- β Offer War Scenario - Competing offers, highest wins
- β Failed Auction Below Reserve - Reserve not met, NFT returns
- β Cross-Platform Strategy - Switch between listing types
- β Panic Cancel Scenario - Error recovery (wrong price)
- β Long-term Holder Journey - Buy β Hold β Relist β Sell
- β Auction Outbid Frustration - Multiple outbids, withdrawals
- β Bulk Operations - Collection-wide management
- Expired listing race conditions
- Offer expires during transaction
- Multiple time extensions
- Ownership changes during offers
- Maximum duration listings (180 days)
- Minimum bid precision (1 wei bids)
- Offer update mechanics
- Zero-bid auctions
- Price update edge cases
- Simultaneous operations
- Large amount handling
- Late settlements
- Cancelled offer cleanup
- 50+ offers on same NFT
- 20 rapid auction bids
- Collection-wide operations (20 NFTs)
For detailed E2E test documentation:
- π test/e2e/README.md - Complete testing guide with patterns and examples
- β‘ test/e2e/QUICK_REFERENCE.md - Command cheat sheet
# Run all tests
forge test
# Run with verbosity
forge test -vvv
# Run specific test suite
forge test --match-path "test/unit/*.sol"
forge test --match-path "test/e2e/*.sol"
# Run specific test
forge test --match-test testListNFT
# Run with gas report
forge test --gas-report
# Run E2E tests with console logs
forge test --match-path "test/e2e/*.sol" -vv
# Run coverage
forge coverage| Operation | Average Gas | Min Gas | Max Gas | Notes |
|---|---|---|---|---|
| List NFT | 226,930 | 222,420 | 242,344 | Includes approval check + storage |
| Buy NFT | 135,556 | 33,212 | 177,186 | With royalty + fee distribution |
| Cancel Listing | 37,142 | 37,142 | 37,142 | State cleanup |
| Update Listing | 38,408 | 36,865 | 39,952 | Price/duration changes |
| Operation | Average Gas | Min Gas | Max Gas | Notes |
|---|---|---|---|---|
| Create Auction | 297,566 | 285,054 | 325,009 | NFT escrow + state setup |
| Place Bid | 67,873 | 57,145 | 86,845 | Includes refund mechanism |
| Settle Auction | 136,353 | 64,735 | 174,532 | NFT transfer + payments |
| Withdraw Pending | 31,092 | 31,092 | 31,092 | Pull-pattern refund |
| Operation | Average Gas | Min Gas | Max Gas | Notes |
|---|---|---|---|---|
| Make Offer | 228,857 | 208,137 | 279,349 | ETH escrow + tracking |
| Accept Offer | 126,031 | 33,192 | 178,679 | NFT transfer + distribution |
| Cancel Offer | 41,647 | 41,647 | 41,647 | Refund + state cleanup |
| Update Offer | 39,674 | 39,674 | 39,674 | Amount/duration changes |
- β Custom errors save ~50% vs string reverts
- β Tight storage packing reduces SSTORE costs
- β Pull-pattern prevents expensive loops
- β Cached storage reads in hot paths
- β Minimal external calls per transaction
| Contract | Deployment Cost | Deployment Size |
|---|---|---|
| NFTMarketplace | 1,493,237 gas | 6,732 bytes |
| AuctionHouse | 1,698,196 gas | 7,680 bytes |
| OffersManager | 1,581,479 gas | 7,140 bytes |
| Total | 4,772,912 gas | 21,552 bytes |
Gas prices based on actual test runs with Foundry gas reporting
nft.approve(address(marketplace), tokenId);
marketplace.listNFT(
address(nft),
tokenId,
1 ether,
7 days
);marketplace.buyNFT{value: 1 ether}(listingId);nft.approve(address(auctionHouse), tokenId);
auctionHouse.createAuction(
address(nft),
tokenId,
0.5 ether, // starting price
1 ether, // reserve price (0 for no reserve)
block.timestamp,
7 days,
500 // 5% minimum bid increment
);auctionHouse.placeBid{value: 0.6 ether}(auctionId);offersManager.makeOffer{value: 0.3 ether}(
address(nft),
tokenId,
7 days
);nft.approve(address(offersManager), tokenId);
offersManager.acceptOffer(offerId);- Foundry
- Git
git clone https://github.com/Enricrypto/nft-marketplace.git
cd nft-marketplace
forge install
forge build# Run all tests
forge test
# Run E2E tests with detailed output
forge test --match-path "test/e2e/*.sol" -vv
# Generate gas report
forge test --gas-report
# Generate coverage report
forge coverageFor detailed deployment instructions, see:
- π Full Deployment Guide - Complete walkthrough
- β‘ Quick Start - Fast deployment in 5 steps
# Configure environment
cp .env.example .env
source .env
# Deploy to testnet
forge script script/Deploy.s.sol --rpc-url $SEPOLIA_RPC_URL --broadcast --verifySee docs/DEPLOYMENT_GUIDE.md for network-specific instructions.
All contracts have been deployed and verified on the Sepolia testnet.
All contracts have been deployed and verified on the Sepolia testnet:
0xe3A0A6F0B0925a535f7c83fBe680C74E096a8500
β‘οΈ https://sepolia.etherscan.io/address/0xe3A0A6F0B0925a535f7c83fBe680C74E096a8500
0x9107fc30F33811509Ed111d2fD7fCa732d5503E5
β‘οΈ https://sepolia.etherscan.io/address/0x9107fc30F33811509Ed111d2fD7fCa732d5503E5
0x017b449Ccc3D1Cc3A1aE756627bc318092b298FB
β‘οΈ https://sepolia.etherscan.io/address/0x017b449Ccc3D1Cc3A1aE756627bc318092b298FB
- Network: Sepolia Testnet (Chain ID: 11155111)
- Deployer:
0xd0D211cCEF07598946bB0dF5ECee0bF75cAF3ECC - Platform Fee: 2.5% (250 basis points)
- Fee Recipient:
0xd0D211cCEF07598946bB0dF5ECee0bF75cAF3ECC - Deployment Date: December 2, 2024
- Total Gas Used: 4,772,948 gas
- Total Cost: 0.000004773 ETH (~$0.009 USD)
- Status: β Verified on Etherscan
- Visit the NFTMarketplace on Etherscan
- Connect your wallet
- Call
listNFT
- Visit the AuctionHouse on Etherscan
- Connect your wallet
- Call
createAuction
- Visit the OffersManager on Etherscan
- Connect your wallet
- Call
makeOffer(send ETH asmsg.value)
Coming soon after final security audit.
MAINNET_RPC_URL=
SEPOLIA_RPC_URL=
ETHERSCAN_API_KEY=
PRIVATE_KEY=
FEE_RECIPIENT=0x...
PLATFORM_FEE=250 # 2.5%
- β Fixed price listings
- β English auctions
- β Offers system
- β Royalty + fee architecture
- β Comprehensive test suite (140 tests)
- β Gas optimization
- β Production-ready security patterns
- Batch listings
- Dutch auctions
- ERC-1155 support
- Collection verification
- Signature-based listings
- Subgraph indexing
- Frontend SDK
- API documentation
- Audit completion
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass:
forge test - Submit a pull request
- All new features must include unit tests
- Complex flows should have E2E tests
- Maintain 100% test pass rate
- Gas regressions should be justified
- E2E Testing Guide - Comprehensive testing patterns
- Quick Reference - Common commands
- Foundry Book - Foundry documentation
MIT
- ERC-721 + ERC-2981 standards
- OpenZeppelin contracts
- Foundry framework
- Trail of Bits security patterns
Enricrypto β GitHub
Project Link: https://github.com/Enricrypto/nft-marketplace
# Clone and setup
git clone https://github.com/Enricrypto/nft-marketplace.git
cd nft-marketplace
forge install
# Build
forge build
# Test
forge test # All tests
forge test --match-path "test/e2e/*.sol" -vv # E2E tests with logs
forge test --gas-report # With gas report
# Deploy locally
anvil # In another terminal
forge script script/Deploy.s.sol --rpc-url http://localhost:8545 --broadcastStatus: Production-ready β’ Fully tested β’ Gas-optimized β’ Security-focused