The on-chain enforcement layer for ACKRATE — published so anyone can prove the bytecode on Stellar matches this source.
Mainnet canary deployment: docs/mainnet-canary-deployment.md
Mainnet planning: docs/mainnet-roadmap.md
Mainnet V2 deployment:
CCLZEBJX…4HWR — the condensed,
single-contract T3 Step 1 enforcement layer documented in
contracts/mainnet-v2/README.md.
Mainnet V2 source proof and StellarExpert verification status:
docs/mainnet-v2-source-verification.md
Current milestone: T3 Step 2 contract-security gate; Steps 3–4 remain paused. The dated SDK Step 1 release evidence records the published package checks; it does not claim completion of all T3 deliverables or acceptance of revised grant scope.
Current Mainnet V2 security verification evidence:
- Concise T3 Step 2 result, threat model, diagrams, function coverage, live state, and reproduction guide
- Current V2 threat model and attack-to-test mapping
- Current V2 trust boundaries, data entities, and lifecycle diagrams
- Dated V2 scan results, fixed verification gaps, and disclosed maintenance exception
- Continuous dependency advisory scan
- Complete contract gate check
The older docs/security-* reports describe the previous Registry +
TimelockController canary and are retained only as historical release evidence.
Historical governed mainnet canary and deployment handoff:
contracts/mainnet/README.md
The governed mainnet canary is live and independently read-verified. Its exact contract IDs, four deployment transactions, constructor arguments, observed WASM hashes, GitHub attestations, and StellarExpert links are recorded in the completed deployment manifest.
The SDK, CLI, agents, merchant server, web UI, database, RPC provider, and x402
wire format are treated as untrusted. Only the contract's atomic
execute_payment path can consume a mandate and move value. The negative suite,
threat model, data flows, dependency scan, and exact-byte artifact checks are
release gates on every change.
The current Mainnet V2 target is
CCLZEBJXG4YVJEPBCR5F27N733BCK5HQJWZZGB3K54JVODY3VAGP4HWR.
The published coordinated npm releases—@ackrate/stellar@0.3.0,
@ackrate/core@0.4.0, @ackrate/ap2@0.4.0,
@ackrate/express-middleware@0.3.0, and @ackrate/cli@0.2.0—make this
the official Mainnet default through the SDK configuration, dependency graph,
and CLI bundle. All five passed a combined public clean-install check on
2026-09-07 at 04:25:11 Bangkok (UTC+7); public latest tags and downloaded
archive SHA-512 integrity values matched at 04:25:38–04:25:45.
See the dated Step 1 release evidence,
the package-to-contract mapping,
and the SDK release status
for the exact package roles and publication evidence.
The canonical SDK deployment configuration
exports this address as DEPLOYMENTS.mainnet.mandateRegistryId and provides the
ready MAINNET configuration with its complete bundled deployment manifest.
Core exposes it as ackrate.mainnet; the CLI no longer requires a manual
manifest for this official deployment. The advanced
publishedMainnetNetworkFromDeploymentManifest(manifest) helper validates a
deliberately supplied record against the same pinned identity. Configuration is
not a live-state check or permission to spend: signatures, user-approved limits,
and explicit real-USDC CLI confirmation still apply. Authorized upgrades replace
the implementation at the same contract address, subject to compatibility and
release-evidence review. Current V2 uses native Stellar 2-of-3 administration
without an integrated timelock. The older canary and Testnet upgrade controls
below describe separate historical/development deployments.
Every deployed byte traces back to a tagged commit in this repo. The pipeline is reproducible, attested, and verifiable by anyone with a terminal:
flowchart LR
A["📦 Tagged Source\n(this repo)"] --> B["🏗️ StellarExpert\nsoroban-build-workflow\nv25.1.0 · eed2fc0"]
B --> C["🔐 Deterministic WASM\nSHA-256 hash"]
C --> D["🧾 GitHub\nProvenance Attestation"]
C --> E["🚀 Testnet Deployment\n(on-chain hash match)"]
D --> F["✅ Anyone verifies:\nsource ⇄ hash ⇄ chain"]
E --> F
style A fill:#1a1a2e,stroke:#7B73FF,color:#fff
style B fill:#1a1a2e,stroke:#7B73FF,color:#fff
style C fill:#16213e,stroke:#e94560,color:#fff
style D fill:#16213e,stroke:#e94560,color:#fff
style E fill:#16213e,stroke:#e94560,color:#fff
style F fill:#0f3460,stroke:#00d9a5,color:#fff
| Folder | Current testnet contract | Historical testnet contract |
|---|---|---|
contracts/simple |
CCHQ5G4Y…CZRM — release 0.2.3 |
CB4KOTLG…7ZOA — immutable v0.1.0 |
contracts/composites |
CCYRF7FK…HEYW — release 0.3.0 |
CBALARHT…WOQX — immutable v0.2.0 |
Both contracts keep the crate name mandate-registry, but their package versions and release tags are distinct. The historical deployments remain available as immutable source anchors; the current deployments add pause, authority rotation, and timelocked same-address upgrades.
Both current contracts bolt on the same operational surface — without touching existing mandate or pool encodings.
stateDiagram-v2
direction LR
[*] --> Active : __constructor(admin)
Active --> UpgradeScheduled : schedule_upgrade(wasm_hash)\n🔑 admin only
UpgradeScheduled --> Active : cancel_upgrade()\n🔑 admin only
UpgradeScheduled --> Timelock : ⏳ fixed contract delay
state Timelock {
[*] --> Waiting
Waiting --> Ready : delay elapsed
}
Timelock --> Executed : execute_upgrade()\n🔑 admin + ⏸️ paused + ⏳ elapsed
Executed --> Active : ♻️ new WASM\nsame contract ID\nstorage preserved
Three gates on execute_upgrade: current admin authorization, elapsed fixed
delay, and paused state. The current Simple testnet contract enforces 3,600
seconds; the Composite contract enforces 86,400 seconds. Contract ID and storage
survive the swap.
stateDiagram-v2
direction LR
[*] --> Running : Paused = false at deploy
Running --> Paused : pause()\n🔑 admin only
Paused --> Running : unpause()\n🔑 admin only
note right of Paused
Money-moving entry points
return Paused = 10
before changing state.
pause/unpause are idempotent.
end note
flowchart TB
P[⏸️ Paused = true]
subgraph SIMPLE["contracts/simple"]
S1["🚫 execute_payment"]
end
subgraph COMP["contracts/composites"]
C1["🚫 solo payment"]
C2["🚫 firing pool capture"]
C3["✅ non-firing abort · revocation · registration\nvalidation · reads · commitment\neviction · simulation"]
end
P --> S1
P --> C1
P --> C2
P -.->|unaffected| C3
style P fill:#e94560,stroke:#e94560,color:#fff
style S1 fill:#1a1a2e,stroke:#e94560,color:#fff
style C1 fill:#1a1a2e,stroke:#e94560,color:#fff
style C2 fill:#1a1a2e,stroke:#e94560,color:#fff
style C3 fill:#0f3460,stroke:#00d9a5,color:#fff
| Addition | Type or signature | Behavior |
|---|---|---|
Admin |
instance Address |
Set by the constructor; authorizes pause, unpause, rotation, and the upgrade lifecycle. |
Paused |
instance bool |
Starts false; when true, money-moving entry points return Paused = 10 before changing state. |
PendingUpgrade |
instance Option<PendingUpgrade> |
Stores the proposed WASM hash and its earliest execution timestamp. |
__constructor |
(admin: Address) |
Establishes the initial admin and active state atomically at deployment. |
get_admin |
() -> Address |
Returns the current operational authority. |
set_admin |
(new_admin: Address) |
Requires the current admin and transfers future control. |
pause / unpause |
() -> () |
Require the current admin and are idempotent. |
is_paused |
() -> bool |
Exposes the emergency-stop state without authorization. |
schedule_upgrade |
(new_wasm_hash: BytesN<32>) -> u64 |
Requires the current admin and starts the contract's fixed delay. |
cancel_upgrade |
() -> () |
Requires the current admin and removes the pending upgrade. |
execute_upgrade |
() -> () |
Requires the current admin, elapsed delay, and paused state; replaces WASM while preserving contract ID and storage. |
get_pending_upgrade |
() -> Option<PendingUpgrade> |
Returns the pending hash and earliest execution timestamp. |
get_upgrade_delay |
() -> u64 |
Returns 3,600 seconds for Simple and 86,400 seconds for Composite. |
Run the same gate check used by CI and tagged releases:
./scripts/gatecheck-contracts.shOr run one contract directly.
⚙️ Simple mandate contract:
cd contracts/simple/mandate-registry
cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo test
cargo build --target wasm32v1-none --release⚙️ Composite mandate contract:
cd contracts/composites/mandate-registry
cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo test
cargo build --target wasm32v1-none --releaseflowchart LR
F["cargo fmt\n--check"] --> C["cargo clippy\n-D warnings"] --> T["cargo test"] --> B["cargo build\nwasm32v1-none\n--release"] --> G["✅ Gate\npassed"]
style G fill:#0f3460,stroke:#00d9a5,color:#fff
Zero warnings tolerated. Same gate, local and CI.
The current gate check runs 32 simple tests and 64 composite tests. Each suite includes a positive timelocked-upgrade lifecycle that uploads replacement WASM, proves early and unpaused execution fail, executes while paused, calls the replacement at the original contract ID, and confirms administrator, pause, pending-upgrade, and mandate storage behavior across the swap.
Both current deployments use the exact tagged and attested WASM produced by
the StellarExpert soroban-build-workflow.
The live Simple implementation is the simple-v0.2.3 cleanup from commit
eab02453cf06efa914d043df5295995c4dbc7b57, activated through the verified
same-address upgrade flow; the Composite release comes from commit
eed2fc012b1eee9a7345d353c55e7f575167dcfc.
| Contract | Release artifact | SHA-256 and on-chain hash | Deployment | Attestation |
|---|---|---|---|---|
Simple 0.2.3 cleanup |
mandate-registry_v0.2.3.wasm |
ba370a80369daa0a0dea2554410dca6f2a9f7a76ba707cb92a83434e2fe76e87 |
afaa1811…4f828 |
GitHub provenance |
Composite 0.3.0 |
mandate-registry_v0.3.0.wasm |
b3368d7fb68017d078792b125dff0389d4c4c893c86fb075baeb9100f0e0f0a1 |
a93d1d7d…35bbb |
GitHub provenance |
Historical and previous deployment hashes:
| Contract | Recorded hash |
|---|---|
Simple v0.2.0 published deployment |
13f7023d4a361b6e49d3d39f61f55c5eeece51a602013a3cddae420d2ce8552b |
Simple v0.1.0 |
4eb1b9430bd4a978348e7efc283a0bf599df048216a43b582921c17daed8c69e |
Composite v0.2.0 |
6333c20b490a570ed7b1c8cbfbf382da00ee8a0d1e4ef1ba013d02fa1cf16f44 |
Every future release follows the same pipeline: tagged build → hash + interface inspection → attestation → deployment → live checks → recorded evidence.
This repo is just the enforcement contract. The full protocol, SDK, x402 round-trip, reference apps, security gate checks, and clause-by-clause on-chain proof live in: