The architecture is split into four Solidity contracts: CreditsToken (ERC-20 with 18 decimals, symbol CEC) and TicketNFT (ERC-721) are both platform-minted; only the registered EventPlatform can mint or burn for CreditsToken, and only the platform can mint/invalidate/mark used/mark refunded for TicketNFT. TicketNFT enforces non-transferability by overriding approve, setApprovalForAll, transferFrom, and safeTransferFrom to revert with a NonTransferable custom error.
TreasuryVault maintains per-event accounting using paidCreditsByEvent and refundCreditsByEvent mappings; writes are restricted so only EventPlatform updates these records.
EventPlatform acts as the coordinator: admin approves organizers; organizers create events and configure ticket tiers (tier label, CEC price, max supply), set per-event wallet caps, and transition event lifecycle states (Draft → OnSale → SoldOut, with additional cancellation/completion states referenced). Students buy credits by sending ETH to EventPlatform.buyCreditsWithEth() (mints CEC at ethToCreditsRate), then follow a two-transaction ERC-20 approval pattern—approve allowance to EventPlatform and call obtainTicketWithCredits to receive a TicketNFT.
On the frontend, the repository provides a React + Vite SPA using ethers.js v6 and Bulma. The SPA is role-aware and detects admin/organizer/student roles by reading eventPlatform.admin() and eventPlatform.approvedOrganizers(account) on wallet connection/network changes. The SPA uses a local deployment script (deploy-spa-local.ts) to deploy contracts and write deployed addresses plus parsed ABIs into spa/src/config/contract-info.json so the UI has a single source of truth without hardcoding addresses. The user flows include credit purchase, ERC-20 allowance checking/approval before ticket purchase, organizer studio actions (create event, add tiers, set wallet cap, start sales), an admin console (approve organizers, update exchange rate), a wallet dashboard, and a ticket inventory. Tests (Mocha/Chai) cover contract components, access control rejections, state transitions, and misuse scenarios for non-transferability, plus an end-to-end scaffold.