What Is Reverted and What Remains When a Transaction Fails?
A wallet reports that a transfer failed. The recipient's balance has not increased. Does that also mean the sender paid no fee, and that submitting the same signed transaction again will execute it from the beginning?
Failure alone does not answer those questions. Being unable to prepare a transaction for execution is different from the ledger executing it and recording a failure. Even when a failure occurs during execution, the effects that remain depend on how much of the call was reverted.
In the case where a small transfer failed despite a sufficient balance, the problem arose while preparing usable inputs. This article takes up the next question: when a transaction fails, what happens to asset changes, events, fees, and the records that prevent the same transaction from being used again?
Start with where the failure occurred
Suppose A holds 100 units of asset X and B holds none. A wants to send 20 X to B. X is a different asset from NIGO, which pays transaction fees, and there is no additional minting or burning. A successful transfer would leave A with 80 X and B with 20 X.
The names are the same as in the preceding articles, but each failure example starts from a fresh initial state: A=100 and B=0. The balances do not carry over from an earlier example.
If the wallet cannot find suitable inputs and therefore cannot build a transaction to sign, the ledger has not executed the transfer. Even a submitted transaction can be rejected during validation—for example, if its signature is invalid or it refers to inputs that have already been spent. That rejection itself neither moves assets nor settles a fee.
A different case arises when a transaction passes the basic checks and reaches execution, but a program rejects it because a business condition is not met. This is a failure that can be recorded on the ledger as a processing result. When the sections below say that fees or replay-protection effects remain, they refer to a result that has been included in a block and committed. Merely attempting a provisional execution does not finalize a charge.
If the final condition rejects the transfer, earlier success is not final
Suppose this transfer must pass a Native program's policy checks. The article on the unified asset model distinguished transfers that may proceed directly from those that must go through a policy. Here, a transfer rejected by its policy is not routed around it through another path.
A policy can have one part that checks the transfer operation and another that checks additional conditions. In a composed policy, these are called ACTION and GUARD. Imagine that ACTION returns a result permitting the transfer of 20 X and even produces a transfer event, but the final GUARD rejects the transfer because a recipient condition is not satisfied.
Producing an event is not a reason to give B the 20 X immediately. A Native policy's execution output is not a final asset change until all required checks have passed. If the final check fails, the earlier result and events are not accepted either.
The final X balances are therefore A=100 and B=0. No successful transfer event remains. A receipt, the record of the transaction's processing result, may still record the failed execution. “No transfer succeeded” and “There is no transaction processing record” mean different things.
The regression tests target this distinction. They check that earlier logs and partial business effects do not leak into the result when ACTION has actually produced logs and the final GUARD then rejects execution or exhausts its execution budget. The operation used in those tests is a separate state change; the 100 X transfer above is an example for explaining the boundary.
A zero fee does not make the same signature reusable
Restoring the X balances does not mean restoring every piece of state involved in processing the transaction.
Separately from its business inputs, a Native transaction specifies owner-controlled NIGO inputs for fee settlement and replay protection. Replay protection prevents an already processed signed transaction from being applied again. Even when policy execution fails, these inputs are consumed, and their value minus the prescribed fee is returned in a change Cell that can serve as a new input.
Consider the ZERO fee policy. Suppose A specifies one Cell containing 10 NIGO for this purpose. The amount is illustrative, and the fee is zero.
- X is not transferred, so A still has 100 X and B has 0 X.
- The original 10 NIGO Cell is consumed, and A receives a new change Cell containing 10 NIGO.
- The total amount of NIGO is unchanged, but the same signed transaction still points to the old, now-spent Cell and cannot be applied again.
Under a fee-charging policy, the prescribed fee reduces the change. In the current Native path, the monetary fee is based on a cost that accounts for properties such as the size of the envelope—the signed transaction data. The receipt also records program execution work as gas, but multiplying that entire gas figure by a price does not give the correct Native transaction fee.
There are two reasons to make this distinction. A business failure does not erase the execution resources already used, and a chain that charges no monetary fee must still prevent repeated application of the same signature. Reverting business operations and settling transaction processing are separate responsibilities.
In EVM, distinguish a failed child call from a failed transaction
Let us briefly continue the example of using an asset in EVM after approving it in Native. Start again with A=100 X and B=0 X. A separate Native transaction granting business contract P an allowance of 30 X has already been committed. In the current EVM transaction, P wants to send 20 X of that allowance to B.
There are two failure boundaries to consider.
First, the asset-handling child call fails, but P handles that failure. Suppose the allowance is sufficient, but the asset call is rejected because an additional payment condition is not met. P checks the failed result, records “payment on hold” without making any other asset changes, and completes successfully. The failed asset call's changes and events are discarded. The X balances remain 100/0, and the remaining allowance is 30. P's payment-on-hold record, however, can survive if the overall transaction succeeds. A failed child call does not always mean that the outer transaction fails.
Second, the asset call succeeds, but P's overall business operation is later reverted. The child call may temporarily have calculated balances of 80/20 and a remaining allowance of 10. If P then fails a subsequent condition and executes REVERT, the changes and events within that call's scope are discarded together. The final result is once again 100/0 with an allowance of 30. The allowance of 30 that was committed in a separate, earlier transaction is not itself revoked.
Changes made during EVM execution accumulate in isolated provisional state and survive within a parent call's scope only if that parent succeeds. If the parent handles a child failure but later fails itself, even the payment-on-hold record it intended to keep is reverted. Conversely, a failed child call does not automatically cancel valid follow-up work performed by its parent.
Calling a Native asset policy from inside EVM does not commit a separate Native transaction either. It adds no separate Native fee or replay-protection input. The outer EVM transaction is responsible for the cost and processing result.
The outer transaction can leave a record even when assets are restored
Even if the entire EVM transaction executes REVERT or exhausts its gas limit, discarding business state is different from discarding the effects of processing the outer transaction.
An Ethereum-signed transaction uses an account's nonce, the sequence number for its next transaction, to prevent replay. If a valid transaction is executed and committed as a failure, consumption of that nonce and any applicable fee remain. A NIGO-signed EVM transaction instead prevents replay using the committed transaction's identity, without consuming the same ETH nonce. Not every EVM transaction follows the same nonce rules.
A Type-4 transaction, which delegates an account's execution code, adds another boundary. A validly applied code-delegation authorization and its associated nonce changes can survive a subsequent failure in the business call. This authorization concerns account code delegation; it is different from the allowance of 30 X in the example above.
The illustrative transfer can be summarized as follows. Both EVM rows assume that the allowance of 30 was committed in a separate transaction.
| Where the failure occurs | Final X state | Other records to examine |
|---|---|---|
| Preparation or outer validation fails | A=100, B=0 | No execution fee or success event from the rejection itself |
| Included Native policy rejection | A=100, B=0 | No transfer event. Failure receipt and NIGO fee/replay effects |
| EVM child fails; parent succeeds | A=100, B=0, allowance=30 | No failed-child events. Other parent work and outer processing effects may remain |
| Outer EVM operation reverts | A=100, B=0, allowance=30 | Business state/events discarded. Failure receipt and outer fee/replay effects remain |
Mentioning a fee does not always imply a positive monetary amount. Under ZERO, the monetary fee is zero. Under a fee-charging policy, the amount settled depends on the transaction format and the type of failure. The next article will examine the relationship between execution work and monetary cost, without treating every case—including exhaustion of the gas limit—as one formula.
Not every error should be recorded as a normal transaction failure
The discussion so far concerns business rejections and execution-budget exhaustion that can be determined under defined rules. If storage reads or the execution infrastructure fail, the system must not turn that problem into “the user's transfer failed” and produce a normal failure receipt. Such errors must propagate as block-execution failures, and uncommitted provisional changes must be discarded.
Simulation is another separate case. It can report success, failure, and estimated gas, but those results alone do not change actual balances or replay-protection records. A provisional attempt discarded after failing validation during parallel execution is likewise not the same as a failed transaction included in the ledger.
This article describes the boundaries found in the implementation and regression tests examined on October 19, 2026. State changes and receipts are persisted at the commit boundary of the enclosing block processing. The completion of a policy-validation function does not, by itself, mean that the result has been persisted.
To understand a failure, look beyond a single success flag and consider where it occurred, which business operations were reverted, and which transaction processing effects remained after commitment. That explains why a nonce can advance even when balances are restored, or why a signature cannot be reused even when the fee is zero.
This leads to the next question: why measure and limit execution work when no monetary fee is charged? The next article will separate the execution resources measured in gas from the cost settled in NIGO.