A dual-chain faucet system for distributing both Cosmos native tokens (ATOM) and ERC-20 tokens on the Cosmos EVM environment. Built for frequently-resetting devnets with flexible, centralized configuration management.
- Dual Environment Support: Cosmos SDK + EVM compatibility layer
- Multi-Token Distribution: Distributes ATOM, WBTC, PEPE, and USDT tokens
- Centralized Configuration: Network settings in
config.js
, token details intokens.json
- Secure Key Management: Mnemonic-based address derivation with caching
- Contract Validation: Automatic validation and deployment on startup
- Rate Limiting: Per-address and per-IP limits with persistent storage
- Modern UI: Vue.js interface with MetaMask integration and transaction history
Required Software:
- Node.js >= 18.0.0
- Foundry (latest version)
Installation:
# Install Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup
# Verify installations
node --version
forge --version
git clone <repository-url>
cd devnet-faucet
npm install
cp .env.example .env
Edit .env
- only mnemonic is required:
# Required: 12-word mnemonic phrase for address derivation
MNEMONIC="your twelve word mnemonic phrase here"
# Optional: Override network endpoints (defaults in config.js)
# RPC_URL="https://your-custom-rpc.example.com"
Primary Configuration: Edit config.js
for network settings:
blockchain: {
name: "cosmos-evm-chain",
ids: {
chainId: 4231, // EVM chain ID (current: devnet-1)
cosmosChainId: '4321', // Cosmos chain ID
},
endpoints: {
rpc_endpoint: "https://devnet-1-rpc.ib.skip.build",
rest_endpoint: "https://devnet-1-lcd.ib.skip.build",
evm_endpoint: "https://devnet-1-evmrpc.ib.skip.build",
evm_explorer: "https://evm-devnet-1.cloud.blockscout.com",
}
}
Token Configuration: tokens.json
contains comprehensive token metadata:
- Contract addresses and deployment info
- Faucet distribution amounts and limits
- Token features (mintable, burnable, etc.)
- Governance roles and permissions
- UI metadata (logos, descriptions, categories)
# Complete deployment pipeline
npm run deploy # Deploy contracts, set approvals, validate
npm start # Start faucet server
This will:
- Validate environment and dependencies
- Deploy ERC-20 tokens from
tokens.json
configuration - Deploy AtomicMultiSend contract for batch transfers
- Set token approvals for the faucet wallet
- Verify all contracts are accessible
- Update configuration files with deployed addresses
The faucet can be deployed to Vercel for serverless hosting. See docs/VERCEL_DEPLOYMENT.md for detailed instructions.
Quick start:
# Install Vercel CLI
npm i -g vercel
# Deploy to Vercel
vercel
Important: Set the MNEMONIC
environment variable in your Vercel project settings.
npm run validate # Environment validation
forge build # Compile Solidity contracts
node scripts/deploy-token-registry.js # Deploy tokens
node scripts/automated-deploy.js # Deploy & configure system
To add new tokens, edit tokens.json
:
{
"tokens": [
{
"symbol": "NEWTOKEN",
"name": "New Token",
"decimals": 18,
"faucet": {
"enabled": true,
"configuration": {
"amountPerRequest": "1000000000000000000000",
"targetBalance": "1000000000000000000000"
}
}
}
]
}
config.js
: Central authority for network parameters (chain IDs, RPC endpoints, gas settings)tokens.json
: Token-specific configuration (contracts, amounts, metadata)TokenConfigLoader
: Bridges configuration files and validates consistency
- AtomicMultiSend: Batch ERC-20 token distribution contract
- ERC-20 Tokens: Auto-generated from
tokens.json
with custom features - ContractValidator: Validates contract addresses on startup
- SecureKeyManager: Derives addresses from mnemonic with caching
- Address Validation: Ensures consistency between deployments
- Multi-Environment: Same private key for both Cosmos and EVM
GET /
- Web interface with Vue.js frontendGET /send/:address
- Request tokens (accepts Cosmos or EVM addresses)GET /config.json
- Network configuration for frontendGET /balance/cosmos
- Cosmos token balancesGET /balance/evm
- EVM token balances
- Cosmos:
cosmos1...
(bech32 format) - EVM:
0x...
(40 hex characters)
- Per Address: 1 request per 24 hours
- Per IP: 10 requests per 24 hours
- Database: SQLite at
.faucet/history.db
Token | Symbol | Decimals | Amount/Request | Contract |
---|---|---|---|---|
Wrapped Bitcoin | WBTC | 8 | 1,000 | 0xB259846bb... |
Pepe Token | PEPE | 18 | 1,000 | 0xe2D7606B6... |
Tether USD | USDT | 6 | 1,000 | 0x21065d53D... |
Cosmos Atom | ATOM | 6 | 1 | Native transfer |
- Address Type Detection: Automatically detects Cosmos vs EVM format
- EVM Distribution: Uses AtomicMultiSend for batch ERC-20 transfers
- Cosmos Distribution: Direct bank send for native ATOM
- Transaction Tracking: Full transaction history with explorer links
# Environment Variables
MNEMONIC=<mnemonic_phrase>
NODE_ENV=production
# Optional overrides
RPC_URL=<custom_rpc_endpoint>
- Node.js 18+ runtime
- Persistent storage for rate limiting database
- Funded faucet wallet (native tokens for gas + ERC-20 tokens)
# Validate all systems
npm run validate
# Check contract addresses
node scripts/validate-contracts.js
# View faucet balances
curl localhost:8088/balance/evm
- Faucet Balances: Monitor token levels for distribution
- Gas Balance: Ensure native tokens for transaction fees
- RPC Connectivity: Validate endpoint accessibility
- Contract Validity: Verify contracts after network resets
Since devnets reset frequently:
- Update network endpoints in
config.js
if changed - Run
npm run deploy
to redeploy contracts - Update
tokens.json
with new contract addresses - Restart faucet service
Contract Validation Failed
# Redeploy contracts
npm run deploy
# Or manually validate
node scripts/validate-contracts.js --interactive
Address Derivation Mismatch
# Verify mnemonic is correct
echo $MNEMONIC
# Clear cached addresses (forces re-derivation)
rm -rf .faucet/cached-addresses.json
Token Transfer Failures
# Check approvals
node scripts/approve-tokens.js
# Verify faucet has tokens
curl localhost:8088/balance/evm
Network Connection Issues
- Verify RPC endpoints in
config.js
- Check if devnet has reset
- Validate chain IDs match network
- Server logs: Console output with sanitized sensitive data
- Transaction history: Stored in browser localStorage
- Rate limiting: SQLite database in
.faucet/history.db
├── config.js # Central network configuration
├── tokens.json # Token definitions and metadata
├── faucet.js # Main server application
├── src/
│ ├── TokenConfigLoader.js # Configuration bridge
│ ├── SecureKeyManager.js # Key derivation and caching
│ ├── ContractValidator.js # Contract validation
│ └── tokens/ # Generated token contracts
├── scripts/
│ ├── automated-deploy.js # Full deployment pipeline
│ ├── deploy-token-registry.js # Token deployment
│ └── validate-*.js # Validation utilities
└── views/
└── index.ejs # Vue.js frontend
- New Tokens: Add to
tokens.json
with full metadata - Network Support: Update endpoints in
config.js
- UI Changes: Modify
views/index.ejs
Vue components - Validation: Add checks to
ContractValidator.js