Course: ISE 2.2 Ethical Hacking and Security — Blockchain Technologies and Applications Blockchain: Ethereum Sepolia Testnet Token: EventTicket (TKT) — ERC-20, 0 decimals, 1 token = 1 ticket Ticket price: 0.01 SETH
A Web3 Distributed Application (DApp) that implements an event ticketing system on the Ethereum Sepolia testnet. Tickets are ERC-20 tokens (EventTicket / TKT). Users purchase tickets using Sepolia ETH (SETH) and can return them for a full refund at any time.
BlockchainTicketingDapp/
├── contracts/
│ └── TicketToken.sol ← ERC-20 + Ownable + ReentrancyGuard
├── scripts/
│ └── deploy.js ← deploys to Sepolia, auto-writes config.js
├── test/
│ └── TicketToken.test.js ← 25 Hardhat/Chai tests
├── frontend/
│ ├── index.html ← landing page
│ ├── wallet.html ← create + download ethereum wallet
│ ├── balance.html ← balance check (3 roles)
│ ├── purchase.html ← buy tickets with MetaMask
│ ├── transfer.html ← return tickets, receive SETH refund
│ ├── css/style.css ← shared styles
│ └── js/
│ ├── config.js ← CONTRACT_ADDRESS + ABI (auto-generated by deploy)
│ ├── wallet.js
│ ├── balance.js
│ ├── purchase.js
│ └── transfer.js
├── hardhat.config.js
├── package.json
└── .env ← private key + RPC URL (never commit this)
TicketToken inherits from three OpenZeppelin contracts:
| Inheritance | Purpose |
|---|---|
ERC20 |
Full standard token interface — transfer, approve, transferFrom, balanceOf, etc. |
Ownable |
Restricts withdraw() to the deployer (venue operator) |
ReentrancyGuard |
Blocks reentrancy attacks on buyTickets and returnTickets, both of which transfer ETH |
All tickets are minted to address(this) at deployment — the contract itself is the vendor. Buyers purchase from the contract; returned tickets go back to the contract.
Custom functions beyond ERC-20:
| Function | Visibility | Purpose |
|---|---|---|
buyTickets(uint256 amount) |
external payable | buy tickets, pay ticketPrice * amount SETH |
returnTickets(uint256 amount) |
external | return tickets, receive SETH refund |
withdraw() |
external onlyOwner | venue operator pulls all collected SETH |
ticketsAvailable() |
view | how many tickets remain unsold |
ticketsSold() |
view | how many tickets have been purchased |
isValidTicketHolder(address) |
view | returns true if address holds ≥ 1 ticket |
- Technology: plain HTML + CSS + JavaScript (no framework)
- Web3 library: Web3.js v1.10.4 (loaded via CDN, same library used in course examples)
- Wallet interaction: MetaMask (
window.ethereum) for all signing operations - Read-only calls: public Sepolia RPC (
https://rpc.sepolia.org) — no wallet required for balance checks or doorman lookups - Styling: Nunito font (Google Fonts), pastel pink/lavender palette
Before you start, make sure you have:
- Node.js v18 or v20 (v23 works with a warning — run
node -vto check) - npm (comes with Node)
- VS Code with the Live Server extension installed (by Ritwick Dey)
- MetaMask browser extension installed and set up
- Three Ethereum wallets in MetaMask labelled: Venue Operator, Attendee, Doorman
- Sepolia ETH in all three wallets (free from sepoliafaucet.com)
# 1. clone the repo
git clone <your-repo-url>
cd BlockchainTicketingDapp
# 2. install dependencies
npm install
# 3. verify tests pass (should show 25 passing)
npx hardhat testCreate a .env file in the project root (or edit the existing one):
PRIVATE_KEY=your64hexcharacterprivatekeyhere
SEPOLIA_RPC_URL=https://rpc.sepolia.org
PRIVATE_KEYis the private key for your Venue Operator / deployer wallet — the one that will own the contract. Do NOT include the0xprefix. Never commit this file.
npx hardhat run scripts/deploy.js --network sepoliaExpected output:
deploying with account: 0xYOUR_ADDRESS
account balance: 0.1 ETH
--- deployment complete ---
contract address: 0xABCDEF...
deployment tx hash: 0x123456...
etherscan link: https://sepolia.etherscan.io/address/0xABCDEF...
config.js written to frontend/js/config.js
The deploy script automatically updates frontend/js/config.js with the deployed contract address and ABI. You do not need to edit config.js manually after running this.
Save the contract address and deployment tx hash — you need them for your project report.
- Open the project folder in VS Code
- Right-click
frontend/index.html - Select "Open with Live Server"
- Your browser opens at
http://127.0.0.1:5500/frontend/index.html
The frontend will not work correctly if opened as a
file://URL. You must use Live Server.
| Page | URL | How to use |
|---|---|---|
| Home | /frontend/index.html |
Navigation hub |
| Create Wallet | /frontend/wallet.html |
Enter a password → Generate Wallet → Download Keystore |
| Check Balance | /frontend/balance.html |
Select a role tab (Attendee / Doorman / Venue Operator) |
| Buy Tickets | /frontend/purchase.html |
Connect MetaMask (Sepolia) → enter quantity → Buy Tickets |
| Return Tickets | /frontend/transfer.html |
Connect MetaMask → enter quantity → Return Tickets |
- Open MetaMask → click the network dropdown → select Sepolia Test Network (if Sepolia doesn't appear: Settings → Advanced → Show test networks → ON)
- Import your three test wallets using their private keys (Account → Import Account)
- Label them:
Venue Operator,Attendee,Doorman
npx hardhat testAll 25 tests should pass:
TicketToken
Deployment (7 tests)
buyTickets (6 tests)
returnTickets (4 tests)
withdraw (3 tests)
ERC-20 standard (2 tests)
isValidTicketHolder (3 tests)
25 passing
Run this after deployment to verify everything works on the real network:
- Deploy contract → record address + tx hash
- Venue Operator tab on balance page → confirm 0 sold, 100 available, 0 SETH
- Switch MetaMask to Attendee wallet
- Buy 1 ticket on purchase page → confirm in MetaMask → record tx hash
- Attendee tab on balance page → confirm TKT = 1
- Doorman tab → enter Attendee address → confirm VALID
- Venue Operator tab → confirm 1 sold, 99 available, 0.01 SETH collected
- Return 1 ticket on transfer page → confirm in MetaMask → record tx hash
- Doorman tab → Attendee address → confirm NO VALID TICKET
- Attendee tab → confirm TKT = 0, SETH refunded
| Role | Page | How They Interact |
|---|---|---|
| Event Attendee | balance.html (Attendee tab), purchase.html, transfer.html | Connects MetaMask to check their own balances, buy and return tickets |
| Doorman | balance.html (Doorman tab) | Enters any wallet address to verify ticket validity — read-only, no wallet required |
| Venue Operator | balance.html (Venue Operator tab) | Views live distribution stats (sold, available, SETH collected) — read-only |
Before zipping for Brightspace:
-
npx hardhat test→ 25 passing -
frontend/js/config.jshas the real deployed contract address - All Sepolia tx hashes are recorded in the report
-
.envis NOT in the zip -
node_modules/,artifacts/,cache/are NOT in the zip - Report PDF is included
- AI usage statement is included
- Peer review reflection (200 words) is included
Files to include in the zip:
contracts/TicketToken.sol
scripts/deploy.js
test/TicketToken.test.js
hardhat.config.js
package.json
frontend/index.html
frontend/wallet.html
frontend/balance.html
frontend/purchase.html
frontend/transfer.html
frontend/css/style.css
frontend/js/config.js
frontend/js/wallet.js
frontend/js/balance.js
frontend/js/purchase.js
frontend/js/transfer.js
README.md
[your report PDF]
[AI usage statement]
[peer review reflection]
| Resource | Link |
|---|---|
| Sepolia Etherscan | https://sepolia.etherscan.io |
| Sepolia Faucet | https://sepoliafaucet.com |
| Backup Faucet | https://faucet.quicknode.com/ethereum/sepolia |
| OpenZeppelin ERC20 Docs | https://docs.openzeppelin.com/contracts/5.x/erc20 |
| Your Contract (fill in) | https://sepolia.etherscan.io/address/CONTRACT_ADDRESS |