A full-stack Web3 dApp that allows users to mint, purchase, and auction NFTs using ETH or USDC. Chainlink oracles fetch real-time ETH/USD prices. NFT metadata is stored using Pinata (IPFS), and minting/purchasing is restricted to whitelisted users via Merkle trees.
-
Deployed on: https://nft-auction-web3-frontend.onrender.com
-
via CI/CD automation workflows
- Whitelist-based minting and purchasing
- Pay with ETH or USDC (Chainlink price feed for ETH)
- NFT metadata pinned to IPFS via Pinata
- English auction with escrowed bidding and refunds
- Role-based access control (Admin, Sales Manager)
- Full smart contract test suite with Foundry
- Smart Contracts: Solidity (using Foundry)
- Frontend: React.js
- Backend: Express.js
- Oracle: Chainlink ETH/USD
- Storage: Pinata (IPFS)
/src
– NFT and Auction contracts/frontend
– React-based frontend app/server
– Express.js backend for whitelist verification, and future plans to be used to optimize data fetching from blockchain/script
– Deployment scripts (for local and testnet)
Frontend:
cd frontend
npm install
Backend:
cd backend
npm install
Contracts:
forge install
git submodule sync
git submodule update --init --recursive
- Use Foundry’s
anvil
to spin up a local chain. - Run
DeployLocally
script to deploy contracts with mocked Chainlink and USDC. - Frontend and backend will connect to this local setup.
- Inherits: OpenZeppelin ERC721 + RoleManager + MerkleWhitelist + PriceConsumer
safeMint()
: Mint NFT if whitelistedpurchaseNFT()
: Purchase minted NFT using ETH or USDC
createAuction()
: List an NFT for auctionplaceBid()
: Place bid with escrowwithdraw()
: Withdraw bids after losingendAuction()
: End auction and transfer NFT
Run all Foundry tests:
forge test -vvv
Generate coverage (ignoring script files):
forge coverage --no-match-coverage script
- Smart contracts deployed to Sepolia using Forge scripts
- Frontend hosted on Render
- https://dev.to/jamiescript/design-patterns-in-solidity-1i28
- https://www.cyfrin.io/blog/what-is-a-reentrancy-attack-solidity-smart-contracts
- https://docs.ipfs.tech/how-to/best-practices-for-nft-data/
- forge script .... Deploy the NFT contract
- node script/CopyABI.js to update the abi contract in the frontend
- update the .env's with the new contract address (frontend/foundry)
- mint NFT's again since they are all losted
- (0): I use for deployment (DEFAULT_ADMIN) -> Account 2 in metamask
- (9): I use for WhitelistManager -> Account 4 in metamask
- Backend was hashing addresses with just keccak256(address) — a plain string hash — while smart contract likely expected keccak256(abi.encodePacked(address)) like Solidity does. That mismatch is why the proofs were invalid (resulting in false in cast call).
- solidityPackedKeccak256(...) = mimics abi.encodePacked + keccak256 from Solidity
- If the hash of your leaf in JS doesn’t match the one Solidity expects, the Merkle proof won’t validate — ever.