Technical deep dive

How Stvor works

The $1.5B Bybit hack was a tampered payload. Same root cause: execution happened before anyone verified the live operation still matched intent. Stvor binds intent to execution at the checkpoint — before the payment rail fires. A swapped destination is a signed DENY, not a silent pass.

Overview

Stvor is middleware between intent and execution. It does not replace custody, monitoring, or signing infrastructure. It answers: does what is about to run still match what was committed? Any check fails → DENY with a signed receipt inline from POST /verify, no payment attempted.

01 · commit → verify → settle

commit

POST /commitments

Canonical params hashed and stored at intent time. Intent is frozen before any transaction is built.
verify

POST /verify

Live payload compared to commitment with timingSafeEqual. Destination swap or hash mismatch → DENY.
settle

Your execution rail

Stripe capture, chain broadcast, or ledger write fires only after ALLOW. Signed Trust Receipt is returned inline from POST /verify. Optionally call POST /receipt with txHash after settlement.

02 · What verify checks

One gate: SHA-256(JCS(live payment payload)) compared to the stored payloadHash with crypto.timingSafeEqual(). Payment payload fields are to, amount, currency, and optional chain/ asset. Swap the destination or amount after commit → signed DENY.

03 · Payload attestation

Commit–reveal pattern: hash the canonical task payload at intent time. Before execution, re-hash the live payload and compare. A single byte change produces a different digest.

Attack

Bybit — $1.5B — Feb 2025

  1. 1.Safe{Wallet} developer workstation compromised
  2. 2.Malicious JS injected: UI shows correct destination, tx silently swapped
  3. 3.Signers approve what they see — sign something else

✗ $1.5B transferred in one routine-looking operation

Stvor

Blocked at verify

  1. 1.SHA-256(task_payload) committed at intent — immutable before UI renders
  2. 2.timingSafeEqual(received_hash, committed_hash) before execution
  3. 3.Mismatch → signed DENY. Stripe PaymentIntent.cancel() if escrowed.

✓ Attacker gets nothing. Receipt proves the block.

payload-compare.ts
import crypto from "node:crypto";

function canonicalize(params: Record<string, unknown>) {
  return JSON.stringify(params, Object.keys(params).sort());
}

function verifyPayload(
  liveParams: Record<string, unknown>,
  commitment: { payloadHash: string },
) {
  const hash = crypto.createHash("sha256")
    .update(canonicalize(liveParams))
    .digest("hex");

  const a = Buffer.from(hash, "hex");
  const b = Buffer.from(commitment.payloadHash, "hex");
  if (a.length !== b.length) return { decision: "DENY", reason: "PAYLOAD_MISMATCH" };
  if (!crypto.timingSafeEqual(a, b)) return { decision: "DENY", reason: "PAYLOAD_MISMATCH" };
  return { decision: "ALLOW" };
}

04 · Intent-to-execution binding

Slow-accumulation attacks (fake tokens, approval farming) are a different class of problem than payload swaps. Stvor's live gate answers one question: did this specific execution still match the committed payment payload?

05 · Stripe reference flow

The live reference implementation uses Stripe capture_method: manual. Funds authorize at funding but do not capture until verify returns ALLOW. This is one rail — not the product.

OPENFUNDEDSUBMITTEDVERIFIEDCOMPLETE
Note
See the interactive reference at nous.stvor.xyz/demo. Production API: https://api.stvor.xyz.

06 · Trust Receipt

After ALLOW or DENY, POST /verifyreturns an ES256 (P-256, IEEE-P1363) signed Trust Receipt inline (ATS-1 draft). Verifiable offline with only the issuer's public key — browser verifier, CLI, or ~20 lines of WebCrypto.

receipt-sample.json
{
  "receiptId": "rec_41gdRVEv7_Yo",
  "binding": "agent-committed",
  "agentId": "agent_demo_blocked",
  "decision": "DENY",
  "reason": "PAYLOAD_MISMATCH",
  "to": "0x8f3a2c91d4e7b0a6c5d8f1e2a4b7c9d0e3f6a8c1d",
  "amount": "50000.00",
  "currency": "USDC",
  "kid": "key_xd4o8VukjEgAyNPg",
  "signature": "rQ3nsY5ghE3QT7acZGfWTmZJkoKkNgnE30CH-d2Ie22dAmBGW_mf49e7o1NOsn0EayW63fzbe_ZJhvdsfzXiuA"
}

07 · Threat model

Payload manipulation (in scope)

Attacker modifies destination, amount, or currency between commit and execution. Stvor catches this because the modified payload produces a different SHA-256 digest → signed DENY before settlement.

Out of scope

Scope revocation (authorization expired in March, execution in April), slow approval farming, prompt injection that poisons the commit itself, key compromise, and humans who bypass the checkpoint entirely.

Warning
Stvor does not solve key compromise, compromised signing infrastructure, or social engineering of human approvers who bypass the checkpoint entirely.

08 · References