Skip to content

KanishJebaMathewM/SentryPay-HashKey

Repository files navigation

SentryPay — Autonomous On-Chain Parametric Payouts

AI proposes. The chain disposes.

SentryPay is an autonomous verdict engine that watches real-world risk signals and — without any human approval step — executes an on-chain payout through HSP, with every decision's reasoning permanently logged for audit.

Submitted to the HashKey Chain Horizon Hackathon (AI Track) · July 2026


The Idea in One Paragraph

A policy defines a monitored metric, a trigger threshold, and a payout amount. Premiums are deposited into an on-chain pool. An off-chain AI monitor continuously polls the metric, runs it through a deterministic weighted-factor confidence engine, and submits a signed verdict on-chain. A smart contract independently re-checks the threshold — if both the AI's verdict and the contract's own calculation agree the condition is met, the contract calls the HSP router to settle the payout. No human is in the loop, and every verdict (triggered or not) is permanently logged with its contributing factors.


Live Deployment (HashKey Chain Testnet — Chain ID 133)

Contract Address
PolicyRegistry 0xe68A4F963B294a3B0f44C3deC41759918CA8702c
ProtectionPool 0x619B9465d6dD6EBAc4Dff383E9d7fe881284cD5a
PayoutTrigger 0x7FEb9FDcd1C4596FD3fb912d79c75a5B2Cf06DCA
HSP Router 0xA8E6fDa725895D40d56215077Ace2949eB2caf83

RPC: https://testnet.hsk.xyz · Explorer: https://testnet-explorer.hsk.xyz Deploy block (event-scan start): 30257900

Where it runs

Component Host Notes
Dashboard (React SSR) Vercel Reads verdicts/payouts directly from the chain in the browser.
AI Monitor GitHub Actions (cron, every 5 min) Runs one poll cycle per invocation (RUN_ONCE), submits a signed verdict on-chain.
Shared state HashKey Chain (testnet) The two services never talk directly — the chain is the single source of truth. Monitor writes verdicts; dashboard reads them.

See docs/CLOUD_DEPLOYMENT.md for the full free-hosting setup.


Architecture

 AI Monitor (GitHub Actions cron)        HashKey Chain (testnet)         Dashboard (Vercel)
 ────────────────────────────────        ───────────────────────         ──────────────────
 fetchMetric.ts        ┐                  PolicyRegistry.sol
 confidenceEngine.ts   ├─ submitVerdict ─►ProtectionPool.sol       ┌────► chain-reader.ts
 runner.ts (RUN_ONCE)  ┘                  PayoutTrigger.sol         │      (ethers getLogs)
                                                │                   │
                                                ▼                   │
                                          HSP Router → Beneficiary  │
                                                │                   │
                                          (events emitted) ─────────┘

The monitor and dashboard never call each other. They agree only because both point at the same contract addresses on the same chain — the monitor writes VerdictLogged / PayoutExecuted events, and the dashboard reads them via eth_getLogs on every refresh.

Key Design Choices

  1. Deterministic confidence engine, not an LLM. The trigger decision uses a rule-based weighted-factor scorer. Same inputs → same output, always. The weights and factors are visible in source code and hashed on-chain. This is a deliberate choice for money-moving decisions — reproducibility and auditability over opaque AI calls.

  2. Chain re-validates independently. PayoutTrigger.sol does not trust the AI's offchainTriggered flag alone. It re-checks the metric value against the stored threshold itself. The contract — not the script — is the final arbiter.

  3. Always log, fail closed. Every poll cycle produces a logged VerdictLogged event, whether triggered or not. If the data source is unavailable, the cycle is skipped entirely — no verdict submitted, no false negatives dressed up as considered "no" decisions.

  4. No double-pay. Once a policy is settled, any further verdict submissions for it simply log without executing another payout.


Repository Structure

