|
| 1 | +# FULA Rewards Program Portal |
| 2 | + |
| 3 | +A decentralized web portal for managing reward programs, members, and FULA token distributions. All data is stored on-chain — no backend or database required. Designed for static hosting on GitHub Pages. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +The Rewards Program system enables organizations to create hierarchical reward programs where FULA tokens can be deposited, distributed to members with optional lock conditions, and withdrawn. The portal is a pure frontend that interacts directly with the `RewardsProgram` smart contract on Base network. |
| 8 | + |
| 9 | +## Role Hierarchy |
| 10 | + |
| 11 | +``` |
| 12 | +Admin |
| 13 | + └── ProgramAdmin |
| 14 | + └── TeamLeader |
| 15 | + └── Client |
| 16 | +``` |
| 17 | + |
| 18 | +- **Admin**: Contract-level administrator. Can create programs, assign ProgramAdmins, and manage all members across all programs. |
| 19 | +- **ProgramAdmin**: Manages a specific program. Can add TeamLeaders and Clients. Assigned by Admin. |
| 20 | +- **TeamLeader**: Can add Clients under themselves. Assigned by ProgramAdmin or Admin. |
| 21 | +- **Client**: End member. Cannot add other members. Assigned by TeamLeader, ProgramAdmin, or Admin. |
| 22 | + |
| 23 | +Each member is identified by a **Member ID** (also called Reward ID), which is unique within each program but can be reused across different programs. |
| 24 | + |
| 25 | +## Programs |
| 26 | + |
| 27 | +Programs are identified by: |
| 28 | +- **Program ID**: Auto-incrementing numeric ID (1, 2, 3, ...) |
| 29 | +- **Program Code**: Short code up to 8 characters (e.g., "SRP", "GTP") |
| 30 | +- **Name** and **Description** |
| 31 | + |
| 32 | +Only Admins can create programs. |
| 33 | + |
| 34 | +## Token Operations |
| 35 | + |
| 36 | +### Deposit |
| 37 | +Members deposit FULA tokens from their wallet into the program's StakingPool vault. Two-step process: |
| 38 | +1. **Approve** the contract to spend FULA tokens |
| 39 | +2. **Deposit** tokens into a specific program |
| 40 | + |
| 41 | +### Transfer to Sub-Member |
| 42 | +Parents can transfer tokens to their sub-members with optional restrictions: |
| 43 | +- **Free transfer** (`locked=false`, `lockTime=0`): Recipient can withdraw immediately |
| 44 | +- **Time-locked** (`locked=false`, `lockTime>0`): Recipient can withdraw after the lock period expires (1-1095 days). Each transfer's lock time is tracked independently. |
| 45 | +- **Permanently locked** (`locked=true`): Recipient cannot withdraw. Can only transfer back to a parent in their hierarchy. |
| 46 | +- Transfers include an optional **note** (max 256 characters) recorded on-chain. |
| 47 | + |
| 48 | +### Transfer to Parent |
| 49 | +Members can transfer tokens back up the hierarchy to any parent in their chain. If no specific parent is specified, tokens go to the direct parent. This is the only way to move permanently locked tokens. |
| 50 | + |
| 51 | +Deduction order: available balance -> expired time-locks -> unexpired time-locks -> permanently locked. |
| 52 | + |
| 53 | +### Withdraw |
| 54 | +Members withdraw available (unlocked) tokens to their wallet. Expired time-locks are automatically resolved during withdrawal. |
| 55 | + |
| 56 | +## Balance Types |
| 57 | + |
| 58 | +Each member's balance in a program has three components: |
| 59 | +- **Withdrawable**: Freely available tokens that can be withdrawn |
| 60 | +- **Permanently Locked**: Tokens that can only be transferred back to parents, never withdrawn |
| 61 | +- **Time-Locked**: Tokens with an expiry date. Become withdrawable after the lock period. Max 50 active time-lock tranches per member per program. |
| 62 | + |
| 63 | +## Pages |
| 64 | + |
| 65 | +### Dashboard (`/`) |
| 66 | +Role-based overview showing total programs, your programs, wallet FULA balance, and current role. Requires wallet connection. |
| 67 | + |
| 68 | +### Programs (`/programs`) |
| 69 | +- **List view**: Table of all programs with ID, code, name, description, and status |
| 70 | +- **Detail view** (`/programs?id=1`): Program details, your balance breakdown, and member table (sub-members if TeamLeader/Client, all members if Admin) |
| 71 | +- **Create Program** (Admin only): Dialog to create a new program with code, name, and description |
| 72 | +- **Add Program Admin** (Admin only): Assign a ProgramAdmin with wallet and member ID |
| 73 | +- **Add Member** (ProgramAdmin/TeamLeader): Add TeamLeaders or Clients |
| 74 | + |
| 75 | +### Members (`/members`) |
| 76 | +Search for members by: |
| 77 | +- **Member ID** + Program ID: Find a specific member's details |
| 78 | +- **Program Code**: Look up a program by its short code |
| 79 | + |
| 80 | +### Tokens (`/tokens`) |
| 81 | +Five-tab interface for token operations: |
| 82 | +1. **Deposit**: Approve and deposit FULA tokens into a program |
| 83 | +2. **Transfer to Sub-Member**: Send tokens to a sub-member with optional lock and note |
| 84 | +3. **Transfer to Parent**: Return tokens to a parent in the hierarchy |
| 85 | +4. **Withdraw**: Withdraw available tokens to your wallet |
| 86 | +5. **History**: Recent transfer records with ID, from/to, amount, lock status, note, and date |
| 87 | + |
| 88 | +### Balance Lookup (`/balance`) |
| 89 | +Public page that does **not require wallet connection** for viewing. Enter a Member ID to see: |
| 90 | +- All programs the member belongs to |
| 91 | +- Their role and parent in each program |
| 92 | +- Balance breakdown (withdrawable, locked, time-locked) per program |
| 93 | +- Status in each program |
| 94 | + |
| 95 | +If the connected wallet matches the member's wallet, action panels appear for deposit, transfer to parent, and withdraw. |
| 96 | + |
| 97 | +Shareable link format: `/balance?member=MEMBER_ID` |
| 98 | + |
| 99 | +## On-Chain Data Notice |
| 100 | + |
| 101 | +All data entered through this portal is stored on the blockchain and is **publicly visible and verifiable**. Users must acknowledge this before submitting any transaction. A disclaimer checkbox is required before: |
| 102 | +- Creating a program |
| 103 | +- Assigning a Program Admin |
| 104 | +- Adding a member |
| 105 | +- Transferring tokens to a sub-member |
| 106 | + |
| 107 | +A persistent footer notice reminds users that all records are permanently on-chain. |
| 108 | + |
| 109 | +## Tech Stack |
| 110 | + |
| 111 | +- **Next.js 15** (Static Export) — no server required |
| 112 | +- **React 19** — UI framework |
| 113 | +- **RainbowKit 2.x** — wallet connection (desktop + mobile) |
| 114 | +- **Wagmi 2.x** + **Viem 2.x** — contract interaction |
| 115 | +- **TanStack React Query** — data fetching and caching |
| 116 | +- **Material UI 6.x** — component library (dark theme) |
| 117 | + |
| 118 | +## Project Structure |
| 119 | + |
| 120 | +``` |
| 121 | +src/ |
| 122 | +├── app/ |
| 123 | +│ ├── layout.tsx Root layout with sidebar nav + header + footer |
| 124 | +│ ├── page.tsx Dashboard |
| 125 | +│ ├── providers.tsx Wagmi, RainbowKit, MUI, QueryClient providers |
| 126 | +│ ├── balance/page.tsx Public member balance lookup |
| 127 | +│ ├── members/page.tsx Member search |
| 128 | +│ ├── programs/page.tsx Program list + detail (via ?id= param) |
| 129 | +│ └── tokens/page.tsx Token operations (deposit, transfer, withdraw) |
| 130 | +├── components/ |
| 131 | +│ ├── common/ |
| 132 | +│ │ └── OnChainDisclaimer.tsx Reusable on-chain data checkbox |
| 133 | +│ └── layout/ |
| 134 | +│ ├── Header.tsx AppBar with wallet connect + role chip |
| 135 | +│ └── Navigation.tsx Sidebar navigation |
| 136 | +├── config/ |
| 137 | +│ ├── chains.ts Supported chains (Base, Base Sepolia, Hardhat) |
| 138 | +│ └── contracts.ts Contract addresses, ABIs, role enums |
| 139 | +├── hooks/ |
| 140 | +│ ├── useRewardsProgram.ts Contract read/write hooks |
| 141 | +│ └── useUserRole.ts Role detection hooks |
| 142 | +└── lib/ |
| 143 | + ├── utils.ts Formatting utilities |
| 144 | + └── wagmi.ts Wagmi configuration |
| 145 | +``` |
| 146 | + |
| 147 | +## Smart Contract |
| 148 | + |
| 149 | +The portal interacts with the `RewardsProgram` smart contract which inherits from `GovernanceModule` (UUPS upgradeable). The contract uses a separate `StakingPool` as the token vault — all FULA tokens are held in the StakingPool while the RewardsProgram manages the accounting ledger. |
| 150 | + |
| 151 | +- **FULA Token**: `0x9e12735d77c72c5C3670636D428f2F3815d8A4cB` (Base) |
| 152 | +- **RewardsProgram**: Set via `NEXT_PUBLIC_REWARDS_PROGRAM_ADDRESS` env var |
| 153 | +- **StakingPool**: Set via `NEXT_PUBLIC_STAKING_POOL_ADDRESS` env var |
| 154 | + |
| 155 | +## Setup |
| 156 | + |
| 157 | +```bash |
| 158 | +# Install dependencies |
| 159 | +npm install |
| 160 | + |
| 161 | +# Set environment variables |
| 162 | +cp .env.local.example .env.local |
| 163 | +# Edit .env.local with your contract addresses and WalletConnect project ID |
| 164 | + |
| 165 | +# Development |
| 166 | +npm run dev |
| 167 | + |
| 168 | +# Build for static hosting |
| 169 | +npm run build |
| 170 | +# Output in out/ directory |
| 171 | +``` |
| 172 | + |
| 173 | +## Environment Variables |
| 174 | + |
| 175 | +| Variable | Description | |
| 176 | +|----------|-------------| |
| 177 | +| `NEXT_PUBLIC_REWARDS_PROGRAM_ADDRESS` | Deployed RewardsProgram contract address | |
| 178 | +| `NEXT_PUBLIC_STAKING_POOL_ADDRESS` | Deployed StakingPool contract address | |
| 179 | +| `NEXT_PUBLIC_FULA_TOKEN_ADDRESS` | FULA token address (defaults to Base mainnet) | |
| 180 | +| `NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID` | WalletConnect project ID for wallet connections | |
| 181 | +| `NEXT_PUBLIC_CHAIN` | Target chain: `base`, `baseSepolia`, or `hardhat` | |
| 182 | + |
| 183 | +## Deployment |
| 184 | + |
| 185 | +### GitHub Pages |
| 186 | + |
| 187 | +The repository includes a GitHub Actions workflow (`.github/workflows/deploy.yml`) that automatically builds and deploys to GitHub Pages on push to `main`. |
| 188 | + |
| 189 | +1. Go to repository Settings > Pages |
| 190 | +2. Set Source to "GitHub Actions" |
| 191 | +3. Push to `main` — the workflow builds and deploys automatically |
| 192 | + |
| 193 | +### Manual Static Hosting |
| 194 | + |
| 195 | +```bash |
| 196 | +npm run build |
| 197 | +# Serve the out/ directory with any static file server |
| 198 | +npx serve out |
| 199 | +``` |
| 200 | + |
| 201 | +## Security Considerations |
| 202 | + |
| 203 | +- All contract interactions require wallet signing — no private keys are stored |
| 204 | +- The portal is read-only without a connected wallet (except the Balance Lookup page) |
| 205 | +- On-chain data disclaimer required before any write transaction |
| 206 | +- No personal or protected information should be entered — all data is publicly visible on the blockchain |
| 207 | +- The contract enforces role-based access control — the portal's UI restrictions are convenience, not security |
0 commit comments