🟢 Live Demo: sentinel-vault-ai.vercel.app 🎥 Video Demo: youtu.be/G0hb350hL7k
AI reputation is usually cosmetic. SentinelVault turns it into a transparent, code-enforced economic constraint.
The more trust the agent earns, the more capital it is allowed to deploy. Bad agents can't trade.
Agent starts with minimal seed reputation to bootstrap activity. Trust must be earned through successful trades — every decision is logged with reasoning.
After each trade decision, the agent generates an artifact that captures its reasoning, confidence score, and risk context. If PINATA_JWT is configured, the artifact is pinned to IPFS; otherwise it is saved locally. Either way, the artifact is linked to the executed transaction, creating an auditable trail of agent decisions.
| Contract | Address |
|---|---|
| SentinelVault v2 | 0x3CEb1CEFa9baaA1b6C62508560a689AeF40F4B48 |
| UniswapV3Adapter | 0x5f3E3c7c6ab9dB110185cd05d94D2674644C31C6 |
| ReputationRegistry | 0x5e6915AB82aeA458078734435DFE46b0fC4964B9 |
| Policy | 0x1d1380eB6CEbAC6FAEFab5C124F5DA20683e4493 |
| OracleVerifier | 0x5634150a2A71aE6516b0c92e0f4943B8109821AD |
| TrustGate | 0x508e14620690203AD6Cb8ab65D77F87e049CadD1 |
| Agent | 0x79a4Ca003893a3E80bbdBb57f59b9745018106f6 |
| ERC-8004 Identity | BaseScan (minted via Synthesis platform registration, not implemented in this repo) |
1. ReputationRegistry.sol
getReputation(agent)→ uint256reportOutcome(agent, stakeAmount, success, intentHash, reason, confidence)→ updates score- Asymmetric stake/burn model:
- Success →
reputation += stake * 1.5 - Failure →
reputation -= stake * 2.0 - Agent must maintain >57% win rate just to hold position
- Trust is hard to earn, easy to lose
- Success →
ReputationUpdatedevent with agent, delta, newScore, intentHash
2. Policy.sol
getMaxPosition(agent)→ uint256 (based on reputation)checkIntent(agent, amount, reputationStake)→ (bool allowed, string reason)- Formula:
maxPosition = base + rep * multiplier(capped byglobalMax)- Config:
base = 100, multiplier = 5, globalMax = 1000 - rep 0 → 100 | rep 10 → 150 | rep 50 → 350 | rep 100 → 600 | rep 200 → 1000 (cap)
- Config:
- Daily limit enforcement per agent
- Human Guardian: contract owner can
pauseAgent()/resumeAgent()— AI is autonomous but human stays in control.
3. SentinelVault v2 — Intent-Verified Execution Engine
- Not a generic forwarder. Identity-aware, intent-verified, adapter-based, balance-checked execution engine.
- Agent signs EIP-712
TradeIntent→ vault verifies signature on-chain → policy enforced → typed adapter executes swap → balance delta verified → oracle records atomically executeIntent(intent, signature, adapter, adapterData)— the production-grade path:- EIP-712 signature verification (agent identity bound to execution)
- Nonce tracking (replay protection)
- Deadline enforcement (freshness)
- Token allowlist (only approved tokenIn/tokenOut)
- Adapter allowlist (no arbitrary calldata — each DEX gets a typed adapter)
- Max value per trade limit
- Policy enforcement (reputation constrains capital)
- Balance delta verification (don't trust adapter return values)
- Oracle recording (atomic, tied to execution)
- Vault IS the execution identity: quote, custody, and routing all bound to vault address
- Owner can
pause(),withdraw(), manage adapters/tokens/limits — guardian retains control
4. OracleVerifier.sol
- Chainlink ETH/USD price feed for objective trade verification
recordTrade()locks entry price from Chainlink (called by vault after successful swap)verifyOutcome()reads exit price afterminWait(configurable; 4h in production, 60s for validation) and calls ReputationRegistry
5. TrustGate.sol
- Any protocol can set a minimum reputation threshold and gate access to agents that haven't earned enough trust
- Deployed example of how ReputationRegistry enables permissionless trust queries
Agent stakes reputation on every trade — confidence becomes economic commitment:
Agent confidence: 0.85 → stakes 15 rep
Agent confidence: 0.35 → stakes 3 rep
Success → reputation += stakeAmount * 1.5
Failure → reputation -= stakeAmount * 2.0
Contract enforces: require(reputation >= stakeAmount) — agent can't stake what it hasn't earned.
ReputationRegistry is a public contract — any agent or protocol can query trust before interacting:
uint256 rep = registry.getReputation(counterpartyAgent);
require(rep >= minimumTrust, "Agent not trusted enough");No centralized registry. No API keys. Reputation lives on-chain and is verifiable by anyone, permissionlessly.
Trade outcomes are verified by Chainlink ETH/USD price feed:
- Agent executes swap, then calls
OracleVerifier.recordTrade()→ entry price locked from Chainlink - After
minWaitelapses (configurable per deployment), an authorized verifier callsOracleVerifier.verifyOutcome(agent)→ exit price read from Chainlink - OracleVerifier compares prices and calls
ReputationRegistry.reportOutcome()
Entry and exit prices come from the oracle. Verification can be called by the agent or by a separate authorized verifier process.
AI reasoning (Claude Opus) → decides LONG / SHORT / SKIP
↓
EIP-712 TradeIntent signed off-chain
↓
SentinelVault.executeIntent() ← TRUST BOUNDARY
├── 1. EIP-712 signature verified ON-CHAIN (agent identity bound)
├── 2. Nonce checked (replay protection)
├── 3. Deadline checked (freshness)
├── 4. Token allowlist checked
├── 5. Adapter allowlist checked (no arbitrary calldata)
├── 6. Max value per trade checked
├── 7. Policy.sol enforced (reputation constrains capital)
├── 8. UniswapV3Adapter executes swap (vault→adapter→SwapRouter02)
├── 9. Balance delta verified (don't trust adapter)
└── 10. OracleVerifier.recordTrade() — atomic, tied to execution
↓ (after minWait elapses)
OracleVerifier.verifyOutcome(agent) → Chainlink exit price → reputation update
↓
Artifact → IPFS (decision trail)
Architecture: The vault is the execution identity — quote, custody, and routing are all bound to the vault address. Instead of forwarding arbitrary calldata, the vault calls typed swap adapters that know each DEX's semantics. The UniswapV3Adapter routes through SwapRouter02 (which supports contract callers, unlike the Trading API executor). This eliminates the identity mismatch that breaks generic forwarding patterns.
- Agent produces EIP-712
TradeIntent(agent, market, side, amount, reputationStake, nonce, timestamp) - EIP-712 intents are signed off-chain and verified on-chain by the vault before execution
- For the hackathon demo, Risk Router responses are simulated when
RISK_ROUTER_URLis unset - On acceptance → vault executes swap via UniswapV3Adapter → txHash on Sepolia
Trade execution via two paths:
- Vault path (production): SentinelVault → UniswapV3Adapter → SwapRouter02. Adapter knows router semantics, builds correct calls, pins recipient to vault. Contract callers fully supported.
- Quote API: Uniswap Trading API (
https://trade-api.gateway.uniswap.org/v1/) used for price quotes and gas estimates. - LONG swaps USDC → ETH, SHORT swaps ETH → USDC
- Swap amounts are derived from the agent's reputation-scaled
maxPosition(0.0003–0.003 ETH range on testnet).
- JSON artifact per decision pinned to IPFS via Pinata
- On-chain data is limited to events (
TradeExecuted,ReputationUpdated) and oracle price records - Full reasoning, confidence scores, and trade context live in IPFS artifacts
- If
PINATA_JWTis not set, IPFS pinning is silently skipped (artifacts still saved locally)
{
"volatility": 0.82,
"trend": "weak",
"drawdown": 0.14,
"confidence": 0.31,
"mode": "VAULT",
"stakeAmount": 3,
"reason": "High volatility and weak trend detected. Reducing exposure and preserving capital.",
"txHash": "0x...",
"ipfsCid": "Qm...",
"timestamp": 1234567890
}| Theme | How SentinelVault addresses it |
|---|---|
| Agents that pay | Reputation enforces spending limits — vault verifies EIP-712 intent on-chain, enforces policy, executes via typed adapter, verifies balance delta, records on oracle atomically. Full reasoning in IPFS artifacts. |
| Agents that trust | On-chain reputation score = verifiable trust without centralized registry. ERC-8004 identity via Synthesis platform. |
| Agents that cooperate | EIP-712 intents (off-chain signed) + IPFS artifacts = auditable decision trail |
| Agents that keep secrets | Weak fit: minimizes on-chain footprint, but does not implement private payments, ZK auth, or encrypted coordination. |
- Solidity + Hardhat (contracts)
- Node.js / TypeScript (agent runtime)
- Claude (reasoning engine)
- Kiro CLI (development orchestration)
- Sepolia testnet
- Uniswap Trading API (quotes and gas estimates; execution via adapter → SwapRouter02)
- Chainlink price feeds (oracle verification)
- EIP-712 typed data signing (off-chain signing, on-chain verification before execution)
- IPFS / Pinata (artifact storage)
sentinel-vault/
├── contracts/
│ ├── ReputationRegistry.sol
│ ├── Policy.sol
│ ├── OracleVerifier.sol # Chainlink-verified outcomes
│ ├── TrustGate.sol # multi-agent trust gate
│ ├── SentinelVault.sol # intent-verified execution engine (trust boundary)
│ ├── interfaces/
│ │ └── ISwapAdapter.sol # typed adapter interface
│ ├── adapters/
│ │ └── UniswapV3Adapter.sol # Uniswap V3 SwapRouter02 adapter
│ └── mocks/
│ ├── MockSwapAdapter.sol # vault test mock
│ └── MockSwapRouter.sol # adapter test mock
├── agent/
│ ├── index.ts # main loop (vault v2 executeIntent path)
│ ├── confidence.ts # multi-timeframe → confidence score
│ ├── market.ts # Binance multi-timeframe data
│ ├── intent.ts # EIP-712 TradeIntent builder
│ ├── reasoning.ts # Claude reasoning engine
│ ├── riskRouter.ts # Risk Router adapter (simulated for demo)
│ ├── ipfs.ts # Pinata IPFS pinning
│ └── uniswap.ts # Uniswap Trading API
├── test/
│ ├── sentinelVault.test.ts # 46 vault v2 tests
│ └── uniswapV3Adapter.test.ts # 7 adapter tests
├── scripts/
│ ├── deploy-all.ts # unified deploy
│ ├── deploy-vault-v2.ts # vault v2 + adapter
│ ├── validate-sepolia.ts # full Sepolia validation suite
│ └── lifecycle-proof.ts # trade → oracle → verify → reputation delta
├── VALIDATION.md # on-chain evidence with tx hashes
├── validation-report.json
├── lifecycle-proof.json
├── sample-artifacts/ # real agent decision artifacts
├── hardhat.config.ts
├── .env.example
└── README.md
The agent runs on a VPS (pm2 managed), executing real Uniswap swaps on Sepolia at every 4-hour UTC candle close.
Full end-to-end validation against real Uniswap V3 on Sepolia — see VALIDATION.md for complete evidence.
| Test | Result | TX Hash |
|---|---|---|
| SHORT (ETH→USDC) | ✅ 0.0005 ETH → 2.75 USDC | 0xf7f5e959... |
| LONG (USDC→ETH) | ✅ 0.5 USDC → 0.00009 ETH | 0xc9939be3... |
| verifyOutcome | ✅ rep 32→22 (delta -10) | 0x4384674f... |
| DeadlinePassed | ✅ Correctly reverted | — |
| NonceUsed | ✅ Correctly reverted | — |
| TokenNotAllowed | ✅ Correctly reverted | — |
| AdapterNotAllowed | ✅ Correctly reverted | — |
| ExceedsMaxValue | ✅ Correctly reverted | — |
53 local tests passing (46 vault + 7 adapter). 14 trades executed on-chain.
| Tick | Decision | Tx Hash | IPFS Artifact |
|---|---|---|---|
| Mar 16 20:00 UTC | LONG (150 USDC, stake 3 rep) | 0xdbda32... |
QmVT9AQ... |
| Mar 17 00:00 UTC | SKIP (conflicting signals) | — | QmQ92wn... |
| Mar 17 04:00 UTC | SKIP (overbought RSI 71.57) | — | QmbQeom... |
| Mar 17 08:00 UTC | SKIP (overbought RSI 72.22) | — | QmNtJZ7... |
Oracle verification in action: After the Mar 16 20:00 LONG trade, the Chainlink oracle verified the outcome at Mar 17 04:00 — ETH price dropped, reputation went from 40 → 34 (stake 3 × 2.0 = 6 burned).
Sample artifacts are in sample-artifacts/ for inspection.
npm install
npx hardhat compile
npx hardhat test # 53 tests (46 vault + 7 adapter)
# deploy vault v2 + adapter
npx hardhat run scripts/deploy-vault-v2.ts --network sepolia
# run Sepolia validation suite
npx ts-node scripts/validate-sepolia.ts
# run full lifecycle proof (trade → oracle → verify → reputation delta)
npx ts-node scripts/lifecycle-proof.ts
# run agent (dry mode)
DRY_RUN=true npx ts-node agent/index.ts
# run agent (live testnet)
npx ts-node agent/index.tsNote: The agent only runs in vault mode. VAULT_ADDRESS is required so all live executions pass through the policy-enforced trust boundary.
- Risk Router is simulated for the hackathon demo (no live endpoint)
verifyOutcome(agent)depends on an authorized caller process; not yet fully automated on-chain- ERC-8004 identity was minted via Synthesis platform registration, not implemented in this repo
- Trade sizing on testnet is proportionally scaled (0.0003–0.003 ETH) — not representative of production amounts
minAmountOutis derived from an off-chain quote (Uniswap Trading API); the trust assumption is that the quote source is honest at signing time- Approval-reset patterns and adversarial ERC-20 edge cases are not yet hardened for production
Signed off-chain by the agent, verified on-chain by the vault before execution:
{
"domain": {
"name": "SentinelVault",
"version": "2",
"chainId": 11155111,
"verifyingContract": "0x3CEb1CEFa9baaA1b6C62508560a689AeF40F4B48"
},
"types": {
"TradeIntent": [
{ "name": "agent", "type": "address" },
{ "name": "tokenIn", "type": "address" },
{ "name": "tokenOut", "type": "address" },
{ "name": "amountIn", "type": "uint256" },
{ "name": "minAmountOut", "type": "uint256" },
{ "name": "policyAmount", "type": "uint256" },
{ "name": "deadline", "type": "uint256" },
{ "name": "nonce", "type": "uint256" },
{ "name": "isLong", "type": "bool" },
{ "name": "confidence", "type": "uint256" },
{ "name": "reputationStake", "type": "uint256" }
]
}
}MIT
