> **Unaudited developer preview.** The guarded end-to-end path has been exercised
> on Ethereum Sepolia with mock assets. Contracts are deployed on Base mainnet,
> but no mainnet-value settlement has been demonstrated. Do not use this project
> to protect production funds yet.
Giving an agent a wallet is easy. Giving it a wallet with **rules** is not.
```text
agent request → policy (allow / ask / deny) → execute, or a human decides → signed receipt → anchored log
```
AskGrokWallet sits between the agent and the money. Three things are load-bearing,
and each one is checkable from outside this repository:
1. **The policy is enforced, not suggested.** In `guarded` mode the agent's funds live
in a vault and an out-of-policy action **reverts at the contract**, before any value
moves. The bound is a revert, not a setting.
2. **A human is in the loop for exactly the actions that need one.** "Payments under
$50 run, over $50 ask me" compiles to `allow / ask / deny`; only the `ask` cases
reach the approval inbox.
3. **Every outcome leaves a receipt a stranger can verify** — four lines from one
dependency-free file: the signature over every field that matters (including where
the money went), the receipt's fixed position in an append-only hash-chained log,
and the log head anchored in a blockchain transaction. No account, no trust in us.
**Watch it work (30s):** [walkthrough video](https://askgrokwallet.io/askgrokwallet-demo.mp4) ·
**Try it:** [interactive demo](https://askgrokwallet.io/demo) ·
[approval inbox](https://askgrokwallet.io/approvals) ·
**Live site:** [askgrokwallet.io](https://askgrokwallet.io)
---
## For Judges — Runtime NYC, 19 September 2026
| What | Where |
| --- | --- |
| Live product | https://askgrokwallet.io |
| Submission demo, 2:53 (video) | [askgrokwallet.io/askgrokwallet-demo-runtime.mp4](https://askgrokwallet.io/askgrokwallet-demo-runtime.mp4) — the product walkthrough plus the verification and outside-review segments |
| 30-second demo (video) | [askgrokwallet.io/askgrokwallet-demo.mp4](https://askgrokwallet.io/askgrokwallet-demo.mp4) · also committed at [`assets/askgrokwallet-demo.mp4`](assets/askgrokwallet-demo.mp4) |
| Interactive demo + approval inbox | [/demo](https://askgrokwallet.io/demo) · [/approvals](https://askgrokwallet.io/approvals) |
| Public receipt log (live JSON) | https://askgrokwallet.io/api/receipts/chain |
| Receipt verifier — one file, zero dependencies | [release `verify-receipt-v1.0.1`](https://github.com/richard7463/askgrokwallet/releases/tag/verify-receipt-v1.0.1) · sha256 `32de3cad6f3bb23ae8415cd5afe5f54dd8167432a2473814e6ab4ec0b767317a` · check the hash **before** you run the file: `curl -sLO …/SHA256SUMS && shasum -a 256 -c SHA256SUMS` |
| Check it yourself, in one command | `node spec/judge-check.mjs` — asserts the verifier is the released bytes, verifies a real receipt against the live log, and reports the log's size and integrity |
| Write your own verifier, then check it | [`spec/vectors/`](spec/vectors/) — frozen canonical-bytes, hash and signature vectors, plus two implementations (Node and Python) that must reproduce the same bytes: `node spec/vectors/run-vectors.mjs` |
| Show an auditor everything, the public nothing | [`spec/audit-bundle.md`](spec/audit-bundle.md) — receipts plus their log evidence, sealed to an auditor's key; `node spec/verify-audit-bundle.mjs` opens, verifies and reports, including what it cannot prove |
| Onchain proof | [transactions and blocks](#live-proof--checked-2026-09-18) · [deployed contracts](#deployed-and-verified-contracts) |
| Tests you can run in three minutes | 20 contract tests · 13 verifier behaviour assertions · plugin package smoke test — see [Local run](#local-run) |
| Track entered | **Bankr grand prize** — agentic commerce / autonomous financial agents |
| Repository map | [below](#repository-map) |
### Judging scorecard
Bankr judges in this order: **Product**, **Founder-Market-Fit**, **Execution**.
| Criterion | Our answer | Open this to check |
| --- | --- | --- |
| **Product** — useful, compelling, something people would want | Agents already move money (Grok Bot, Cursor, scripts). The two things their operators cannot get today are a **bound** the agent cannot talk its way past and a **record** a third party will accept. This is both, in one loop: policy → human when needed → execution → receipt. | [30s video](https://askgrokwallet.io/askgrokwallet-demo.mp4) · [live demo](https://askgrokwallet.io/demo) · [three modes](#three-modes--pick-by-where-the-keys-live) |
| **Founder-Market-Fit** — disrupting something in the current stack | The stack splits the problem: wallets (MetaMask Guard Mode, Coinbase CDP, Turnkey) hold funds; card rails (Stripe Link) approve per purchase; provider dashboards log what their own service did. None of them hands the operator an enforceable bound *plus* a receipt that survives being shown to someone who does not trust the operator. | [What makes this different](#what-makes-this-different) |
| **Execution** — how much actually works | Live product; contracts deployed on Base mainnet and exercised end-to-end on Sepolia with real transfers and anchored receipts; 20 contract tests; a versioned standalone verifier with an offline behaviour test; an outside reviewer broke that verifier, and the fix shipped as a pinned release with their repro kept as a test. | [Live proof](#live-proof--checked-2026-09-18) · [Outside review](#outside-review-kept-as-a-test) |
---
## Live proof — checked 2026-09-18
Every number and address below was read from the chain or from the live service on
2026-09-18. Open the explorers and check them.
### Guarded execution, end to end (Ethereum Sepolia, chainId 11155111)
One round, in order: the lease, operator and budget checks pass → the vault moves
mock USDC → the receipt-log head is written onchain.
| Step | Transaction | Block | Result |
| --- | --- | --- | --- |
| Guarded vault transfer | [`0xbaf2c3776398e4f8d891b4e3da218361cfa6e79fb72edd603f11e8bf5a5e58e3`](https://sepolia.etherscan.io/tx/0xbaf2c3776398e4f8d891b4e3da218361cfa6e79fb72edd603f11e8bf5a5e58e3) | `11626574` | success → `BoundlessVault` |
| Receipt-log anchor | [`0x1bd82e543f2ddb33348f3bd3f5b06ab44946ed26ef857c6efb36e69d88d3628e`](https://sepolia.etherscan.io/tx/0x1bd82e543f2ddb33348f3bd3f5b06ab44946ed26ef857c6efb36e69d88d3628e) | `11626575` | success → `TrustLeaseController` |
### Deployed and verified contracts
**Base mainnet (chainId 8453)** — bytecode present at every address, checked 2026-09-18:
| Contract | Address | Size | Explorer |
| --- | --- | --- | --- |
| `TrustLeaseController` (ERC-8196 policy + receipt anchors) | `0x4ACcB1df8cc625AC05743888158CC3B866aC9833` | 18,800 B | [BaseScan](https://basescan.org/address/0x4ACcB1df8cc625AC05743888158CC3B866aC9833) |
| `BoundlessVault` (custody; the only contract that moves tokens) | `0xd9526Eb615f5e252341b5a83b3c26eCca4f1284e` | 11,145 B | [BaseScan](https://basescan.org/address/0xd9526Eb615f5e252341b5a83b3c26eCca4f1284e) |
| `VerificationScoreRegistry` (ERC-8126 scores the gate reads) | `0x89c8B3d053a79A0bd5A47597aaF97729f504d359` | 2,558 B | [BaseScan](https://basescan.org/address/0x89c8B3d053a79A0bd5A47597aaF97729f504d359) |
| Mock USDC (demo asset) | `0x17058C78CFE90314dd349C7fAC71Bb4f0A8f0852` | 1,831 B | [BaseScan](https://basescan.org/address/0x17058C78CFE90314dd349C7fAC71Bb4f0A8f0852) |
**Ethereum Sepolia (chainId 11155111)**, where value-moving rounds are demonstrated:
controller `0x6f8a3cc28c607462643b0e656f621f3f279afb70` ·
vault `0x785aaf81456f9d136501f74520dc12d1eb33f5fd` ·
registry `0xfe5b824c99b413db2d8526c8df10667df3f69026` ·
mock USDC `0x860ee8efbaf9c72aac3cedcbaf65fb2756f71db2`.
Deployment record: [`contracts/deployments/base-mainnet.json`](contracts/deployments/base-mainnet.json).
BaseScan source verification has not been submitted yet; the canonical source is
[`contracts/`](contracts/) here, which is what the CI suite compiles.
### Receipts, live
| Check | Value (live, 2026-09-19) | Where to look |
| --- | --- | --- |
| Public log | `intact: true`; entries and anchors grow with every receipt | https://askgrokwallet.io/api/receipts/chain |
| Verifier version | `verify-receipt 1.0.1` | [release](https://github.com/richard7463/askgrokwallet/releases/tag/verify-receipt-v1.0.1) |
| Verifier sha256 | `32de3cad6f3bb23ae8415cd5afe5f54dd8167432a2473814e6ab4ec0b767317a` | `node verify-receipt.mjs --version` |
| Live mirror | identical bytes to the release | `curl -sO https://askgrokwallet.io/verify-receipt.mjs && node verify-receipt.mjs --version` |
### The agent's own wallet, on Base mainnet — 2026-09-18
The policy layer is not the only place a bound can live. AskGrokWallet compiles the
address-and-amount half of a policy into **wallet-layer rules** that a signing
infrastructure enforces before a transaction is signed, and the agent's money sits in a
wallet our backend never holds a key for (a server wallet: MPC key shares, API-token
auth, no raw key in our process or the agent's).
| Rule enforced before signing | Shape |
| --- | --- |
| No key export, ever | `deny` + `operationRestrictions.blockExport` |
| Blocked counterparty | `deny` + `0x9999…9999` |
| Allowed payee + USDC (its proxy **and** implementation) | `allow` + `valueLimit.maxPerCall = 50 USDC` |
| Action | Transaction |
| --- | --- |
| Guarded payment, 0.10 USDC from the agent's wallet | [`0x2d73c475be9be8bfee8baffd699ffb34b9d18cf80a7a0c17e5ad1583d1181c0a`](https://basescan.org/tx/0x2d73c475be9be8bfee8baffd699ffb34b9d18cf80a7a0c17e5ad1583d1181c0a) |
| Same payment without the rules in place (control) | [`0x93b5b65282fe62569606627789c4b493a4bcd5020aec92ea4eac4a72a21bd97c`](https://basescan.org/tx/0x93b5b65282fe62569606627789c4b493a4bcd5020aec92ea4eac4a72a21bd97c) |
| Refused: payment to the blocked counterparty | nothing broadcast |
| Refused: payment above the per-call limit | nothing broadcast |
This closes the "no mainnet-value settlement has been demonstrated" gap: real USDC, Base
mainnet, from a wallet whose key is not in our backend, with the bound enforced inside
the signing infrastructure rather than in a log written afterwards.
### Outside review, kept as a test
A reviewer on the Cursor forum ran the verifier against the demo and found a real bug:
a transaction that was broadcast but still in the mempool (`blockNumber: null`) was
reported as `onchain ✓ … block 0`, because `Number(null)` is `0`. A transaction in the
mempool can be dropped, replaced or reorged away, so that line claimed the one thing
the check exists to prove, before it was true.
Fixed in 1.0.0, and their repro now lives in this repository:
[`spec/test-verify-receipt.mjs`](spec/test-verify-receipt.mjs) runs the verifier against
a stub node and a stub log, with no network. It **fails on the previous build with six
assertions** — including `block 0` — and passes now. The same change covers a reverted
anchor transaction, which used to read as fixed as well.
**A second outside review found the same class of bug one layer deeper.** The
maintainer of the Bankr skills repository read the released 1.0.0 bytes and noticed
that the receipt question had three non-answers — no receipt, an RPC error, a receipt
without a `status` — and all three fell through to `onchain ✓`. Inclusion was checked;
execution was assumed. That is fixed in **1.0.1**, and their three cases are the
`3b` block of the same test file: they **fail against the 1.0.0 bytes**
(`ba066e7c…`) and pass against 1.0.1 (`32de3cad…`).
Two outside reviewers, two real holes, both closed with a published release and a
failing test kept in the repository. That is what the verification story has to
survive to mean anything, and it is why the hash is pinned rather than the URL: you
compare bytes, not a promise.
---
## How it works
```mermaid
flowchart LR
A["Agent