Prototype

Read it before you sign

Simulate the transaction on verified state. Decode what it does. Explain the outcome in plain language.

The Transaction Security Agent (TSA) is a working prototype. A dApp still prepares the bytes, but TSA shows the effect of those bytes before you confirm: balances, approvals, storage writes, and calls. The specification documents the same pipeline as the Transaction Security Assistant.

Read it before you sign
The problem

Blind signing

A transaction is a sequence of bytes. Most wallets show a contract address, a hex blob, and maybe a function name. The signer can only hope that matches what they intended.

The payload is opaque

The dApp prepares the bytes. Confirm accepts them. The signer does not see which balances change, which approvals are granted, or which storage is written.

EIP-712 shows the input

Typed fields make the call parameters readable. They do not show what those parameters do in the EVM. A readable to and data can still be a delegatecall that rewrites a wallet implementation.

The outcome is what matters

A signing format cannot show the state transition. A simulation can. For a Safe, TSA simulates the execTransaction the signatures authorize. For a permit, it simulates permit and the transferFrom the spender can then run.

Two public incidents sit on this gap: the Bybit Safe theft in February 2025, and a $32.4 million permit-phishing loss in September 2024. In both, the signer could not see what the signed data would do on-chain.

Three steps

Simulate. Decode. Explain.

TSA turns a raw transaction into a verified, decoded, and explained outcome. The model does not decide what happened. It explains a proven execution, and the decoded facts stay next to the text.

Simulate on verified state

colibri_simulateTransaction

The call takes the same arguments as eth_call. Colibri fetches a Merkle proof for every account and storage slot the transaction touches, verifies them against a consensus-proven state root, and executes the call in its own EVM. The result records state changes, proven pre-state storage reads, logs, internal calls, the codeHash of every account, keccak preimages of hashed storage keys, and the executed JUMPDEST program counters.

Map bytecode back to source

Sourcify, then a bytecode check

Verified Solidity sources are fetched from Sourcify and compiled. The source is used only when the compiled runtime bytecode matches the codeHash proven during simulation, including immutables, linked libraries, and metadata. ABI, storage layout, and keccak preimages then decode events, calls, and storage changes into names such as balances[0xabc…] instead of a raw slot.

Explain the execution

Only the code that ran

The prompt contains the decoded events, calls, and state changes, plus the Solidity that actually ran. JUMPDEST positions and compiler source maps keep the context to the executed functions. Any language model can answer that prompt. The explanation sits beside the decoded facts so you can check it.

On device

A local SLM for Web3

A local SLM for Web3 is a small language model that runs in the browser or app and explains a transaction already simulated on verified state. The same pipeline can also call a remote API. The prototype's goal is that nothing has to be installed.

  • The default local model is colibri-tsa-4b, a fine-tune of Qwen3.5-4B (Apache 2.0, February 2026), trained on decoded simulation results and the matching Solidity.
  • WebLLM runs the quantized model on the GPU through WebGPU. Current Chrome or Edge is required. The first download is about 2.4 GB and is cached. The packaged 16k context needs about 3.9 GB of VRAM.
  • The same explainer also calls OpenAI-compatible endpoints, Anthropic, or a local Ollama server. Cloud providers are reached with fetch. No provider SDK is bundled.
  • The JavaScript package is @corpus-core/colibri-explainer. It consumes the simulation JSON. It does not import the verifier.

Ask the simulation for positions and state_values. Those two flags are what let enrichment name the functions that ran and the storage slots that were read. Setting chainId turns Sourcify enrichment on. Without it, the model still sees gas, status, raw logs, and hex state changes.

Playground

Try a transaction before you sign it

playground.colibri-proof.tech runs the pipeline in the browser. Paste a transaction, simulate it on proven state, and read the explanation.

  • Paste a transaction object (to, from, value, data or input, gas or gasLimit) or a raw signed transaction.
  • Networks in the playground: Ethereum mainnet, Sepolia, Gnosis, Chiado, and Platåberget. RPC and prover URLs can be overridden.
  • Optional switches: PAP with a ZK proof and a hybrid prover, Sourcify enrichment, proven state values, and only the code the trace covered.
  • An optional oblivious-node URL terminates eth_getProof inside a TEE, so the requested account and storage keys stay private. Leave it empty to use standard PAP.
  • Already executed transactions skip colibri_simulateTransaction and explain the recorded trace instead.
  • The result view shows the explanation, events, the prompt, the decoded JSON, and the raw simulation.
Limits

What a simulation does not guarantee

A simulation shows what would happen on the current state. If that state changes before the transaction is included, or a contract behaves differently depending on block parameters, the outcome can differ.

  • Local inference is not the same as offline. With chainId set, enrichment still fetches public Sourcify metadata. Omit chainId when the explanation must not touch the network.
  • Proof fetches still ask an RPC provider for the accounts and storage slots the transaction touches, together with your IP address. That access pattern can hint at intent.
  • PAP is the work aimed at that remaining leak. The playground can also send eth_getProof through an optional TEE node.
  • The code in the browser still has to be the code you trust. The explainer package and Colibri are published as open source.
FAQ

Questions about TSA

What is a local SLM for Web3?

A local SLM for Web3 is a small language model that runs in the browser or in an app and explains an Ethereum transaction after it has been simulated on verified state. The prompt is not sent to a cloud model. TSA is a prototype of that: a fine-tune of Qwen3.5-4B, run with WebLLM. A general local LLM can talk about crypto from its training data. This model explains a decoded simulation it was given, and it does not decide whether the transaction is safe.

What is the Transaction Security Agent?

TSA is a prototype that simulates a transaction on verified state, decodes the execution against verified contract source, and explains the outcome in plain language before you sign.

Does the language model decide whether the transaction is safe?

No. The model explains a proven execution. The decoded events, calls, and state changes are shown next to the explanation so you can check the text against the facts.

Is EIP-712 enough?

EIP-712 makes the input fields readable. It does not show the state transition those fields cause. TSA simulates that transition.

What is downloaded the first time?

The local WebLLM model is about 2.4 GB and is cached in the browser. It needs WebGPU, in current Chrome or Edge. The packaged 16k context needs about 3.9 GB of VRAM. You can also use OpenAI, Anthropic, or Ollama instead.

What still leaves the machine?

Colibri still requests proofs for the accounts and storage slots the transaction touches. With enrichment on, Sourcify metadata is fetched as well. The explanation itself can stay on your GPU when the provider is WebLLM.

Can I explain a transaction that already executed?

Yes. In the playground, an already executed transaction uses the recorded trace instead of running colibri_simulateTransaction again.

Don't sign blind.

Simulate on verified state. Read the outcome. Then decide.