Current as of v2.8.0: Pharos Pacific Mainnet (chain 1672), Anvita Flow hosted agent, live contracts.
SafeHands is the transaction firewall for AI agent finance on Pharos Pacific Mainnet: a deterministic policy engine that evaluates every agent action (payments, approvals, swaps, x402 calls, tokenized-asset moves) before the signature and returns ALLOW / BLOCK / REQUIRE_CONFIRMATION / PREPARE_ONLY with a plain-English reason. The hosted deployment is read-only and zero-custody: it holds no keys, signs nothing, and broadcasts nothing on its own.
For the Real-Fi & RWA angle (how the attestation ledger, risk registry, token verification, and USDC settlement rails serve tokenized real-world assets), see REALFI_RWA_ALIGNMENT.md.
The fully-hosted, zero-custody agent is live on Anvita Flow as safehands (Agent Carnival Phase 2). Any Steward Agent on the marketplace can discover and call it: no server, no keys, no custody. To try the engine on your own machine without cloning:
npx -y safehands-pharos --demoRun the read-only reference backend locally, then hit it over HTTP:
npm ci && npm run build
node dist/api/server.js # read-only API on http://localhost:4022
# Service health
curl -s http://localhost:4022/health
# Public network config (chain 1672)
curl -s http://localhost:4022/public-config
# A real preflight decision: unlimited approval → BLOCK
curl -s -X POST http://localhost:4022/tools/safehands_preflight_check \
-H "content-type: application/json" \
-d '{"actionType":"approve_token","chainId":1672,"approvalToken":"USDC","spender":"0x000000000000000000000000000000000000dEaD","approvalAmount":"max"}'
# On-chain reputation of the deployer (live attestation contract)
curl -s -X POST http://localhost:4022/tools/get_agent_reputation \
-H "content-type: application/json" \
-d '{"address":"0x6730d3a2A217108AB53CCFe60ffdAd05D3C124e5"}'
# x402 paid endpoint. Fail-closed by default: without x402 config this returns 503.
# With X402_PAY_TO and a reachable external X402_FACILITATOR_URL set, it returns a
# real HTTP 402 challenge (mainnet USDC, eip155:1672).
curl -s -i http://localhost:4022/paid/risk-reportInteractive browser demo (while the local API runs): http://localhost:4022/demo.
AI agents making on-chain transactions need guardrails. Without safety checks, an agent could:
- Send funds to the wrong address or chain
- Approve unlimited token spending
- Sign drainer-crafted calldata it never actually decoded
- Execute swaps above policy limits
- Pay x402 invoices to SSRF targets
- Move a tokenized asset to an unvetted counterparty with no audit trail
SafeHands sits between the agent and the blockchain. Every action goes through preflight, risk scoring, policy checks, and authorization gates before execution is allowed; and, on the opt-in relayed-broadcast path (off by default), the broadcasts it relays are attested on-chain.
| Mode | Wallet | Where | Use case |
|---|---|---|---|
| Read-only preflight (default) | none | hosted or local | Safety checks, risk analysis, demos |
| User-signed | user's own | anywhere | SafeHands validates; user signs externally; verified broadcast + attestation |
| Managed execution | local encrypted wallet | self-hosted only | Full agent autonomy, opt-in; refused on public hosts by a boot guard |
| Env wallet (advanced) | PRIVATE_KEY in env |
local dev | Local mainnet development |
Network: Pharos Pacific Mainnet
Chain ID: 1672
Registry: 0x428e02bf85412e7242d991cd6725ec59e8b06c8d
Attestation: 0x71a7a87b3b1ab6d86204cad691bb32fd75b4588c
Owner: 0x6730d3a2a217108ab53ccfe60ffdad05d3c124e5
Explorer: https://www.pharosscan.xyz
- SafeHandsRegistry: authorized operators, Merkle risk roots,
verifyRiskRecordon-chain view. - SafeHandsAttestation: immutable, privacy-preserving verified-safe records plus
reputationOf()per-address reputation. Only hashed context is published (preparedTransactionHash,policyHash,metadataHash,txHash); never raw calldata, amounts, recipients, or keys.
Both are verifiable on the explorer; the reputation oracle has live attestations recorded by a dedicated attester key (0xe9F1d28C7136BbB1a57DA9852F216b8Cb39Eb888) that never signs user transactions.
npm ci && npm run build
npm run demo # or: npx -y safehands-pharos --demoThe hosted engine decodes approval/transfer/admin calldata offline: no simulation service, no third-party API. Feed it a drainer-style transaction and watch it block from the raw bytes:
# Unlimited approve to an unknown spender, hidden inside a "vault deposit": BLOCK
node anvita/safehands/scripts/safehands-engine.js analyze '{
"subjectType":"intent","action":"vault_deposit",
"walletAddress":"0x1111111111111111111111111111111111111111",
"vault":"0xcA11bde05977b3631167028862bE2a173976CA11",
"to":"0xc879C018Db60520f4355C26eD1a6D572CDAC1815",
"data":"0x095ea7b3000000000000000000000000000000000000000000000000000000000000deadffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}'
# -> recommendation: block, riskScore >= 90
# -> "UNLIMITED approve to an UNKNOWN spender (0x…dead); the spender could move the entire … balance"Contrast with a registry-verified protocol: trust comes only from first-party evidence (the project's own docs + on-chain checks, cited in the registry):
# Morpho Blue on Pharos, verified 2026-07-11 from Morpho's own addresses page
node anvita/safehands/scripts/safehands-engine.js analyze '{"subjectType":"contract","address":"0x18573fA18fd17dDfD790B4a5B5b2977aad3b4Efb"}'
# -> recommendation: allow, riskScore 5
# -> "Canonical registry contract: Morpho Blue (verified via official-docs citation + on-chain check)"Ecosystem names the registry recognizes but whose addresses are not yet published in their own docs (FaroSwap, Stargate, …) stay fail-closed: an unlimited approval to them blocks. That is policy, not a bug: recognition is never proof.
npm test # hermetic deterministic suite (no wallet, no RPC, no network needed)
npm run demo # 12 non-destructive demo scenarios
npm run test:contracts # 25 Hardhat Solidity tests (offline smoke fallback without a compiler)
npm run test:all # all combinedFocused suites also exist: test/x402-gate.test.ts (x402 payment gate with a mock facilitator) and test/risk-inclusion.test.ts (Merkle inclusion proof path), runnable via tsx --test <file>.
Action: send_payment
Chain ID: 1672 (Pharos Pacific Mainnet)
Amount: 0.001 PROS
-> Decision: ALLOW
Action: send_payment
Chain ID: 1 (Ethereum Mainnet)
-> Decision: BLOCK
-> Reason: chain 1 is not the configured Pharos target
Action: approve_token
Amount: unlimited / max
-> Decision: BLOCK
-> Reason: Unlimited approvals are blocked by default
Action: approve_token (finite amount, token not in the active registry)
-> Decision: REQUIRE_CONFIRMATION
-> tokenRegistry.status: unknown; human confirmation required
Action: x402_pay_and_fetch
URL: http://169.254.169.254/metadata (internal IP)
-> SSRF_BLOCKED
Action: x402_pay_and_fetch
Amount: -1 USDC
-> VALIDATION_ERROR
Policy: advanced
Action: swap 1000 PROS
-> within advanced maxSwapPROS: 1000
Policy: conservative
Action: swap 1000 PROS
-> exceeds conservative maxSwapPROS: 1
Policy: advanced · Action: payment on chainId 1 -> BLOCK (non-Pharos chain, regardless of policy)
Policy: advanced · Action: unlimited approval -> BLOCK (regardless of policy)
Policy: advanced · Action: x402 to internal IP -> BLOCK (SSRF, regardless of policy)
| Category | Tools |
|---|---|
| Safety preflight | safehands_preflight_check, safehands_x402_preflight, safehands_risk_report, safehands_wallet_health, explain_risk, token_registry_status |
| Risk registry (on-chain) | publish_risk_score, query_risk_registry, verify_risk_inclusion, get_agent_reputation |
| Risk + analysis | assess_risk, check_token_security, simulate_transaction, estimate_gas, check_allowance |
| Market + chain data | get_token_price, get_wallet_balance, get_gas_price, get_pool_info, get_transaction_status, get_execution_history, query_goldsky_subgraph, get_spv_proof |
| Execution (gated) | safehands_safe_execute, execute_swap, send_payment, approve_token, x402_pay_and_fetch |
| Agent policy | get_agent_policy, set_agent_policy |
| Managed wallet | create_agent_wallet, get_agent_wallet, get_agent_wallet_balance |
All 33 are exposed identically across MCP, HTTP, and CLI.
- Hosted mode (Anvita Flow) and the self-hosted read-only backend are zero-custody; execution, signing, managed wallets, and on-chain publishing are gated and disabled by default. A boot guard refuses managed/write execution on a public host.
- Managed-wallet encryption is AES-256-GCM, not KMS/Vault-grade; not intended for custody of large amounts, and not audited for production custody.
- GoPlus token security does not cover Pharos Atlantic Testnet (
688689). - DODO reverse routes can occasionally lack liquidity for exotic pairs.
- L1 risk-root committer automation and the DA-serving endpoint are roadmap; the on-chain read/verify path (
verify_risk_inclusion) is live. - The risk-root pipeline (queue, batch flush,
commitRiskRoot, inclusion verify) is functional end to end and the first production batch is committed on-chain: a registryqueryreportshasCommittedRoot:trueand returns a risk record sourced from the committed data-availability pointer. The attestation contract also has live on-chain usage.