mirror of
https://github.com/luxfi/precompile.git
synced 2026-07-27 03:33:45 +00:00
The 0x9999 money path: V4 ABI swap -> NativeDChainClient -> C staged -> shared-memory export/import -> D dexvm atomic import/export (Mode A async, no BLS). C SETTLES, C never matches. Value crosses ONLY as a primary-network atomic shared-memory object. The BLS cert / VerifierRegistry / DFillReceipt value path is ripped (quarantined under dex/_deprecated_bls/). Ship rule (structural, not trust): C credited ONLY by consuming a D->C object (ImportSettlement); D funded ONLY by consuming a C->D object (SubmitSwapIntent -> dexvm executeImport). Atomic ops are STAGED in EVM state during execution (revert-aware) and flushed to shared memory at block accept over the deterministic parent->current seq window. contract.AtomicState: the optional host capability a precompile type-asserts to reach atomic shared memory (the platformvm/dexvm import/export primitive). Red fixes applied to the seam: FIX 2 (consensus-liveness chain-halt): native_staging.go FlushAcceptedAtomicOps already takes a batch; the flush is now one-batch-atomic at the host (see evm block.go/vm.go) — the SM Apply and the seq-marker advance commit all-or- nothing, closing the crash-between-Apply-and-marker -> duplicate-Put -> halt window. Regression: native_haltwindow_test.go (re-accept after a committed window is a clean no-op; crash-before-commit re-applies cleanly; the marker must ride the Apply batch). FIX 3 (conservation blast-radius): native_state.go adds seamReserve[a], the seam's OWN pot, decoupled from the depositor pot (settleVault) and the maker pot (makerLockedVault). lockIntentInput funds seamReserve; creditSettlementOutput checks+debits seamReserve. A settlement credit can never raid a depositor's claim; a withdraw can never strand a backed settlement. Invariant realHolding == settleVault + makerLockedVault + seamReserve. Regression: native_conservation_test.go (both subsystems, same asset). FIX 4 (reentrancy defense-in-depth): SettleSwap now takes the same single custody guard slot as deposit/withdraw/modifyLiquidity (enterCustodyKV), so the whole 0x9999 money surface is single-in-flight and an ERC-20 transfer callback cannot re-enter. Regression: native_callindex_test.go (callIndex determinism + intent-id collision-freedom across two swaps + a reverted sub-frame + a STATICCALL; SettleSwap non-reentrant + guard released for sequential calls). 305 prior + 10 new dex tests pass (CGO_ENABLED=0). Live-EVM-call-tree and live-crash-injection tests are CI-only (CGO + luxfi/accel LUXCPP).
29 lines
1.5 KiB
Go
29 lines
1.5 KiB
Go
// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package dex
|
|
|
|
// asset.go holds the asset-identity helper shared by the whole DEX precompile —
|
|
// the injective map from a 20-byte EVM currency address to its canonical 32-byte
|
|
// asset id. It is value-NEUTRAL (no balances, no chains) and is used by the native
|
|
// C<->D seam, custody, and market binding so every surface names the same asset.
|
|
//
|
|
// (Decomplected out of the deprecated engine_zap.go ZAP backend: assetID is a pure
|
|
// identity function with no dependency on the ZAP transport that was ripped from
|
|
// the value path. One asset-identity function, one place.)
|
|
|
|
// assetID maps a 20-byte EVM currency address to its canonical 32-byte asset id,
|
|
// the FULL key the ledger / atomic objects key value by — NOT a truncated handle.
|
|
// The map is INJECTIVE: the 20-byte address is left-padded into 32 bytes (12 zero
|
|
// bytes + the 20 address bytes), so two distinct token addresses — or a token vs
|
|
// native — ALWAYS produce distinct ids. Native LUX (address(0)) maps to the
|
|
// all-zero id; since no real ERC-20 has the zero address, native never collides
|
|
// with a token. The chains/dexvm atomic side keys the same value by the full
|
|
// 32-byte cross-chain ids.ID (native == ids.Empty == all-zero), so a native op
|
|
// agrees across both rails and an ERC-20 only enters via this precompile rail.
|
|
func assetID(c Currency) [32]byte {
|
|
var id [32]byte
|
|
copy(id[12:], c.Address.Bytes())
|
|
return id
|
|
}
|