Ethereum-Faucet

Modern Ethereum Faucet

A full rewrite of the original faucet into a modern, abuse-resistant architecture:

Why this rewrite

Legacy faucet implementations (single function + static frontend) are easy to drain with scripted wallets and botnets. Modern public faucets now combine:

This repository now follows that model.

GitHub Pages status

The legacy GitHub Pages frontend deployment was removed. This project is now run as a full-stack application (apps/api + apps/web) and deployed via your own hosting/runtime.

Architecture

apps/web (React + viem)
    |
    | 1) POST /challenge
    | 2) sign challenge with wallet
    | 3) POST /ticket
    v
apps/api (Fastify + viem signer)
    |
    | validates: signature, captcha (optional), ip/address cooldown,
    | on-chain claim eligibility, faucet balance
    | issues EIP-712 ticket (nonce + deadline + signature)
    v
contracts/contracts/ModernEthFaucet.sol
    |
    | verifies ticket signer + nonce uniqueness + cooldown + wallet balance cap
    | transfers drip amount and records next claim window
    v
recipient wallet

Repository layout

.
├── apps/
│   ├── api/                 # Fastify backend issuing claim tickets
│   └── web/                 # React frontend
├── contracts/
│   ├── contracts/           # Solidity contracts
│   ├── scripts/             # Deployment scripts
│   └── test/                # Hardhat tests
├── package.json             # Workspace scripts
└── tsconfig.base.json

Smart contract design

contracts/contracts/ModernEthFaucet.sol

Key protections:

API design

apps/api/src/index.ts

Endpoints

Eligibility checks before ticket issuance

Frontend design

apps/web/src/App.tsx

Features:

Prerequisites

Quick start

1) Install dependencies

npm install

2) Configure environment files

cp contracts/.env.example contracts/.env
cp apps/api/.env.example apps/api/.env
cp apps/web/.env.example apps/web/.env

Fill all required variables, especially:

3) Compile and test contracts

npm run contracts:test

4) Deploy faucet contract

npm run contracts:deploy

The deployment script can seed initial faucet balance via INITIAL_FUNDING_WEI.

5) Run API and web apps

npm run dev

Configuration reference

contracts/.env

Variable Description
SEPOLIA_RPC_URL RPC endpoint used for deployment/verification.
HOLESKY_RPC_URL Optional alternate network RPC endpoint.
DEPLOYER_PRIVATE_KEY Deployer wallet private key.
ETHERSCAN_API_KEY Optional contract verification key.
FAUCET_OWNER Owner address for admin controls.
TICKET_SIGNER_ADDRESS Address allowed to sign claim tickets.
DRIP_AMOUNT_WEI Drip amount paid per successful claim.
COOLDOWN_SECONDS Minimum wait between claims per wallet.
MAX_RECIPIENT_BALANCE_WEI Wallet balance ceiling for eligibility.
INITIAL_FUNDING_WEI Optional deploy-time faucet seed amount.

apps/api/.env

Variable Description
HOST / PORT API bind address/port.
WEB_ORIGIN Allowed CORS origin for frontend.
RPC_URL RPC endpoint for on-chain checks.
FAUCET_CHAIN_ID Chain ID used in typed-data domain.
FAUCET_CONTRACT_ADDRESS Deployed faucet contract address.
FAUCET_DOMAIN_NAME / FAUCET_DOMAIN_VERSION EIP-712 domain values (must match contract).
FAUCET_DRIP_WEI Expected on-chain drip amount.
FAUCET_COOLDOWN_SECONDS Expected on-chain cooldown.
FAUCET_MAX_RECIPIENT_BALANCE_WEI Eligibility balance cap.
TICKET_SIGNER_PRIVATE_KEY Private key used to sign claim tickets.
CHALLENGE_TTL_SECONDS Signature challenge expiry window.
TICKET_TTL_SECONDS Claim ticket expiry window.
ADDRESS_COOLDOWN_SECONDS / IP_COOLDOWN_SECONDS Local anti-abuse cooldown windows.
TURNSTILE_SECRET_KEY Optional Cloudflare Turnstile secret.
TURNSTILE_VERIFY_URL Turnstile verification endpoint.

apps/web/.env

Variable Description
VITE_API_BASE_URL Base URL of faucet API.
VITE_CHAIN_ID Target chain ID for wallet switching.
VITE_RPC_URL Public RPC used for read operations.
VITE_FAUCET_ADDRESS Faucet contract address.
VITE_EXPLORER_BASE_URL Explorer base URL for tx/address links.
VITE_TURNSTILE_SITE_KEY Optional key for frontend Turnstile integration.

Workspace commands

npm run dev
npm run build
npm run test
npm run lint
npm run format

Security model

Primary defense layers:

Production hardening recommendations

Research references

This rewrite follows patterns used by current public faucets and standards docs:

License

MIT