Sentinel TreasuryDocs

For developers

For developers

Everything an integrator or auditor needs to verify Sentinel's claims independently — the on-chain contract interface, the verify-root-locally algorithm, the export format, and the configured testnet addresses.

EvidenceRegistry interface

A minimal append-only contract. Permissionless: anyone may call it, but records are isolated per msg.sender.

anchor
anchor(bytes32 batchId, bytes32 root) — writes anchors[msg.sender][batchId]. Reverts on ZeroRoot, ZeroBatchId, or AlreadyAnchored.
verify
verify(address customer, bytes32 leaf, bytes32[] proof, bytes32 batchId) → bool — permissionless sorted-pair Merkle inclusion check against the customer's anchored root. Returns false if no anchor exists.
getAnchor
getAnchor(address customer, bytes32 batchId) → Anchor — full read of an anchor record (root, timestamp, blockNumber).
event
EvidenceAnchored(address indexed customer, bytes32 indexed batchId, bytes32 root, uint64 timestamp, uint64 blockNumber)

Verify a root locally

The trust-minimizing step. Before a Safe owner signs an anchor proposal, they recompute the Merkle root entirely client-side from their own audit-log export and compare it against the proposed root. A mismatch is surfaced before any signing affordance is enabled. The algorithm:

  • For each entry, recompute the leaf: keccak256(canonical_json({...payload, _prev_hash, _customer})). Canonical JSON = sorted keys, no whitespace, UTF-8.
  • Re-walk the chain: each entry's prev_hash must equal the previous entry's recomputed entry_hash; the first entry chains to bytes32(0).
  • Merkle-root the leaves with commutative sorted-pair keccak256. This matches OpenZeppelin's MerkleProof.verifyCalldata, so a proof that verifies locally also verifies on-chain via EvidenceRegistry.verify.

The browser implementation and the policy-service generator share the exact same canonical-JSON + sorted-pair algorithm, so a clean local round-trip is also a self-test of the implementation.

Audit-log export

The primary disclosure artifact is an exportable hash-chained audit log as NDJSON (one canonical entry per line, with its prev_hash and entry_hash). Any third party holding the export can re-walk the chain, recompute leaves, and recompute the root of any batch window — without trusting Sentinel. The on-chain anchor strengthens third-party verifiability; it does not replace the export.

Configured testnet addresses

These addresses are the ones the demo is configured to read on HashKey testnet (Chain ID 133). They are not claimed as official or canonical; the KYC SBT address in particular is treated as the configured contract pending HashKey confirmation. All addresses are environment variables in the codebase — never hard-coded.
EvidenceRegistry
0xDF1470Cb919a302a1Ec5C49D6138aB85b1005a9F (Blockscout source-verified)
KYC SBT (configured)
0x6447ae565a90Daa0BD0B36C03EEB7717Cd2BFd43
Demo Safe (1-of-1)
0xd0E2BDa7DB57630817B8Efd75e351356d2ddabC6