SentryPay/
├── contracts/          Solidity contracts + Hardhat setup
│   ├── src/
│   │   ├── PolicyRegistry.sol     Policy definitions
│   │   ├── ProtectionPool.sol     Premium custody + HSP disburse
│   │   ├── PayoutTrigger.sol      On-chain decision gate
│   │   └── MockHSPRouter.sol      Local dev only — NEVER deployed to mainnet
│   ├── interfaces/
│   │   └── IHSPRouter.sol
│   ├── test/                      Hardhat/Mocha contract tests
│   └── scripts/
│       ├── deploy-local.ts        Deploy to a local Hardhat node
│       ├── deploy-testnet.ts      Deploy to HashKey testnet (Chain 133)
│       ├── deploy-mainnet.ts      Deploy to HashKey mainnet (Chain 177)
│       ├── seed-demo-policy.ts    Create a demo policy for end-to-end testing
│       └── verify.ts              Blockscout source verification
│
├── monitor/            AI monitor service (Node.js + TypeScript)
│   ├── src/
│   │   ├── types.ts               Shared type definitions
│   │   ├── fetchMetric.ts         Data source polling
│   │   ├── confidenceEngine.ts    Weighted-factor verdict engine
│   │   ├── submitVerdict.ts       On-chain verdict submission (native rail)
│   │   ├── runner.ts              Poll loop (persistent, or single-pass via RUN_ONCE)
│   │   ├── hspMandate.ts          EIP-712 HSP Mandate build + sign (USDC rail)
│   │   ├── hspRelay.ts            Watches PayoutExecuted, settles USDC via HSP
│   │   ├── settleOnce.ts          One-shot HSP USDC settlement (dry-run helper)
│   │   ├── demoTrigger.ts         CLI staged-trigger helper (BELOW policies)
│   │   └── checkBalances.ts       Wallet gas / USDC balance preflight
│   └── test/
│       ├── confidenceEngine.test.ts
│       └── hspMandate.test.ts     HSP mandate-hash vectors
│
├── .github/workflows/
│   └── monitor.yml     Free cron host — runs the monitor once every 5 min
│
├── api/
│   └── index.mjs       Vercel serverless entry — bridges the SSR handler to Node
├── vercel.json         Vercel build + routing config (SSR)
│
├── src/                React frontend (TanStack Start / Router)
│   ├── lib/
│   │   ├── mock-data.ts           Demo data (fallback when chain not connected)
│   │   ├── chain-config.ts        Network config + contract addresses
│   │   ├── chain-reader.ts        Ethers.js read-only event / state reader
│   │   ├── chain-writer.ts        Signed writes: createPolicy / deactivate / deposit
│   │   ├── wallet.ts              EIP-1193 injected-wallet plumbing
│   │   ├── demo-trigger.ts        Server-function wrapper for the staged demo trigger
│   │   └── demo-trigger.server.ts SERVER-ONLY — signs the demo verdict (AI signer key)
│   ├── hooks/
│   │   ├── use-chain-data.ts      TanStack Query hooks for live chain data
│   │   ├── use-wallet.tsx         Wallet connection state (React context)
│   │   ├── use-is-owner.ts        On-chain owner gating for the Admin area
│   │   ├── use-create-policy.ts   / use-deactivate-policy.ts / use-deposit-premium.ts
│   │   ├── use-demo-trigger.ts    Fires the staged demo trigger
│   │   └── use-owner-state.ts     Local "simulate owner" toggle (mock mode only)
│   ├── components/                TopNav, Footer, and the ui-sentry design kit
│   └── routes/                    Page components (Overview, Policies, Verdicts, Payouts, Admin)
│
├── docs/
│   ├── DEPLOYMENT.md              Native + HSP USDC settlement runbook
│   └── CLOUD_DEPLOYMENT.md        Free Vercel + GitHub Actions hosting setup
├── .env.example        Environment variable template
└── README.md

Quick Start

1. Install dependencies

# Frontend
npm install

# Contracts
cd contracts && npm install

