A complete, production-ready system for compliant fiat-to-crypto conversions with integrated compliance checks, resilient architecture, and comprehensive operational tooling.
Railsdex is an end-to-end protocol that enables secure, compliant conversion of fiat currency (via M-PESA) to blockchain-native country tokens. The system enforces compliance checks at every step, handles payment provider webhooks with full idempotency guarantees, and provides production-grade monitoring and operational tooling.
- Smart Contract Layer: UUPS upgradeable contracts with role-based access control, compliance orchestration, and idempotent minting
- API Service: Resilient Node.js backend with HMAC authentication, exponential backoff retries, and dead-letter queue handling
- Observability Stack: Complete Prometheus/Grafana monitoring with pre-configured dashboards and alerting rules
- Operations: Docker Compose deployment with health checks, graceful degradation, and comprehensive runbooks
┌──────────────┐ HMAC ┌─────────────────┐ Web3 ┌──────────────────┐
│ M-PESA │ Verification │ API Service │ Provider │ Smart Contracts │
│ Webhook ├─────────────────▶│ (Node.js) ├───────────────▶│ (Solidity) │
└──────────────┘ └────────┬────────┘ └────────┬─────────┘
│ │
│ Idempotency │ On-chain
│ Check │ Events
▼ ▼
┌─────────────────┐ ┌──────────────────┐
│ Database │ │ EVM Network │
│ (SQLite/Pg SQL) │ │ (Anvil) │
│ - Dedup Keys │ │ - UserRegistry │
│ - Retry Queue │ │ - MintEscrow │
│ - DLQ │ │ - Compliance │
└────────┬────────┘ └──────────────────┘
│
│ Metrics
▼
┌─────────────────┐
│ Prometheus │
│ Grafana │
│ Dashboards │
└─────────────────┘
- Compliance-First: Every mint transaction validated against UserRegistry with risk scoring
- Idempotency: UUID-based deduplication with 24-hour TTL prevents double-mints
- Retry Logic: Exponential backoff (691ms initial, 2x multiplier, 30s max) handles RPC failures
- Dead-Letter Queue: Failed transactions persisted for manual review and replay
- Event-Driven: Indexed on-chain events enable efficient off-chain indexing and reconciliation
This implementation includes all components specified in the production trial requirements:
| Contract | Description | Features |
|---|---|---|
| ComplianceManager | UUPS upgradeable compliance orchestrator | • Role-based access (ADMIN, COMPLIANCE_OFFICER, UPGRADER) • Pausable for emergency stops • Indexed events for off-chain processing |
| UserRegistry | User compliance data storage | • Risk score (0-100) per user • Attestation hash storage • Compliance query interface (verified + risk ≤83 + attestation) |
| MintEscrow | Core minting logic with escrow | • USD stablecoin deposit acceptance • Compliance-gated 1:1 minting • Idempotency via intent IDs • Refund mechanism for non-compliant users |
| CountryToken | ERC20 country-specific token | • Symbol from seed.json (KES) • 18 decimals • Role-based minting |
| USDStablecoin | Mock USDC for testing | • Pre-mint capability • 18 decimals |
event UserRiskUpdated(
address indexed user,
uint8 newRiskScore,
address indexed updatedBy,
uint256 timestamp
);
event AttestationRecorded(
address indexed user,
bytes32 indexed attestationHash,
bytes32 attestationType,
address indexed recordedBy
);
event MintIntentSubmitted(
bytes32 indexed intentId,
address indexed user,
uint256 amount,
bytes32 indexed countryCode,
bytes32 txRef
);
event MintExecuted(
bytes32 indexed intentId,
address indexed user,
uint256 amount,
bytes32 indexed countryCode,
bytes32 txRef
);- 107 tests passing across all contracts
- 94.26% test coverage (exceeds 80% requirement)
- Test types:
- Unit tests for individual functions
- Fuzz tests (257 runs each) for input validation
- Integration tests for multi-contract flows
- Upgrade tests for UUPS mechanism
- Negative tests for unauthorized access
forge test # Run all tests
forge coverage # Generate coverage report
forge snapshot # Generate gas snapshots| Endpoint | Method | Description | Security |
|---|---|---|---|
/mint-intents |
POST | Submit new mint request | HMAC signature + idempotency key |
/callbacks/mpesa |
POST | Process M-PESA payment webhook | HMAC signature + timestamp freshness |
/health |
GET | Service health check | Public |
/metrics |
GET | Prometheus metrics | Public |
- Idempotency: Database-backed deduplication (24h TTL from seed.json)
- Retry Logic: Exponential backoff with configurable parameters
- Dead-Letter Queue: File-based persistence for exhausted retries
- RPC Failure Handling: Graceful degradation, no crashes
- Nonce Management: Sequential transaction ordering with
pendingnonce strategy
- 35 tests passing
- Test coverage:
- HMAC verification (valid/invalid signatures, expired timestamps)
- Exponential backoff calculations
- Idempotency key handling
cd api && npm test # Run API testsdocker compose up # Start all servicesServices included:
- API service (Node.js)
- Anvil (local Ethereum node)
- Prometheus (metrics collection)
- Grafana (visualization)
- Proper health checks and dependencies configured
# RPC operations
fiatrails_rpc_requests_total{method, status}
fiatrails_rpc_duration_seconds{method, quantile}
fiatrails_rpc_errors_total{method, error_type}
# Business metrics
fiatrails_mint_intents_total{status}
fiatrails_callbacks_total{source, status}
# Queue metrics
fiatrails_dlq_depth
fiatrails_retry_attempts_total{operation}
# Compliance
fiatrails_compliance_checks_total{result}
Pre-configured panels:
- RPC error rate (5-minute rolling window)
- p95 latency for RPC and API calls
- DLQ depth over time
- Successful mint rate
- Visual alerts when thresholds exceeded
Access: http://localhost:3001 (admin/admin)
GitHub Actions workflow (.github/workflows/ci.yml):
- Run Foundry tests (107 tests)
- Run API tests (35 tests)
- Solidity linting (
forge fmt --check) - Gas report generation (
forge snapshot) - Docker image builds
Comprehensive operational documentation included:
| Document | Purpose |
|---|---|
| ADR.md | Architecture Decision Records explaining trade-offs: • UUPS vs Transparent proxy rationale • Event schema design • Idempotency strategy • Key management approach • Database and retry parameters |
| THREAT_MODEL.md | Security analysis covering: • On-chain threats (reentrancy, replay, role escalation) • Off-chain threats (HMAC forgery, DDoS, nonce griefing) • Operational threats (key leakage, RPC censorship) • Likelihood, impact, and mitigations for each |
| RUNBOOK.md | Operational procedures: • Contract upgrade rollback • HMAC secret rotation (zero downtime) • DLQ processing • Degraded mode operations • SLOs and alert response |
| TESTING.md | Testing guide including: • Automated test documentation • Manual testing procedures (retry/DLQ) • Failure scenario simulations |
| FINAL_REVIEW.md | Comprehensive code review: • Security assessment • Test coverage analysis • Submission checklist verification |
- Docker & Docker Compose: Required for running the full stack
- Node.js 18+: For local API development
- Foundry: For smart contract development (installation)
# 1. Clone the repository
git clone https://github.com/Githaiga22/FiatRails.git
cd FiatRails
# 2. Start services
docker compose up -d
# 3. Deploy contracts and run demo
./scripts/deploy-and-demo.shThe deployment script will:
- Start all Docker services (API, Anvil, Prometheus, Grafana)
- Deploy all smart contracts to Anvil
- Configure contract relationships (roles, addresses)
- Pre-mint USD tokens to test users
- Create compliant test users in UserRegistry
- Execute a complete mint flow demonstration
- Generate
deployments.jsonwith contract addresses
Services will be available at:
- API: http://localhost:3000
- Grafana: http://localhost:3001 (admin/admin)
- Prometheus: http://localhost:9090
- Health: http://localhost:3000/health
- Metrics: http://localhost:3000/metrics
cd contracts
# Install dependencies
forge install
# Run tests
forge test # All tests
forge test -vvv # Verbose output
forge test --match-test testMintFlow # Specific test
# Check coverage
forge coverage
# Generate gas report
forge snapshot
# Format code
forge fmt
forge fmt --check # Verify formattingcd api
# Install dependencies
npm install
# Development mode (with auto-reload)
npm run dev
# Run tests
npm test
# Production mode
npm start# Ensure services are running
docker compose up -d
# Run complete E2E test suite
node scripts/e2e-test.jsE2E test scenarios:
- Complete mint flow (intent → callback → on-chain verification)
- Idempotency protection (duplicate requests with same key)
- Non-compliant user rejection
- Health and metrics endpoint validation
The project includes an HMAC-authenticated helper script for testing:
# Submit a mint intent
node scripts/api-helper.js submit-intent \
0x70997970C51812dc3A010C7d01b50e0d17dc79C8 \
1000000000000000000 \
MPESA-TEST-123
# Trigger M-PESA callback
node scripts/api-helper.js trigger-callback \
MPESA-TEST-123 \
0x70997970C51812dc3A010C7d01b50e0d17dc79C8 \
1000000000000000000
# Check health
node scripts/api-helper.js health# Submit mint intent
curl -X POST http://localhost:3000/mint-intents \
-H "Content-Type: application/json" \
-H "X-Idempotency-Key: $(uuidgen)" \
-H "X-Signature: <hmac-signature>" \
-H "X-Timestamp: $(date +%s)" \
-d '{
"userId": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
"amount": "1000000000000000000",
"countryCode": "KES",
"transactionRef": "MPESA-TEST-123"
}'
# Check metrics
curl http://localhost:3000/metrics# Load contract addresses
export COUNTRY_TOKEN=$(cat deployments.json | jq -r '.countryToken')
export USER_REGISTRY=$(cat deployments.json | jq -r '.userRegistry')
export MINT_ESCROW=$(cat deployments.json | jq -r '.mintEscrow')
# Check user balance
cast call $COUNTRY_TOKEN "balanceOf(address)(uint256)" \
0x70997970C51812dc3A010C7d01b50e0d17dc79C8 \
--rpc-url http://localhost:8545
# Check user compliance
cast call $USER_REGISTRY "isCompliant(address)(bool)" \
0x70997970C51812dc3A010C7d01b50e0d17dc79C8 \
--rpc-url http://localhost:8545
# Get intent status
cast call $MINT_ESCROW "getIntentStatus(bytes32)(uint8)" \
0x... \
--rpc-url http://localhost:8545Railsdex/
├── contracts/ # Smart contracts (Foundry)
│ ├── src/
│ │ ├── ComplianceManager.sol # UUPS upgradeable compliance
│ │ ├── UserRegistry.sol # Risk scoring & attestations
│ │ ├── MintEscrow.sol # Core minting logic
│ │ ├── CountryToken.sol # ERC20 country token
│ │ └── USDStablecoin.sol # Mock USDC
│ ├── test/ # Foundry tests (107 tests)
│ ├── script/ # Deployment scripts
│ │ └── Deploy.s.sol
│ ├── IComplianceManager.sol # Interface definitions
│ ├── IMintEscrow.sol
│ ├── IUserRegistry.sol
│ └── foundry.toml
│
├── api/ # Node.js API service
│ ├── src/
│ │ ├── routes/ # Endpoint handlers
│ │ │ ├── mintIntents.js
│ │ │ ├── callbacks.js
│ │ │ └── health.js
│ │ ├── middleware/ # HMAC & idempotency
│ │ │ ├── hmacVerification.js
│ │ │ └── idempotency.js
│ │ ├── services/ # Retry & metrics
│ │ │ └── retry.js
│ │ ├── blockchain.js # Web3 provider
│ │ ├── database.js # SQLite setup
│ │ ├── config.js # Load seed.json
│ │ └── index.js # Express app
│ ├── test/ # API tests (35 tests)
│ ├── Dockerfile
│ └── package.json
│
├── ops/ # Operations configuration
│ ├── prometheus.yml # Metrics scraping config
│ ├── alerts.yml # Alert rules
│ └── grafana/
│ ├── provisioning/
│ └── dashboards/
│ └── fiatrails.json # Pre-built dashboard
│
├── docs/ # Documentation
│ ├── ADR.md # Architecture decisions
│ ├── THREAT_MODEL.md # Security analysis
│ ├── RUNBOOK.md # Operational procedures
│ ├── TESTING.md # Testing guide
│ └── FINAL_REVIEW.md # Code review summary
│
├── scripts/ # Utility scripts
│ ├── deploy-and-demo.sh # Complete deployment + demo
│ ├── api-helper.js # HMAC-authenticated API client
│ └── e2e-test.js # End-to-end test suite
│
├── .github/
│ └── workflows/
│ └── ci.yml # CI/CD pipeline
│
├── docker-compose.yml # Multi-service orchestration
├── deployments.json # Contract addresses (generated)
├── seed.json # Project configuration
└── README.md # This file
All system parameters are derived from seed.json:
{
"candidateId": "githaiga-munene",
"chain": {
"chainId": 31382,
"rpcUrl": "https://rpc.sepolia-api.lisk.com"
},
"tokens": {
"country": {
"countryCode": "KES",
"name": "Kenyan Shilling Token",
"symbol": "KES"
}
},
"security": {
"maxRiskScore": 83,
"timestampWindow": 300
},
"retry": {
"initialBackoff": 691,
"maxBackoff": 30000,
"multiplier": 2,
"maxRetries": 5
},
"idempotency": {
"ttl": 86400
},
"secrets": {
"hmacSalt": "...",
"webhookSecret": "..."
}
}Usage throughout codebase:
- Chain ID used in deployment scripts
- Country code used as token symbol
- Max risk score enforced in UserRegistry
- Retry parameters used in API backoff logic
- Secrets used for HMAC verification
Access metrics at http://localhost:3000/metrics
fiatrails_rpc_requests_total- Total RPC calls by method and statusfiatrails_rpc_duration_seconds- RPC latency histogram (p50, p95, p99)fiatrails_rpc_errors_total- RPC error counts by error type
fiatrails_mint_intents_total- Mint requests by statusfiatrails_callbacks_total- Webhook processing countsfiatrails_compliance_checks_total- Compliance check results
fiatrails_dlq_depth- Current dead-letter queue sizefiatrails_retry_attempts_total- Retry attempt countsfiatrails_idempotency_hits_total- Duplicate request detection
Pre-configured dashboard includes:
-
RPC Health Panel
- Error rate (5m window) with alert threshold at 10%
- p95 latency with alert threshold at 2s
-
Business Metrics Panel
- Successful mint rate
- Compliance check distribution
- Callback processing rate
-
Queue Health Panel
- DLQ depth over time with alert threshold at 10 items
- Retry attempt distribution
-
Alerts Panel
- Visual indicators when thresholds exceeded
- Links to relevant runbook procedures
Prometheus alerts configured in ops/alerts.yml:
- HighRPCErrorRate: RPC error rate >10% for 2+ minutes (CRITICAL)
- DLQGrowing: DLQ depth >10 items for 5+ minutes (CRITICAL)
- SlowRPCCalls: p95 RPC latency >2s for 5+ minutes (WARNING)
- NoSuccessfulMints: Zero successful mints in 10 minutes (WARNING)
# Pause ComplianceManager (blocks all compliance checks)
cast send $COMPLIANCE_MANAGER "pause()" \
--private-key $ADMIN_KEY \
--rpc-url http://localhost:8545
# Unpause when issue resolved
cast send $COMPLIANCE_MANAGER "unpause()" \
--private-key $ADMIN_KEY \
--rpc-url http://localhost:8545# 1. Deploy new implementation
forge script script/DeployV2.s.sol --rpc-url http://localhost:8545 --broadcast
# 2. Upgrade proxy
cast send $COMPLIANCE_MANAGER "upgradeTo(address)" $NEW_IMPL \
--private-key $UPGRADER_KEY \
--rpc-url http://localhost:8545
# 3. Verify upgrade
cast call $COMPLIANCE_MANAGER "implementation()(address)" \
--rpc-url http://localhost:8545For rollback procedures, see RUNBOOK.md.
# View DLQ items
ls -la api/dlq/
cat api/dlq/*.json | jq .
# Manual replay after RPC restoration
node scripts/api-helper.js trigger-callback \
$TX_REF $USER_ADDRESS $AMOUNTFor detailed DLQ procedures, see RUNBOOK.md.
See RUNBOOK.md for the complete zero-downtime HMAC secret rotation procedure.
- Reentrancy Protection: All state-changing functions use
nonReentrantmodifier - Access Control: Role-based permissions (ADMIN, EXECUTOR, COMPLIANCE_OFFICER, UPGRADER)
- Upgrade Safety: UUPS pattern with authorization checks, initialization guards
- Idempotency: Intent IDs prevent double-execution
- Input Validation: Amount checks, country code validation, zero-address protection
- HMAC Verification: SHA-256 HMAC with timing-safe comparison
- Timestamp Freshness: 5-minute window (from seed.json) prevents replay attacks
- Idempotency Keys: UUID-based deduplication with 24-hour TTL
- Error Handling: No sensitive information leaked in error responses
- Input Validation: Amount limits, country code checks, required field verification
- Secret Management: All secrets in seed.json or environment variables
- Network Isolation: Docker network segmentation
- Monitoring: Comprehensive metrics and alerting
- Audit Trail: Indexed events for all state changes
For complete threat analysis, see THREAT_MODEL.md.
| Metric | Target | Measurement Window |
|---|---|---|
| Availability | 99.9% | 30 days |
| API p95 Latency | <500ms | 5 minutes |
| RPC p95 Latency | <2s | 5 minutes |
| Mint Success Rate | >95% | 1 hour |
| RPC Error Rate | <5% | 5 minutes |
Contract gas usage (from forge snapshot):
- MintEscrow.submitIntent: ~120k gas
- MintEscrow.executeMint: ~180k gas
- UserRegistry.updateUser: ~50k gas
- Smart Contracts: 107 tests, 94.26% coverage
- API Service: 35 tests, comprehensive coverage
- End-to-End: 4 complete flow scenarios
# Smart contract tests
cd contracts && forge test
# API tests
cd api && npm test
# E2E tests (requires running services)
docker compose up -d
node scripts/e2e-test.jsFor manual testing procedures (retry logic, DLQ processing), see TESTING.md.
GitHub Actions pipeline runs on every push:
Smart contract tests (Foundry)
API tests (Node.js)
Solidity linting (forge fmt)
Gas report generation
Docker image buildsAll checks must pass before merging. See .github/workflows/ci.yml for details.
Solution: API uses pending nonce strategy. Check for stuck transactions:
cast tx-status $TX_HASH --rpc-url http://localhost:8545Solution: Verify Prometheus is scraping metrics:
curl http://localhost:9090/api/v1/targets | jq .
curl http://localhost:3000/metricsSolution: Check RPC connectivity and process DLQ items:
# Check RPC
cast block-number --rpc-url http://localhost:8545
# Process DLQ
ls api/dlq/ && cat api/dlq/*.json | jq .For comprehensive troubleshooting, see RUNBOOK.md.
- External security audit completed
- Load testing performed
- Backup and disaster recovery procedures tested
- Key management system configured (e.g., AWS KMS)
- Multi-region deployment planned
- Monitoring and alerting verified
- On-call rotation established
- Deploy contracts to target network (e.g., Lisk Sepolia)
- Update
seed.jsonwith production RPC URL - Configure production database (PostgreSQL recommended)
- Set up secret management (AWS Secrets Manager, HashiCorp Vault)
- Deploy API service with auto-scaling
- Configure load balancer and health checks
- Set up log aggregation (ELK, Datadog, etc.)
- Verify all monitoring and alerts
For production deployment guide, contact the development team.
MIT License - see LICENSE for details.
This project was built as a production trial assessment. For questions, issues, or contributions:
- Review existing documentation in
/docs - Check troubleshooting guide in RUNBOOK.md
- Create an issue with detailed context
- Follow existing code style and testing patterns
Built with industry-standard tools and libraries:
- Foundry - Fast Ethereum development toolkit
- OpenZeppelin - Secure smart contract library
- Express.js - Minimalist web framework
- ethers.js - Ethereum library
- Prometheus - Monitoring and alerting
- Grafana - Metrics visualization
- Docker - Containerization platform
Developer: Allan Robinson
Email: allan
GitHub: @Githaiga22
For operational issues in production, refer to the on-call procedures in RUNBOOK.md.
Note: This system demonstrates production-ready architecture and practices. For live deployment handling real financial transactions, additional legal compliance, security audits, and regulatory approvals are required.
Status: Ready for technical evaluation and live defense.