CR8 Sepolia Faucet
End-to-end guide for deploying a public faucet on Sepolia that dispenses both CR8 and CR8USD test tokens.
1. Prerequisites
- Sepolia RPC endpoint and funded deployer key:
SEPOLIA_RPC_URL=https://...PRIVATE_KEY=0x...(same.envused for other Hardhat scripts)
- Live ERC-20 contract addresses for the two tokens you want to distribute (e.g. previously deployed
CR8+CR8USD) - Node 18+,
npm installalready run inpackages/contracts
2. Configure faucet parameters
Add the following variables to packages/contracts/.env (or export them in your shell):
FAUCET_PRIMARY_TOKEN_ADDRESS=0xYourCR8Address
FAUCET_SECONDARY_TOKEN_ADDRESS=0xYourCR8USDAddress
FAUCET_PRIMARY_DRIP=10 # human-readable amount, default decimals = 18
FAUCET_SECONDARY_DRIP=25 # human-readable amount, default decimals = 18
FAUCET_PRIMARY_DECIMALS=18
FAUCET_SECONDARY_DECIMALS=18
FAUCET_COOLDOWN_SECONDS=3600 # 1 hour per walletFAUCET_PRIMARY_* controls CR8, FAUCET_SECONDARY_* controls CR8USD. Set either drip to 0 to temporarily disable that token.
3. Deploy the faucet
cd packages/contracts
npx hardhat compile
npx hardhat run scripts/deployFaucet.js --network sepoliaThe script prints the new faucet address. Save it; you will need it for funding and UI integration.
Optional: Verify on Etherscan
npx hardhat verify --network sepolia \
<FAUCET_ADDRESS> \
$FAUCET_PRIMARY_TOKEN_ADDRESS \
$FAUCET_SECONDARY_TOKEN_ADDRESS \
$(npx hardhat --network sepolia --show-stack-traces console <<< "ethers.parseUnits('$FAUCET_PRIMARY_DRIP',$FAUCET_PRIMARY_DECIMALS);") \
$(npx hardhat --network sepolia --show-stack-traces console <<< "ethers.parseUnits('$FAUCET_SECONDARY_DRIP',$FAUCET_SECONDARY_DECIMALS);") \
$FAUCET_COOLDOWN_SECONDSReplace the inline helper with the literal uint256 values printed during deployment if preferred.
4. Fund the faucet
Transfer enough CR8 and CR8USD to the faucet contract so it can serve multiple users:
npx hardhat console --network sepolia
> const signer = await ethers.getSigner();
> const cr8 = await ethers.getContractAt("ERC20", process.env.FAUCET_PRIMARY_TOKEN_ADDRESS);
> cr8.transfer("<FAUCET_ADDRESS>", ethers.parseUnits("10000", 18));
> const usd = await ethers.getContractAt("ERC20", process.env.FAUCET_SECONDARY_TOKEN_ADDRESS);
> usd.transfer("<FAUCET_ADDRESS>", ethers.parseUnits("10000", 18));Keep the faucet topped up to avoid “insufficient balance” reverts.
5. Exposing the faucet
- Share the contract address so builders can call
requestTokens(address recipient)directly, or - Wire it into the dashboard/dapp UI with a button that sends the transaction from the connected wallet.
Each wallet can claim once per cooldown window. Use the balances() view to monitor remaining liquidity, and withdraw(token, to, amount) to reclaim leftover funds when rotating deployments.