# Monitor
cd monitor && npm install

2. Configure environment

cp .env.example .env
# Fill in DEPLOYER_PRIVATE_KEY, AI_SIGNER_PRIVATE_KEY, RPC_URL, etc.

3. Run contract tests

cd contracts
npx hardhat test

4. Deploy locally (Hardhat node)

# Terminal 1 — start local node
cd contracts && npx hardhat node

# Terminal 2 — deploy
cd contracts && npx hardhat run scripts/deploy-local.ts --network localhost

5. Start the monitor (local dev with MOCK data source)

cd monitor
METRIC_SOURCE_TYPE=MOCK MOCK_SCENARIO=gradual_decline npx tsx src/runner.ts

6. Start the frontend

npm run dev

Deployment Runbook

1. Testnet Deployment (Chain ID 133)

Follow this step-by-step sequence to deploy, verify, and run SentryPay on HashKey Chain Testnet:

  1. Fund your wallets: Go to the HSP Sandbox Faucet and paste the public addresses for both your Deployer and AI Signer wallets to request testnet HSK and test USDC.
  2. Deploy the contracts:
    cd contracts
    npx hardhat run scripts/deploy-testnet.ts --network hashkeyTestnet
    Note: If HSP_ROUTER_ADDRESS_TESTNET is left blank in your .env, this script will automatically deploy and wire a MockHSPRouter contract so you can test for free.
  3. Configure environment: The deploy script generates a deployments.testnet.env file. Copy the printed variables directly into your root .env file.
  4. Verify the contracts on Blockscout:
    npx hardhat run scripts/verify.ts --network hashkeyTestnet
  5. Test the End-to-End flow:
    • Start the frontend: npm run dev and deposit some test HSK premium.
    • Start the monitor:
      cd ../monitor
      npm run dev
    • Watch the monitor evaluate the mock scenario, log the verdict on-chain, and execute the payout via the Mock HSP Router.

2. Mainnet Deployment (Chain ID 177)

Once testnet testing is successful, deploy to HashKey Chain Mainnet for judge review:

  1. Fund your Deployer wallet: Ensure your deployer wallet is funded with real HSK on mainnet to pay for contract deployment gas.
  2. Set the HSP Router Address: Verify the mainnet adapter/router address from hsp-hackathon.hashkeymerchant.com/docs (default: 0x467AaF53D68A1aF0E480119330a91176251b5c40) and set it as HSP_ROUTER_ADDRESS_MAINNET in your .env.
  3. Deploy the contracts:
    cd contracts
    npx hardhat run scripts/deploy-mainnet.ts --network hashkeyMainnet
    The script has a 5-second safety countdown abort window and strictly checks that it is executing on Chain ID 177.
  4. Verify the contracts:
    npx hardhat run scripts/verify.ts --network hashkeyMainnet
  5. Update environment variables: Copy the variables from the generated deployments.mainnet.env file into your root .env to switch the frontend and monitor to mainnet.
  6. Run the live monitor: Start the monitor service. It will poll and log real VerdictLogged events to the blockchain, building on-chain credibility for the judges.
  7. Publish the dashboard: The frontend is a TanStack Start SSR app (not a static bundle), so it deploys to Vercel as a serverless function, not a dist/ upload. See docs/CLOUD_DEPLOYMENT.md for the exact Vercel + GitHub Actions setup. Push to main and Vercel builds automatically:
    cd ..
    git push        # Vercel auto-deploys; the monitor runs on GitHub Actions cron

HSP Integration

SentryPay supports two payout rails, selected per network via the settleOnchain flag. The full runbook for both is in docs/DEPLOYMENT.md.

Rail settleOnchain Token How funds move Used for
On-chain native true (default) HSK ProtectionPool.disburse()IHSPRouter.settle() → beneficiary Local + testnet demo
HSP off-chain false USDC Payer wallet USDC.transfer; HSP adapter observes + signs a receipt Mainnet (real HSP)

