πŸ— System Architecture

Overview

The DEX Dashboard is a full-stack Web3 monorepo with smart contracts on the backend (Solidity + Foundry) and a React frontend (Next.js 16 + wagmi). It simulates a decentralized exchange where users can mint mock tokens, trade them on a fixed-ratio DEX, and track market data from CoinGecko.

Monorepo Structure

DEX/
β”œβ”€β”€ contracts/                     # Foundry smart contracts
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ MockERC20.sol          # ERC20 token (mETH, mBTC, mUSDC)
β”‚   β”‚   β”œβ”€β”€ Faucet.sol             # Time-locked token faucet
β”‚   β”‚   └── MockDEX.sol            # Fixed-ratio DEX with 6 swap paths
β”‚   β”œβ”€β”€ test/                      # 182+ Solidity tests
β”‚   β”‚   β”œβ”€β”€ MockERC20.t.sol        # 35 tests
β”‚   β”‚   β”œβ”€β”€ Faucet.t.sol           # 51 tests
β”‚   β”‚   β”œβ”€β”€ MockDEX.t.sol          # 96 tests (fuzz + invariant)
β”‚   β”‚   └── MockDEX.invariant.t.sol # Invariant tests
β”‚   β”œβ”€β”€ script/
β”‚   β”‚   └── Deploy.s.sol           # Deployment script
β”‚   β”œβ”€β”€ .env                       # Sepolia RPC URL + Etherscan API key
β”‚   └── foundry.toml               # Foundry configuration
β”œβ”€β”€ frontend/                      # Next.js 16 application
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ app/                   # Pages (Home, Faucet, Swap, Analytics)
β”‚   β”‚   β”œβ”€β”€ components/            # UI components (shadcn/ui, custom)
β”‚   β”‚   β”œβ”€β”€ hooks/                 # Custom React hooks
β”‚   β”‚   β”œβ”€β”€ lib/                   # Constants, ABIs, utilities
β”‚   β”‚   └── providers.tsx          # Web3 provider
β”‚   └── tests/                     # Vitest frontend tests
β”œβ”€β”€ docs/                          # GitHub Pages documentation
β”‚   β”œβ”€β”€ index.html                 # Documentation home
β”‚   β”œβ”€β”€ user-guide/                # User-facing guides
β”‚   β”œβ”€β”€ developer-guide/           # Developer-facing guides
β”‚   β”œβ”€β”€ qa.html                    # FAQ page with search
β”‚   └── assets/                    # CSS, JS
β”œβ”€β”€ scripts/
β”‚   └── update-addresses.sh        # Extracts deployed addresses β†’ constants.ts
β”œβ”€β”€ images/                        # README screenshots
└── Makefile                       # Build automation (install, build, test, deploy)

Smart Contract Architecture

Three contracts are deployed together. The deployment script handles the inter-contract wiring automatically.

Contract Dependencies

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  MockERC20  │────▢│      Faucet       β”‚
β”‚  (mETH)     β”‚     β”‚                   β”‚
β”‚             β”‚     β”‚  - mints via      β”‚
β”‚  MockERC20  β”‚     β”‚    setFaucet()    β”‚
β”‚  (mBTC)     β”‚     β”‚  - 24h cooldown   β”‚
β”‚             β”‚     β”‚  - 3 tokens       β”‚
β”‚  MockERC20  β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚  (mUSDC)    β”‚
β”‚             β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚             │────▢│     MockDEX       β”‚
β”‚             β”‚     β”‚                   β”‚
β”‚             β”‚     β”‚  - 3 reserves     β”‚
β”‚             β”‚     β”‚  - 2 swap rates   β”‚
β”‚             β”‚     β”‚  - 6 swap paths   β”‚
β”‚             β”‚     β”‚  - SafeERC20      β”‚
β”‚             β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Deployment Flow

  1. Step 1: Deploy 3 MockERC20 instances (mETH, mBTC, mUSDC) β€” each gets a placeholder faucet address
  2. Step 2: Deploy Faucet contract β€” receives mETH, mBTC, mUSDC addresses; becomes their real faucet via setFaucet()
  3. Step 3: Deploy MockDEX contract β€” receives all 3 token addresses plus initial swap rates (ethRate=1700, btcRate=40000)
  4. Step 4: Add initial liquidity β€” owner deposits tokens into MockDEX reserves
  5. Step 5: Update Faucet addresses β€” tokens' faucet is set to the real Faucet contract (after minting initial liquidity)

