Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 147 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

**LottoLink** is a unified lottery infrastructure built on:
- **Flare Network (Coston2 testnet)** - Data Truth Layer for provably fair draws using Secure RNG, FTSO price feeds, and FDC for external lottery attestation
- **Plasma Network** - Money Movement Layer for instant zero-fee USDT payouts via EIP-3009 gasless transfers

## Architecture

### Multi-Package Monorepo Structure
```
lottolink/
├── contracts/ # Solidity smart contracts (Hardhat)
├── backend/ # Node.js + Express API with blockchain event listeners
├── frontend/ # Next.js 14 + Tailwind UI
└── package.json # Root scripts for unified commands
```

### Contract Architecture (contracts/flare/)
The contracts are split across two networks:

**Flare Contracts (Coston2 testnet)**:
- `DrawManager.sol` - Manages lottery draws using Flare's Secure RNG (`RandomNumberV2` at `0x97702e350CaEda540935d92aAf213307e9069784`)
- `PayoutCalculator.sol` - Calculates winnings and authorizes payouts
- `LotteryRegistry.sol` - Registry of available lotteries
- `ResultAttestor.sol` - Uses FDC JsonApi to attest external Web2 lottery results
- Interfaces: `IRandomNumberV2.sol`, `IFtsoV2.sol` (for USD↔USDT price feeds), `IFdcVerification.sol`

**Plasma Contracts**:
- `LottoEscrow.sol` - Handles USDT deposits and gasless withdrawals using EIP-3009

Hardhat config uses `viaIR: true` optimizer setting for Solidity 0.8.25. Sources are in `./flare` directory (not standard `./contracts`).

### Backend Architecture (backend/src/)
Express API with three core components:
- `index.ts` - Main server with REST endpoints and in-memory data store (use DB in production)
- `listeners/` - Blockchain event listeners for Flare (draws, payouts) and Plasma (ticket purchases)
- `services/plasma.ts` - Handles gasless USDT payout execution via EIP-3009

The backend listens to smart contract events and coordinates cross-chain actions (Flare draws trigger Plasma payouts).

### Frontend Architecture (frontend/app/)
Next.js 14 App Router structure:
- Uses wagmi v2 + viem v2 for Web3 interactions
- Tailwind CSS for styling
- React Query (`@tanstack/react-query`) for data fetching

## Development Commands

### From Root Directory
```bash
npm run install:all # Install all dependencies across packages
npm run dev # Run backend + frontend concurrently
npm run build # Compile contracts, build backend & frontend
npm run contracts:compile # Compile Solidity contracts
npm run contracts:test # Run Hardhat tests
npm run contracts:deploy:flare # Deploy to Flare Coston2
npm run contracts:deploy:plasma # Deploy to Plasma
```

### Individual Packages
```bash
# Contracts (from ./contracts)
npm run compile # Compile with Hardhat
npm test # Run all tests
npx hardhat test test/FileName.ts # Run specific test file
npx hardhat run scripts/deploy-flare.ts --network coston2

# Backend (from ./backend)
npm run dev # Run with ts-node
npm run build # Compile TypeScript
npm start # Run compiled code

# Frontend (from ./frontend)
npm run dev # Next.js dev server on port 3000
npm run build # Production build
npm start # Serve production build
```

## Environment Variables

### Backend (.env in backend/)
```bash
DRAW_MANAGER_ADDRESS # Flare DrawManager contract address
PAYOUT_CALC_ADDRESS # PayoutCalculator contract address
ESCROW_ADDRESS # Plasma LottoEscrow contract address
ESCROW_PRIVATE_KEY # Private key for signing gasless payouts
USDT_ADDRESS # Plasma USDT token (default: 0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb)
PORT # API port (default: 3001)
```

### Contracts (.env in contracts/)
```bash
PRIVATE_KEY # Deployment account private key
PLASMA_RPC_URL # Plasma RPC endpoint (default: https://rpc.plasma.to)
```

## Network Configuration

| Network | Chain ID | RPC URL |
|---------|----------|---------|
| Flare Coston2 (testnet) | 114 | https://coston2-api.flare.network/ext/C/rpc |
| Plasma | — | https://rpc.plasma.to |

**Important Flare Contracts**:
- RandomNumberV2: `0x97702e350CaEda540935d92aAf213307e9069784`
- ContractRegistry: `0xaD67FE66660Fb8dFE9d6b1b4240d8650e30F6019`

## Technology Stack

| Component | Stack |
|-----------|-------|
| Contracts | Solidity 0.8.25, Hardhat, OpenZeppelin 5.0, TypeChain |
| Backend | Node.js, Express, TypeScript 5.3, ethers.js v6 |
| Frontend | Next.js 14, React 18, wagmi v2, viem v2, Tailwind 3.4 |

All packages use TypeScript with ES2022 target and strict mode enabled.

## Docker & CI/CD

- `docker-compose.yml` orchestrates frontend (port 3000) and backend (port 4000)
- Individual Dockerfiles in `./backend` and `./frontend`
- GitHub Actions workflow (`.github/workflows/workflow.yml`) builds Docker images on push/PR to main branch

## Key Integration Points

### Flare-Specific Features
1. **Secure RNG**: DrawManager requests random numbers from `RandomNumberV2` with `isSecureRandom: true` flag
2. **FTSO Price Feeds**: USD to USDT conversion at settlement time via `IFtsoV2` interface
3. **FDC JsonApi**: ResultAttestor uses Flare Data Connector to attest external Web2 lottery results

### Cross-Chain Flow
1. User buys ticket on Plasma (USDT deposit to LottoEscrow)
2. LottoEscrow emits event → backend listener records ticket
3. DrawManager on Flare requests RNG and conducts draw
4. PayoutCalculator determines winners → emits PayoutAuthorized event
5. Backend listener executes gasless USDT transfer on Plasma using EIP-3009

## Code Conventions

- Use ethers v6 patterns (not v5): `provider.getBlock()` instead of `provider.getBlockNumber()`
- Prefer `async/await` over raw Promises
- Backend uses in-memory storage - replace with database for production
- Contracts follow OpenZeppelin 5.0 patterns (constructor-based initialization, no initializers unless upgradeable)
Loading