Colliding transaction nonces
Two iTRY workers could claim the same sequence number, and one of their orders died. Reserved nonces fixed that. My first recovery job then risked settling a transaction twice.
Try it: this is the bug, small enough to play with. Click a queued transaction to drop it.
- Orders
- 0
- Settled
- 0
- Collisions
- 0
- Settled twice
- 0
- Rebroadcast
- 0
- Failed submissions
- 0%
Each transaction from one account carries a number, and the network settles them strictly in order. When workers ask the network for the next number, two that ask together get the same one, and one of their orders dies. A slow transaction gets retried under a new number and can settle twice. Reserve numbers from a ledger and the collisions stop. Click a queued transaction to make the network drop it, and the ledger sends it back out under its own number. On iTRY, this change is how failed orders fell 90%.
iTRY is a regulated tokenized fund at Inverter Network. Investors pay in USDC and the fund deploys it into money-market funds. I owned the transaction path, from order submission to the reconciliation that proves what settled.
Every transaction from an account carries a sequence number, and the network will not settle 41 before 40. Workers asked the network for the next number just before submitting. Two workers asking at the same moment got the same answer, and one order died.
Reserved nonces
Number assignment moved into DynamoDB. A worker reserves its number with a conditional write that fails if another worker already holds it. A scheduled job resubmits stalled transactions and a reconciler picks up what the network dropped. Failed orders fell 90%.
Late or lost
My first recovery pass treated a missing transaction as failed and retried it. Some had already settled, and the retry could move value twice.
A transaction you cannot see is either late or lost. Late means wait. Lost means resubmit under the original number, which the network can settle only once. Most of my time on iTRY went into telling the two apart. The simulation above runs both versions side by side.