Event Ticketing NFT Platform Development
The classical ticket market suffers from two systemic problems: scalpers buy quotas via bots and resell with 300-500% markup, and organizers lose control of secondary circulation after initial sale. NFT tickets solve both problems architecturally — through on-chain logic, not through CRM tightening.
Ticket Smart Contract Architecture
Contract built on ERC-721 with extensions that override standard transferFrom. Key mechanics:
Royalties on secondary sales implemented via ERC-2981 (royaltyInfo). Organizer gets percentage of each resale automatically — no middleman. Supported by OpenSea, Blur, LooksRare, and most aggregators.
Whitelist and purchase limits — via Merkle Tree for gas-efficient verification. Instead of storing address list on-chain, store only root hash. User provides proof, contract verifies in O(log n) for few thousand gas.
Soulbound mode — ticket becomes non-transferable after validation if needed. Implemented via override _beforeTokenTransfer with isUsed flag check. Kills secondary market for specific categories (e.g., personalized VIP).
Dynamic URI — metadata changes based on state: before event, after validation, after use. Via tokenURI checking block.timestamp against eventDate and isUsed. Nice for collectible "post-match" ticket state.
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId,
uint256 batchSize
) internal override {
require(!usedTickets[tokenId], "Ticket already validated");
if (transferRestricted[tokenId]) {
require(from == address(0) || to == address(0), "Non-transferable");
}
super._beforeTokenTransfer(from, to, tokenId, batchSize);
}
Validation at Entry
Technically most responsible part. Two variants:
On-chain validation — organizer calls validateTicket(tokenId) via mobile app with connected wallet. Transaction records isUsed = true, reentry impossible. Downside — latency and gas cost per entry. On Polygon/Arbitrum acceptable (~$0.01), on Ethereum mainnet — no.
Off-chain with signature — standard pattern for high throughput. Ticket owner signs message {tokenId, eventId, timestamp} with wallet (EIP-712 typed data). Validator at entry checks signature via ecrecover and verifies ownerOf(tokenId) via read-only RPC call. If signature valid and token belongs to signer — let in. "Used" recorded off-chain in organizer database; on-chain write optional, batched after event.
For festivals with thousands simultaneous entries use second variant with local state cache synced every 30 seconds via WebSocket subscription to Transfer events.
Frontend and User Flow
User buys via standard dApp:
- Wallet connection (wagmi + ConnectKit / RainbowKit)
- Category selection and quantity
- If presale — whitelist verification via Merkle proof
- Payment in ETH/MATIC/USDC via
mint() - Ticket appears in wallet as NFT, displays in interface with QR code (EIP-712 signed message)
For organizers — separate management panel: event setup, on-chain sales analytics export, quota and whitelist management.
Secondary Marketplace Integration
Standard integration with OpenSea via properly filled contractURI (collection-level metadata) and tokenURI (per-token metadata). Operator support via setApprovalForAll — standard. If need to restrict platforms, implement operator filter (OpenSea Operator Filter Registry pattern, though enforcement weakened).
For own secondary market — mini-marketplace on Seaport (open-source OpenSea protocol): listing via fulfillBasicOrder, atomic token and payment swap in one transaction, royalties via ERC-2981.
What's Included in Development
- Smart contract ERC-721 with extensions (royalties, whitelist, soulbound mode, dynamic metadata)
- Testnet + mainnet deployment (Ethereum, Polygon, or other EVM chain by choice)
- Frontend dApp for buyers (React + wagmi)
- Management panel for organizers
- Mobile app or web scanner for entry validation
- IPFS integration (Pinata/NFT.Storage) for metadata and images
- Contract audit (Slither + manual review)
Stack varies by scale — from single-page dApp for intimate event to full SaaS with multi-organizer mode.







