Testnet Deployment
Deploy the full Cortex stack (contracts + offchain services) to a public testnet.
Current Hosted Deployment
Frontend: https://cortex.projectaegis.ai
API: https://cortex-api.projectaegis.ai
Network: Base Sepolia, chain ID 84532
Indexer start block: 42716484
Live Contract Addresses
| Contract | Base Sepolia Address |
|---|---|
| AgentRegistry | 0x39e3a043532187af2ffe308154375fb662ccb0d6 |
| IntentBook | 0x16f7e7c4856bad4dcbE61400630087Dab75B229E |
| PolicyModule | 0x7120d45cbd6b5d079f39418e4f84880c634ef614 |
| AttestationRegistry | 0x62631b3f111424831Daa61beCB2E7A4bB0f71D2f |
| SolverRegistry | 0x21cf04BC864953DA4C79160f820F38eF74213EeA |
| AttestorRegistry | 0x40f2623F177a400a5928C99F107500049a884da0 |
| CommerceRegistry | 0xc4c014d9eb2d07ff6f7d2b8625e8cf3bc1150574 |
Recommended testnet: Base Sepolia — an OP Stack L2 with fast blocks (~2s), free faucets, and a good block explorer.
| Base Sepolia | OP Sepolia | |
|---|---|---|
| Chain ID | 84532 | 11155420 |
| RPC | https://sepolia.base.org | https://sepolia.optimism.io |
| Explorer | sepolia.basescan.org | sepolia-optimistic.etherscan.io |
Prerequisites
- Foundry —
forge,cast - Node.js >= 18
- PostgreSQL client tools —
psql - Three wallets — deployer, solver, agent (each needs testnet ETH)
1. Get Testnet ETH
Fund your deployer wallet with Base Sepolia ETH from any of these faucets:
- Alchemy Faucet — requires free Alchemy account
- Coinbase Developer Platform — requires Coinbase account
- thirdweb Faucet — no account required
2. Configure Environment
cp ops/.env.testnet.example ops/.env.testnetEdit ops/.env.testnet with your values:
RPC_URL=https://sepolia.base.org
DATABASE_URL=postgres://user:pass@host:5432/cortex
DEPLOYER_KEY=0x<your-deployer-private-key>
SOLVER_PRIVATE_KEY=0x<your-solver-private-key>
AGENT_PRIVATE_KEY=0x<your-agent-private-key>Never commit private keys. The .env.testnet file is gitignored.
3. Deploy Contracts
source ops/.env.testnet
./ops/deploy-testnet.shDeploys AgentRegistry, IntentBook, PolicyModule, AttestationRegistry, SolverRegistry, AttestorRegistry, and CommerceRegistry to Base Sepolia. Contract addresses are written to ops/.env.testnet.
4. Set Up Postgres
You need a Postgres instance accessible from wherever you run the services.
- Railway — simplest option, supports Node.js + Postgres in one platform
- Neon — serverless Postgres with a free tier
- Supabase — managed Postgres with a generous free tier
Copy the connection string and update DATABASE_URL in ops/.env.testnet.
5. Start Services Locally
source ops/.env.testnet
ENV_FILE=ops/.env.testnet ./ops/start-services.shBuilds services, runs idempotent migrations, and starts the indexer, solver, and API.
6. Manual Service Commands
Source the testnet env and start each service:
source ops/.env.testnet
# Indexer — polls Base Sepolia for events, writes to Postgres
cd indexer && npm run build && node dist/src/index.js
# Solver — watches IntentSubmitted, simulates, fills
cd solver && npm run build && node dist/src/index.js
# API — REST server on port 3001
cd api && npm run build && node dist/src/index.jsOr as background processes:
source ops/.env.testnet
cd indexer && npm run build && nohup node dist/src/index.js > ../ops/indexer.log 2>&1 &
cd ../solver && npm run build && nohup node dist/src/index.js > ../ops/solver.log 2>&1 &
cd ../api && npm run build && nohup node dist/src/index.js > ../ops/api.log 2>&1 &7. Verify
Check the block explorer
Visit https://sepolia.basescan.org/address/<AGENT_REGISTRY_ADDRESS> to confirm the contract is deployed.
Hit the API
# Health check
curl http://localhost:3001/health
curl http://localhost:3001/analytics/commerce
# List agents
curl http://localhost:3001/agents?owner=0x0000000000000000000000000000000000000000
# List open intents
curl http://localhost:3001/intents?status=openHosted API checks:
curl https://cortex-api.projectaegis.ai/health
curl https://cortex-api.projectaegis.ai/analytics/commerceStart the dashboard
cd web
NEXT_PUBLIC_API_URL=http://localhost:3001 npm run devOpen http://localhost:3000/dashboard. Protocol fees should show 0until a future fee switch is intentionally added.
Hosted dashboard: https://cortex.projectaegis.ai/dashboard.
8. AWS Deployment
The hosted deployment runs on AWS account 159077623001 (SSO profile node.admin,us-east-2): the API and indexer run on the shared sre-adara EKS cluster behind a dedicated cortex ALB at cortex-api.projectaegis.ai, the web app is a static export on S3 + CloudFront at cortex.projectaegis.ai, and Postgres is RDS cortex-postgres. K8s manifests live in infra/k8s/; the web stack is infra/aws-web/.
aws sso login --profile node.admin
aws eks update-kubeconfig --name sre-adara --region us-east-2 --profile node.admin
# Build + push ARM64 images, then deploy to EKS
export AWS_PROFILE=node.admin AWS_REGION=us-east-2
REG=159077623001.dkr.ecr.us-east-2.amazonaws.com
aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin "$REG"
docker buildx build --platform linux/arm64 -f api/Dockerfile -t "$REG/cortex-api:latest" --push .
docker buildx build --platform linux/arm64 -f indexer/Dockerfile -t "$REG/cortex-indexer:latest" --push .
kubectl apply -f infra/k8s/
kubectl rollout restart deployment/cortex-api deployment/cortex-indexer -n cortex
# Web (S3 + CloudFront)
cd infra/aws-web && terraform init && terraform apply && cd ../..
cd web && NEXT_PUBLIC_API_URL=https://cortex-api.projectaegis.ai npm run build && cd ..
aws s3 sync web/out s3://cortex-web-159077623001 --deleteThe cortex-secrets Secret (DATABASE_URL) is created once — see infra/k8s/README.md. On Apple Silicon, Terraform must be a native darwin_arm64 build; an x86_64 binary under Rosetta times out loading the AWS provider.
Register a test agent
source ops/.env.testnet
cast send "$AGENT_REGISTRY_ADDRESS" \
"registerAgent(string,bytes,bytes32)" \
"ipfs://test-agent" \
"0xaabb" \
"0x0000000000000000000000000000000000000000000000000000000000000001" \
--rpc-url "$RPC_URL" \
--private-key "$AGENT_PRIVATE_KEY"Wait a few seconds for the indexer, then query curl http://localhost:3001/agents/1.
Alternative: OP Sepolia
The same steps apply to OP Sepolia. Change:
RPC_URL=https://sepolia.optimism.ioThe deploy script auto-detects the chain ID. Use the OP Sepolia explorer at sepolia-optimistic.etherscan.io.
Troubleshooting
- Deploy fails with “insufficient funds”: Get more testnet ETH from a faucet. Deployment costs ~0.01 ETH.
- Indexer not picking up events: Check that
RPC_URLand contract addresses match. The indexer may take 5-10 seconds. - Solver not filling intents: Verify
SOLVER_PRIVATE_KEYhas testnet ETH. Checkops/solver.log. - Database connection refused: Ensure Postgres is accessible and
DATABASE_URLis correct. Test withpsql "$DATABASE_URL" -c "SELECT 1".