Transaction Simulation: What a Transaction Will Do Before You Sign It

·8 min read·By SSP Editorial Team
SSP Academy cover: transaction simulation in SSP Enterprise

Transaction Simulation: What a Transaction Will Do Before You Sign It

The address is right. The amount is right. You checked both. And the transaction still isn't what you think it is.

That is not a hypothetical. It is the ordinary shape of most crypto losses that involve a careful person. Nobody talked them into sending money to a stranger. They approved something whose visible parts were all correct and whose consequences were somewhere else entirely — in a token allowance, in a contract call, in one character of an address they had seen a hundred times before.

Simulation is the attempt to close that gap: to show you the effects of a transaction rather than its contents, before your signature makes it real.

The gap between what you meant and what you are signing

A transaction is not a sentence. It is bytes.

When those bytes are a plain transfer, the gap between what they say and what they do is small — an address, an amount, a fee. When they are a contract call, the gap can be enormous. approve looks like a permission. It is a standing right for another address to move your tokens, and under the ERC-20 standard nothing in the call is required to bound how much or for how long. A single approval, signed once, can be drained months later.

The interface you are looking at when you sign has to translate those bytes into a sentence. That translation is the attack surface. If the translation is produced by whoever wants your signature, it can say anything.

A dry run, not a promise

Simulation means running the transaction against the current state of the chain without broadcasting it, and recording what changes.

In SSP Enterprise, that happens when a proposal is created, before anyone signs. The simulation is built from what the proposal builder produced — the recipients, amounts, token contract and calldata that SSP itself assembled — never from raw signed hex handed over by a client. It runs read-only. Three engines cover the different chain families:

  • EVM chains run a read-only call against a node and read back the resulting balance changes and the decoded call.
  • UTXO chains need no node at all. The inputs and outputs are already known, so before-and-after is arithmetic on the selected coins, and recipients are classified as change-back-to-you or genuinely external.
  • Solana deserialises the unsigned transaction the builder produced and runs the network's own simulateTransaction, with signature verification switched off, then reads the vault's pre- and post-token balances out of the result.

What comes back is a preview: what each asset's balance was before, what it will be after, and — on EVM — what the call actually is, decoded into a method and its arguments.

Two things it is not. It is not a guarantee: chain state moves, and a simulation run at proposal time is a picture of the chain as it was then. And it is not a gate. Which is the more interesting half of the design, and we will come back to it.

Fourteen things worth being told

A preview that only shows numbers still asks you to spot the problem yourself. So the preview is accompanied by warnings, and there are fourteen of them, at four severities.

Approvals — the category that empties the most wallets. An unlimited or unbounded allowance is critical. Any non-zero spend approval to an address that is not on your allowlist is high. And approving an externally-owned account rather than a contract is high, because there is essentially no legitimate reason to do it: contracts spend allowances, people do not.

Recipients — a recipient not in your organisation's contacts or the vault's whitelist is flagged. So is one your vault has never sent to before. Neither is wrong on its own. Both are worth a second read.

Contract risk — a destination contract whose source is unverified, one deployed within the last seven days, native value being sent to a contract at all, and any address a provider flags as outright malicious.

Execution — the transaction reverting in simulation, which means it will fail on-chain and waste the fee. Or the simulated outflow not matching the amounts the proposal claims — the vault losing more, or less, than the screen says.

Degradation — and, plainly labelled, the case where simulation could not run. An unreachable node produces "unavailable", not silence and not a fabricated clean bill of health.

The distinction between those severities matters more than the count. Critical and high are about a transaction that is probably not what it appears to be. Medium and info are about a transaction that is unusual, which most legitimate transactions occasionally are.

Address poisoning: the attack that beats careful people

One warning deserves its own section, because it is aimed specifically at the habit that most security advice recommends.

Address poisoning works like this. An attacker sends your vault a tiny or zero-value transaction from an address engineered to share the first six and last four characters of an address you already deal with. Nothing is stolen. Nothing is even really done. The transaction exists so that the look-alike address appears in your history.

Later — days later, when you are paying the same counterparty again — you copy the address from your own transaction history, the way careful people do rather than retyping. You check it the way careful people check: first few characters, last few characters. Both match. The middle does not, and the middle is where the money goes.

SSP checks every proposal recipient against the addresses your vault already knows, using exactly the prefix-and-suffix comparison that a human eye performs, and raises a critical warning naming the address being impersonated. The same check runs in the other direction on incoming history, so a poisoned address is marked when it arrives rather than only when you are about to use it.

The reason to know this attack exists even if you never use SSP: the verification habit that stops every other address attack is the one this attack is built to defeat. Compare whole addresses, or compare nothing.

Why the warnings are computed on the server — and still do not block anything

The warning set is decided server-side, using your organisation's contacts and the vault's whitelist as the source of truth. That is deliberate: if a client could decide what counted as allowlisted, a compromised client could quietly decide that everything did.

And yet none of it can stop a transaction. Simulation never gates signing or broadcast. A provider that errors, times out, or cannot reach a node returns "unavailable" and the proposal stays fully signable. The whole subsystem is failure-isolated so that a crash in the preview can never strand a proposal.

That will read as a strange choice, so it is worth stating the reasoning plainly. A preview that can block is a preview that can be made to block — by taking down a node, by producing a false critical, by any of the thousand ways software goes wrong. Funds that cannot move because an advisory service is unhealthy are funds you have partially lost. The threshold in the multisig is what protects the money; the simulation is there to inform the humans holding the keys. What actually stops a transaction is the longer version of that argument.

When the server and your device disagree

Everything above is the server's reading of the transaction. Your device does its own.

Two independent readings of the same transaction

When SSP Wallet shows you a proposal to sign, it decodes the bytes itself and displays what it found — not the server's summary. Then it compares the two. If the server's decoded call implies a different set of recipients than the device derived, the device raises a critical mismatch warning of its own and visually downranks the server's preview.

The device's decode is the authoritative one. The check is deliberately conservative: a missing or pending server simulation is a degradation, not a contradiction, and is not flagged as one. It also only applies to EVM chains, where the server produces a decoded call at all — on UTXO chains there is nothing to compare against, and the device's own decode simply stands alone.

This is the property worth taking away, whatever wallet you use. A second opinion is only worth something if it comes from somewhere that could not have been compromised by the same act as the first. Two summaries from the same server are one summary.

Reading a risk strip without learning to ignore it

Warnings only work until they become wallpaper. A few habits keep them useful.

Read severity first, then the detail. Critical and high are worth stopping over. A medium or info warning on a first payment to a new supplier is the system working correctly, not a reason to worry.

Treat any approval warning as a full stop. Transfers move what they say they move. Approvals grant a right that outlives the transaction. If you did not intend to grant a standing allowance, the answer is no.

Believe the device over the screen. If the two disagree, the phone in your hand is the one running on hardware an attacker would have had to compromise separately.

Do not treat "unavailable" as "fine". It means nobody checked. That is a reason to look harder yourself, particularly on a large or unusual payment.

Everything here is about the moment before a signature. For what happens after — who can sign, how many are needed, and which operations demand both devices again — start with setting up your first enterprise vault and critical actions and re-signing. And for the attack patterns these warnings are shaped around, phishing attacks targeting crypto users covers the human half of the problem.

Share this article

Related articles