The Ethereum Foundation’s Trillion Dollar Security initiative has identified blind signing and transaction uncertainty as a user experience risk, and is exploring native transaction assertions as a next step to enforce a transaction’s final outcome, alongside Clear Signing.
This post covers why a valid signature doesn’t always guarantee the transaction result you wanted, how native transaction assertions could protect users where today’s defenses stop, and the design choices behind them, with EIP-7906 (Transaction Assertions via State Diff Opcode) as one possible approach.
Two ways a signed transaction can go wrong
The problem starts with how Ethereum works. It executes exactly what you authorize, without judging whether the result is what you wanted. A signature commits to a request, but its outcome depends on the code and state it encounters during execution. Users have lost large sums either because they approved something different from what they believed they were approving, or because the request they intended still produced a result they didn’t want.
The first case is an intent mismatch, as seen in the Bybit incident and the BadgerDAO attack. In both attacks, a compromised frontend supplied a signing request that differed from what users believed they were approving. Bybit’s signers authorized replacing the Safe’s implementation contract, while Badger users granted the attacker permission to spend their tokens.
The other case is an outcome mismatch. The signer approves the request they were shown, but its limits or the state it runs against still allow a result that conflicts with their economic goal or a standing safety policy. In the Aave and CoW collateral swap, a user asked to swap about $50.4 million of aEthUSDT for aEthAAVE. AAVE liquidity was far too thin for a trade of that size. CoW’s gas ceiling also rejected the more complex quotes during verification, leaving one verified quote of roughly 329 aEthAAVE. The interface displayed a 99.9 percent price impact warning and required the user to confirm that the entire value could be lost. The user signed anyway and received tokens worth about $36,000.
All three cases lacked a trusted rule over the resulting state, defined independently of the transaction builder and enforced during execution. Bybit’s rule would have required the approved Safe implementation to remain unchanged. A Badger user’s rule would have allowed new token approvals only for published Badger contracts. The Aave user’s rule would have set a minimum acceptable output, calculated independently of the quote shown by Aave’s interface (in this solver-based flow, the signed order or CoW settlement protocol would also have had to require the assertion).
Ethereum has no general mechanism for onchain code to inspect the full set of net state changes and events produced by a transaction.
What a signature does not control
Your signature commits to the action you request, including the target, value and calldata. The EVM executes your call against the contract code and state present when the transaction runs, which may have changed since you signed. The resulting net balance and storage changes, along with any emitted events, can therefore differ from what you expected.
The diagram below shows how the signed request, code and state determine the outcome.

The target contract, or another contract it calls, may use a proxy whose implementation changes before execution, so the code that runs can differ from what you inspected. Transaction ordering can also change the state your call encounters. For example, a sandwich attack can shift a pool’s price before your swap executes without changing your signed transaction.
Where today’s defenses stop
Several defenses are already in place. One is Clear Signing, which explains to the user what action the calldata requests. It depends on accurate decoding and on the signer recognizing when that action differs from what they intended.
Another defense is simulation, which predicts a transaction’s effects using a selected chain state. The chain state can change before inclusion, and the transaction signed may differ from the one simulated. In Radiant Capital’s case, both the wallet interface and the simulation showed the intended transaction, while malware on the signers’ machines substituted a malicious payload at signing time.
Contract checks and wallet guards also enforce rules during EVM execution. Uniswap, for example, reverts a swap if its output falls below amountOutMinimum. Safe’s checkAfterExecution hook lets a guard inspect the account’s state after execution and revert a transaction that violates its rules for owners or configuration. Both approaches require choosing which state to check in advance. To read another contract’s storage, they depend on the functions it exposes. A token’s balanceOf makes balance checks straightforward, but a proxy need not expose its implementation address through a function. Without such an interface, a guard cannot read the implementation slot directly.
These checks cannot inspect the transaction’s full set of net state changes. A guard can verify that a particular balance is unchanged, but it cannot ask the EVM what else changed, so effects it was not designed to check can go unnoticed.
How native transaction assertions work
Native transaction assertions would let onchain code inspect the full set of net state changes after the transaction’s actions have run. An assertion uses read-only logic to compare starting and final values against a rule. If the rule fails, the actions revert.
The rule is included in the transaction and signed along with its actions. It can cover net changes to balances, storage and code, as well as newly deployed contracts and emitted events. It can require a minimum amount received, cap spending, block new approvals, preserve an account’s control logic or allow only a specified set of changes. The diagram below shows how assertions check the outcome and revert the transaction’s actions if the rules fail.

