# Contractless Faucet This faucet uses PHP and JSON storage. It connects directly to a Contractless node through the authenticated RPC protocol, creates and signs transfers locally, and submits them without invoking Contractless CLI programs. ## Requirements - 64-bit PHP 8.1 or newer - Composer - The Contractless PHP Skein and Falcon modules - `contractless/contractless-php-rpc` - Access to a compatible Contractless RPC node - A dedicated, registered faucet wallet - Read access to that wallet file - A writable private directory for the JSON claim ledger Install the native modules first: ```text https://contractless.dev/contractless/Contractless-PHP-Modules ``` Install the RPC package in the Composer project containing the faucet: ```bash composer require contractless/contractless-php-rpc:^0.2.0 -W ``` The web-server account needs permission to read Composer's `vendor` directory and faucet wallet, and write the configured claim-ledger directory. It does not need access to a node runtime, balance sheet, or Contractless CLI binary. The faucet configuration, wallet file, wallet decryption key, and claim ledger must never be downloadable through the web server. ## Configuration For an installation at: ```text /var/www/project/public/faucet ``` copy the included template to the private project root: ```bash cp /var/www/project/public/faucet/.env.example /var/www/project/faucet.env sudo chown root:www-data /var/www/project/faucet.env sudo chmod 640 /var/www/project/faucet.env ``` Then edit `/var/www/project/faucet.env` and replace every example value with the correct faucet settings. The faucet automatically loads `faucet.env` from the project root two directories above the faucet: ```text /var/www/project/faucet.env ``` No Apache configuration, PHP-FPM pool changes, shell exports, or service restarts are required. Reloading the faucet page uses the saved values. The optional `FAUCET_ENV_FILE` process variable can point to a different file, but normal installations do not need it. `FAUCET_ADDRESS` determines the active network: - An address ending in `.cltc` configures testnet and displays `CLTC`. - An address ending in `.clc` configures mainnet and displays `CLC`. The faucet address must be the registered canonical 40-character short address. Faucet claims also require canonical short addresses; vanity aliases are not accepted by the claim form. Point the faucet at its dedicated wallet and provide that wallet's decryption key: ```text CONTRACTLESS_WALLET_PATH=/var/www/project/faucet.wallet CONTRACTLESS_WALLET_KEY=wallet-decryption-key ``` The RPC library reads the public key from the wallet, extracts the encrypted private key from its image, verifies the image payload HMAC, decrypts the private key, proves that the Falcon keypair matches, and verifies that the wallet's short address is derived from that public key. `FAUCET_ADDRESS` must match the canonical `short_address` saved in this wallet. Keep the wallet file and decryption key outside the public document root, but inside a path PHP is permitted to read. For the example layout, the public document root is `/var/www/project/public`, so `/var/www/project/faucet.wallet` is private from HTTP while remaining available to PHP. Never expose the wallet or key through HTML, JavaScript, logs, error responses, or source control. Before enabling the faucet, verify the wallet through the installed RPC package: ```bash cd /path/to/Contractless-PHP-RPC php examples/load_wallet.php /private/path/to/faucet.wallet 'wallet decryption key' ``` Configure the node used for RPC: ```text CONTRACTLESS_RPC_HOST=127.0.0.1 CONTRACTLESS_RPC_PORT=50050 CONTRACTLESS_RPC_TIMEOUT=10 ``` Use port `50050` for the default testnet RPC or `50055` for the default mainnet RPC unless the selected node uses a different configured port. The faucet searches for Composer's autoloader in its own directory, its parent directory, and the web-project root two directories above it. Set `FAUCET_COMPOSER_AUTOLOAD` to the absolute `vendor/autoload.php` path only when Composer is installed elsewhere. For production, set `FAUCET_CLAIMS_FILE` and `FAUCET_LOCK_FILE` to paths outside the public web root. The included `storage` directory is suitable for local setup and includes an Apache access-denial rule, but server-level private storage is preferable. ## Claim Rules Each successful request sends 25 base testnet or mainnet coins and pays a 0.25-coin transfer fee from the faucet wallet. Before reserving or broadcasting a claim, the faucet: - Retrieves its confirmed base-coin balance through RPC - Refuses the request when the faucet cannot cover the claim and fee - Confirms that the receiving canonical wallet address is registered - Creates and signs the transfer locally - Submits the exact signed transaction through RPC The faucet records a successful claim only after the node returns `successful_broadcast: true`. A claim is rejected when either the canonical wallet address or normalized client IP has claimed during the preceding 24 hours. IPv4-mapped IPv6 addresses are treated as IPv4. Native IPv6 clients are grouped by `/64`. Claims are reserved under an exclusive file lock before broadcasting. This prevents simultaneous requests from passing the same address or IP check. Failed broadcasts release their reservation so the user may try again. The faucet trusts `REMOTE_ADDR` and intentionally ignores forwarded-IP headers. When deploying behind a reverse proxy, configure the proxy or web server to replace `REMOTE_ADDR` only from explicitly trusted proxy addresses. ## JSON Ledger The claim ledger is keyed directly by canonical wallet address and normalized IP: ```json { "version": 1, "last_request_timestamp_ms": 0, "total_claimed_atomic": 2500000000, "total_claims": 1, "addresses": { "abcd000000000000000000000000000000001234.cltc": { "claimed_timestamp": 1785000000, "status": "completed", "address": "abcd000000000000000000000000000000001234.cltc", "ip": "203.0.113.10", "txid": "transaction hash" } }, "ips": { "203.0.113.10": { "claimed_timestamp": 1785000000, "status": "completed", "address": "abcd000000000000000000000000000000001234.cltc", "ip": "203.0.113.10", "txid": "transaction hash" } } } ``` ## Security Run the faucet under a dedicated operating-system account with access only to its private configuration and claim ledger. Do not run PHP or the faucet as root. Serve the site over HTTPS, keep directory listing disabled, and keep `faucet.env` outside the public web root.