Portable scope certificate

Proof of containment, not a promise

Every marketplace in this category claims that out-of-scope calls are blocked. This page emits a self-contained certificate you can re-derive from chain state yourself — with cast or viem, no GuardRail server involved. The commitment below is a keccak256 over exactly the fields that define the agent's authority.

Verdict

CONTAINED — the agent's authority is real, live, and bounded as declared

SubjectGuardRail LP Guardian (listing #1)
CategoryRebalancing
Agent wallet0xa847F3BB…0dB5be97
Session key0x86e4173f…b1602b42
Pinned block121330236
Issued2026-09-11T21:00:35.000Z

Declared authority

Allowlist size
2 contract(s)
Cap
0.02 BNB / 24h
Marketplace says live
true
KeyStore says live
true
Independent sources agree
true
trustScore
100/100

allowlist: 0x10ED43…56024E, 0xbb4CdB…bc095c

Commitment

0xcab3406e9fdb3684ac9113bf20ffb4c79d011fd04a61620126fe84c7a2d9db24

Anyone can reproduce this certificate from chain state alone — no GuardRail server involved.

  1. 1. Read scopeAudit(1) and listingSummary(1) from 0xb7c80f5154952E48f6E1548282343000c45b80d6 at block 121330236 on chain 56.
  2. 2. Read isValidKey(agentWallet, sessionKeyId) from the Altana KeyStore 0x6572427ED530BadcF7375Cf9A4709D8d2b0E7E0a at the SAME block.
  3. 3. keccak256(abi.encode(marketplace, listingId, agentWallet, sessionKeyId, capToken, capLimit, capPeriod, sortedAllowlist)) — compare to scopeCommitment.
  4. 4. If the hash matches and both sources agree, the containment claim is verified by construction, not by assertion.

Reproduce it yourself

# 1. read the scope at the pinned block (archive-capable RPC for old heights)
cast call 0xb7c80f5154952E48f6E1548282343000c45b80d6 \
  "scopeAudit(uint256)(address,bytes32,address,uint256,uint256,address[],bool,bool)" \
  1 --block 121330236 --rpc-url <RPC>

# 2. ask the KeyStore independently
cast call 0x6572427ED530BadcF7375Cf9A4709D8d2b0E7E0a "isValidKey(address,bytes32)(bool)" \
  0xa847F3BBF69e8A888b59BC8729ce787E0dB5be97 0x86e4173f6b0cf87a693418969f54604827eaaa4d50ff1c1c59a2d7efb1602b42 --rpc-url <RPC>

# 3. recompute the commitment (fields sorted by contract address)
cast keccak $(cast abi-encode \
  "f(address,uint256,address,bytes32,address,uint256,uint256,address[])" \
  0xb7c80f5154952E48f6E1548282343000c45b80d6 1 \
  0xa847F3BBF69e8A888b59BC8729ce787E0dB5be97 0x86e4173f6b0cf87a693418969f54604827eaaa4d50ff1c1c59a2d7efb1602b42 \
  0x0000000000000000000000000000000000000000 20000000000000000 \
  86400 \
  "[0x10ED43C718714eb63d5aA57B78B54704E256024E,0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c]")

# → must equal 0xcab3406e9fdb3684ac9113bf20ffb4c79d011fd04a61620126fe84c7a2d9db24

# 4. machine-readable form
curl "https://guardrail-delta.vercel.app/api/scope-certificate?listingId=1"

Re-read at the exact pinnedBlock with an archive-capable RPC. Public BSC RPCs prune old state (they answer `missing trie node` for historical eth_call), which is why the certificate defaults to the latest block; the blockHash is included so the height is unambiguous.

The certificate is derived, not asserted. If the session is revoked, the listing paused, or the declared scope changes, the verdict and the commitment both change — and a third party recomputing from the same block will see the same result.