The rule’s source matters as much as the check itself. A compromised frontend can write an assertion that permits the attack. A useful rule must come from independently approved user intent, a standing account policy or protocol logic that the compromised component cannot change.
Three design choices
Designing native transaction assertions requires decisions about what information the EVM exposes, how assertion code accesses it and where the opcodes can run. The information could include state changes, events or both. Access options include enumerating entries, looking up specific values or copying the full set of changes into memory. The opcodes could be restricted to particular transaction types or execution phases, or allowed anywhere in the EVM.
EIP-7906 as a possible solution
One possible approach is EIP-7906, which builds on the frame transactions defined in EIP-8141. A frame transaction contains an ordered sequence of validation and action steps. EIP-7906 adds a read-only POST_TX frame at the end to check the transaction’s outcome. EIP-8141 is scheduled for Hegotá, while EIP-7906 has advanced to “Considered for Inclusion” but is not yet confirmed for the upgrade.
The design exposes both state changes and events. State changes are reported as net differences in native ETH balances and storage, alongside newly deployed contracts and their code hashes. A storage slot written five times appears as one entry with its starting and final values. If the slot ends with its original value, it does not appear at all.
Three new opcodes (EVM instructions) provide access to this information. TXTRACE enumerates net state changes and events, TXDIFF retrieves starting and final values for specific addresses and storage slots, and EVENTDATACOPY copies an event’s data into memory.
These opcodes work only inside a POST_TX frame, which runs at the end of the transaction as a static call. This lets the assertion inspect the outcome without changing state. If the rule is violated, the entire execution body reverts, but the transaction remains in the block with a failed status and the gas payer is charged for the gas consumed. That charge prevents attackers from making builders execute deliberately failing transactions for free.
The assertion has to be required
EIP-7906 does not require transactions to include an assertion, so whoever builds the transaction can leave it out.
For the user’s own transactions, the wallet must ensure that every frame transaction it builds includes the required assertion. The rule can come from a simulation the wallet has run or from a standing policy that applies to all its transactions.
A protocol’s protected function must verify that the call comes from a frame transaction containing the exact required assertion. It must reject ordinary transactions and frame transactions with a missing or incorrect assertion. Callers and integrations would therefore need to use compatible frame transactions, and an already deployed immutable contract could not add this check.
Where transaction assertions could help
Beyond the security benefits for users and protocols, native transaction assertions could support other use cases. They could, for example, strengthen delegation. When you let an agent act on your behalf, you can limit which contracts it uses, how much it spends and how long its permissions last. Assertions could add rules for the outcome of each transaction, so you can constrain both what the agent may do and what its actions produce.
A protocol could also define its own rule, requiring the same safety check for every caller using a frame transaction. In solver execution, the protocol could specify the required outcome while leaving the solver free to choose the route. That guarantee would apply only within one transaction on one network, so it would not cover a route spanning multiple chains. Assertions could also check that a workflow reaches its intended final state, with unused tokens returned to the user and any remaining token approvals revoked.
Help shape the design
Solutions for native transaction assertions are still being designed as part of the Ethereum Foundation’s Trillion Dollar Security initiative, and we want to hear from the wallet and protocol teams who would use them. Get in touch at [email protected] to explore the use cases with us and help shape the research, or join the EIP-7906 discussion thread.
Read more about risk controls and priority work at trilliondollarsecurity.org.