On-chain native rail. ProtectionPool.disburse() calls IHSPRouter.settle() to move native HSK to the beneficiary. If the HSP call reverts for any reason, disburse() falls back to a direct native transfer — the payout is never stuck. For local/testnet development, MockHSPRouter.sol is a drop-in replacement that simply forwards the native token; it is never deployed to mainnet (the mainnet deploy script has a hard code-check).

HSP off-chain (USDC) rail. HSP is zero-custody — no contract holds or routes funds. Here the on-chain trigger only authorizes the payout (emits PayoutExecuted); the monitor's relay (monitor/src/hspRelay.ts) then EIP-712-signs an HSP Mandate, does the actual USDC.transfer from the payer wallet, and posts an observation to the HSP Coordinator. The EIP-712 verifyingContract (0x…0001) is a signature domain, not a payable router — never place it in an HSP_ROUTER_ADDRESS_* field.


Demo Trigger Disclosure

The Policy detail page exposes a "Stage demo trigger" button. Clicking it submits a verdict whose metric value is chosen to satisfy the policy's stored trigger direction (ABOVE → comfortably over the threshold, BELOW → 0), so the demo works regardless of how the policy was configured. It uses the exact same contract path (PayoutTrigger.submitVerdict → executePayout → ProtectionPool.disburse → HSPRouter.settle) as an automatic trigger. Nothing is mocked or bypassed.

Because submitVerdict is onlyAiSigner, the verdict is signed server-side by src/lib/demo-trigger.server.ts using the AI signer key — that key never reaches the browser. The staged verdict is tagged demoTriggered: true in its off-chain factors JSON.

This is disclosed here and labeled in the UI specifically so judges can distinguish the staged path from the live autonomous one. The live monitor has been running against mainnet since deployment and its verdict log is visible on the Verdicts page.


Confidence Engine — Factor Breakdown

For the HSK Pool Liquidity Drain metric (BELOW direction: triggers when drain ≥ threshold):

Factor Weight What it measures
Magnitude 0.55 How far the current drain is relative to the threshold × 2
Persistence 0.30 How many of the last 3 polls also showed the condition met
Velocity 0.15 Whether the drain rate is accelerating (2nd derivative > 0)

The weighted sum produces confidenceScore (0–1). The policy's triggerConfidence field (0–100) is the minimum required to submit a triggering verdict. The on-chain factorsHash links to the off-chain JSON log for full factor inspection.


Security Notes

  • ProtectionPool.disburse() is nonReentrant and enforces checks-effects-interactions ordering.
  • PayoutTrigger.submitVerdict() is restricted to aiSigner only.
  • The AI signer wallet holds only enough HSK for gas — minimal blast radius.
  • No tx.origin used anywhere.
  • Owner and AI signer are separate keys (no shared key).
  • Integer thresholds are unit-tested to catch off-by-a-power-of-ten errors.

Deliberate Scope Cuts (not oversights)

  • Policy creation is owner-only. A production version would have permissionless policy creation with underwriting logic. Stated in PolicyRegistry.sol comments.
  • No gas optimization. Correctness over efficiency for a 3-day build.
  • Single metric per policy. Multi-metric generalization is a v2 roadmap item.
  • No formal governance. Admin-only for the hackathon.

Post-Hackathon Roadmap

  • Permissionless policy creation with on-chain underwriting rules
  • Multi-metric, multi-factor policy definitions
  • DAO governance for registry and pool parameters
  • IPFS pinning of the factors JSON for permanent off-chain audit trail
  • Chainlink/Pyth oracle integration as a corroborating data source
  • Gas-optimized contracts (Yul/assembly for hot paths)

About

AI agents move money autonomously, but the decision can't be trusted. SentryPay watches real-world risk, runs a deterministic verdict engine, and executes an on-chain HSP payout with no human in the loop — every verdict logged on-chain for audit.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors