A robust and secure NFT marketplace implementation supporting ERC721, ERC1155, and ERC6909 tokens with multi-currency support and optional curation controls.
- Multi-Token Support: Compatible with ERC721, ERC1155, and ERC6909 NFTs
- Multi-Currency: Support for ETH and any ERC20 token as payment method
- Bidding System: Advanced bidding functionality with customizable duration
- Optional Curation: Configurable gatekeeping system for curated marketplace experiences
- Marketplace Operations:
- List NFTs for sale
- Place bids with custom timeouts
- Accept bids
- Cancel listings
- Cancel bids (with configurable cancellation fees)
- Admin Controls:
- Currency whitelist management
- Bid duration settings
- Cancellation fee configuration
- Curation system toggle and validator management
The marketplace is built with a modular architecture consisting of:
- Core: Main marketplace functionality with unified multi-token support
- Storage: State variables and data structures
- Admin: Privileged operations and configurations including curation controls
- Views: Read-only functions for querying market state
- Libraries: Reusable utilities for token handling and payments
- Curation: Optional validation layer for marketplace access control
This project uses Foundry, a fast and flexible Ethereum development environment.
- Foundry
- Solidity ^0.8.27
- Clone the repository:
git clone <repository-url>
cd <repository-name>- Install dependencies:
forge install- Build the project:
forge build --via-irRun the test suite:
forge test --via-irRun tests with gas reporting:
forge test --via-ir --gas-reportFormat your Solidity code:
forge fmt- Set up your environment variables in a .env based on .env.example:
cp .env.example .env- (Optional) Fork network with Anvil
source .env &&
anvil --fork-url $ONCHAIN_RPC_URL --fork-block-number 10530428 --accounts 10 --balance 1000 --chain-id $OFFCHAIN_CHAIN_ID --block-time 3- Deploy contracts to your chosen network:
forge script script/MarketplaceDeploy.s.sol:MarketplaceDeployScript \
--rpc-url $OFFCHAIN_RPC_URL \
--private-key $PRIVATE_KEY \
--broadcast
--legacyforge script script/FactoryDeploy.s.sol:FactoryDeployScript \
--rpc-url $OFFCHAIN_RPC_URL \
--private-key $PRIVATE_KEY \
--broadcast
--legacyAnd if you'd like to deploy and verify the smart contracts it should look like:
source .env &&
forge script script/FactoryDeploy.s.sol:FactoryDeployScript \
--rpc-url $RPC_URL \
--private-key $PRIVATE_KEY \
--broadcast \
--legacy \
--verify \
--verifier blockscout \
--verifier-url $EXPLORER Note: --legacy IS IMPORTANT on certain chains Otherwise deployment fails.
- Off chain Playground (Create NFTs, Bid, buy, sell ...)
Create some 721
source .env &&
forge script script/offChainPlayground/NFTFactory.s.sol:Create721 \
--rpc-url $OFFCHAIN_RPC_URL \
--broadcastCreate some 1155
source .env &&
forge script script/offChainPlayground/NFTFactory.s.sol:Create1155 \
--rpc-url $OFFCHAIN_RPC_URL \
--broadcastCreate some 6909
source .env &&
forge script script/offChainPlayground/NFTFactory.s.sol:Create6909 \
--rpc-url $OFFCHAIN_RPC_URL \
--broadcast...
- Reentrancy protection
- Access control for admin functions
- Optional curation system for marketplace access control
- Fee handling in basis points for precision
- Support for safe token transfers
- Custom durations for bids
- Configurable cancellation fees
// List an NFT
createListing(tokenAddress, tokenId, amount, price, currency)
// Accept a bid
acceptBid(tokenAddress, tokenId, tokenAmount)
// Cancel a listing
cancelListing(listingId)// Place a bid
placeBid(tokenAddress, tokenId, tokenAmount, currency, amount, customDuration)
// Buy a listed NFT
buyListing(listingId)
// Cancel a bid
cancelBid(tokenAddress, tokenId, tokenAmount)// Set accepted currencies
setAcceptedCurrencies(currencies[], accepted[])
// Set bid duration
setBidDuration(newDuration)
// Set cancellation fee
setCancellationFeePercentage(newPercentage)
// Configure curation system
setCurationEnabled(enabled)
setCurationValidator(validatorAddress)The marketplace includes an optional curation system that allows administrators to control which NFT collections can be listed and bid upon. This feature enables both permissionless and curated marketplace experiences.
- Toggle Control: Enable or disable curation system at any time
- Validator Contracts: Pluggable validation logic through external contracts
- Dynamic Approval: Real-time approval/disapproval of collections
- Granular Control: Per-collection approval management
When enabled, the curation system validates all listing and bidding operations against an external validator contract. This allows for flexible curation policies while maintaining marketplace core functionality.