mirror of
https://github.com/luxfi/dex.git
synced 2026-09-24 00:26:31 +00:00
The C transaction contains an Order. D matches it and certifies an Execution — price and quantity guaranteed and reserved. The C block carries that Execution. EVM execution verifies it and returns the resulting BalanceDelta. When the child of the Execution's C parent is accepted, D settles it into a Trade if that child used it, or Releases the reservation if it did not. This is the consensus-side half: the certified object, its canonical encoding and domain-separated commitment, and the lifecycle. WHY IT IS SHAPED THIS WAY C never queries D's live state during EVM execution — that would fork C on the first swap, since validators sit at different D heights. Instead D's statement rides in the block and C verifies it. On replay D can be dead, the GPU gone, D a billion blocks ahead; C has parent state, transactions, the statement, and the certificate. That is the entire input set. Move-typed storage, not a status field. ReservedExecution, Trade and Released are distinct types under distinct key prefixes, and a transition MOVES the object. Settle(Trade) and Release(Trade) do not compile — there is no reserved execution left to hand them. This is aimed squarely at the live defect where the intent record is written back only inside the same-asset refund branch, so the ordinary proceeds outcome leaves it Open with its full principal and the deadline reclaim later refunds money already spent out of other traders' pooled reserve. That is a field someone forgot to set on one code path; here there is no field to forget. An unauthenticated execution cannot enter the lifecycle: VerifiedExecution is an interface with an unexported method, so only VerifyExecution can produce one, and Reserve takes nothing else. AcceptedBlock is the same shape, so a settle or release can never be driven by a clock or a bare block id. The reservation is keyed by CChain + CParent + ExecID — the parent OPPORTUNITY, never a candidate block — so competing candidates all name one reservation and none of them moves it. FIX Latest externally, small internal vocabulary. ExecType (the event) and OrdStatus (the resulting state) exist on the wire and are kept distinct per FIX; they are never the internal source of truth. There is deliberately NO FIX state for the provisional reservation — it is internal consensus machinery, and a Trade is published only after C acceptance, which is what keeps the explorer's CLOB honest. 15 tests, all passing: encoding injectivity over every field, domain separation, verifier-supplied parent binding, terminal exclusivity, replay refusal. Co-authored-by: Hanzo Dev <[email protected]>