Data Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    Connect Wallet     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  User    │──────────────────────▢│   MetaMask   β”‚
β”‚ (Browser)β”‚                       β”‚   (Wallet)   β”‚
β”‚          │◀──────────────────────│              β”‚
β”‚          β”‚    Sign Txn / Read    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                              β”‚
     β”‚                                    β”‚
     β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
     β”‚  β”‚  wagmi / viem                   β”‚
     β”‚  β”‚                                 β”‚
     β”‚  β”œβ”€ useAccount()                   β”‚
     β”‚  β”œβ”€ useReadContract()   ◀─── On-chain reads
     β”‚  β”œβ”€ useWriteContract()  ───▢ On-chain writes
     β”‚  └─ useWaitForTxnReceipt()
     β”‚
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚    Next.js 16 Frontend      β”‚
β”‚                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Pages (App Router)   β”‚  β”‚
β”‚  β”‚  β”œβ”€ Home (/)          β”‚  β”‚
β”‚  β”‚  β”œβ”€ Faucet /faucet    β”‚  β”‚
β”‚  β”‚  β”œβ”€ Swap /swap        β”‚  β”‚
β”‚  β”‚  └─ Analytics /analytics β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Custom Hooks         β”‚  β”‚
β”‚  β”‚  β”œβ”€ use-dex.ts        β”‚  β”‚
β”‚  β”‚  β”œβ”€ use-faucet.ts     β”‚  β”‚
β”‚  β”‚  β”œβ”€ use-token-balancesβ”‚  β”‚
β”‚  β”‚  β”œβ”€ use-analytics.ts  β”‚  β”‚
β”‚  β”‚  └─ use-market-data.ts│──▢ CoinGecko API
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Read Path (Viewing Data)

  1. User connects wallet via wagmi + MetaMask connector
  2. Frontend calls useReadContract to fetch on-chain state (balances, reserves, rates, cooldowns)
  3. Market data is fetched from CoinGecko API for candlestick charts and token prices
  4. Analytics page combines on-chain DEX data with market data and simulated trade history

Write Path (Transactions)

  1. User fills a form (e.g., swap amount on Swap page)
  2. Frontend calls useWriteContract with the encoded function call
  3. wagmi prompts the user to sign/confirm in MetaMask
  4. Transaction is submitted to the network (Anvil or Sepolia)
  5. Frontend waits for receipt via useWaitForTransactionReceipt
  6. On success, queries are invalidated and refetched automatically

Frontend Component Architecture

layout/                components/                hooks/
β”œβ”€β”€ header.tsx         β”œβ”€β”€ ui/ (13 primitives)    β”œβ”€β”€ use-dex.ts
β”œβ”€β”€ footer.tsx         β”‚   β”œβ”€β”€ button.tsx         β”œβ”€β”€ use-faucet.ts
└── wallet-button.tsx  β”‚   β”œβ”€β”€ card.tsx           β”œβ”€β”€ use-token-balances.ts
                       β”‚   β”œβ”€β”€ dialog.tsx         β”œβ”€β”€ use-analytics.ts
pages/                 β”‚   β”œβ”€β”€ tabs.tsx           └── use-market-data.ts
β”œβ”€β”€ page.tsx (Home)    β”‚   └── ...
β”œβ”€β”€ faucet/page.tsx    β”œβ”€β”€ home/                  lib/
β”œβ”€β”€ swap/page.tsx      β”‚   β”œβ”€β”€ stats-counters.tsx β”œβ”€β”€ constants.ts
└── analytics/         β”‚   └── animated-section   β”œβ”€β”€ wagmi.ts
    β”œβ”€β”€ page.tsx       β”œβ”€β”€ faucet/                β”œβ”€β”€ dex-abi.ts
    └── client.tsx     β”‚   └── claim-card.tsx     β”œβ”€β”€ faucet-abi.ts
                       β”œβ”€β”€ swap/                  β”œβ”€β”€ utils.ts
                       β”‚   β”œβ”€β”€ swap-card.tsx      └── market-data.ts
                       β”‚   └── settings.tsx
                       β”œβ”€β”€ analytics/
                       β”‚   β”œβ”€β”€ stats-cards.tsx
                       β”‚   β”œβ”€β”€ token-table.tsx
                       β”‚   β”œβ”€β”€ trade-history.tsx
                       β”‚   └── portfolio.tsx
                       └── charts/
                           └── candlestick.tsx

State Management

Design Patterns

Key Design Decisions

Decision Rationale
Foundry (vs Hardhat) Native Solidity testing with fuzz/invariant support, fast compilation in Rust, and built-in linting
Fixed-ratio DEX (vs AMM) Educational simplicity β€” users understand rate-based swaps without AMM complexity (xβ‹…y=k). Rates are owner-set constants.
3-reserve model (vs 2-token pools) Supports cross-rate swaps (mETH↔mBTC) by routing through mUSDC internally, demonstrating a real DeFi pattern
wagmi + viem Modern, type-safe React hooks for wallet connection and contract interaction. Replaces ethers.js v5.
shadcn/ui + Tailwind Accessible, customizable Radix UI primitives that compose well. Full design control without a bloated component library.
Raw HTML docs (GitHub Pages) Zero build step, no framework dependencies. The docs are plain HTML/CSS/JS that deploy instantly via GitHub Pages.
--interactives 1 (private key) Forge prompts for the private key interactively at deploy time. No env vars, no plaintext key files.

Testing Overview

The project has 182+ Solidity tests and frontend unit tests:

See the Testing Guide for complete details.