Skip to content

fix(lib): copy OrderId in DexLimitOrder.Copy - #588

Open
Alicepoltora wants to merge 1 commit into
canopy-network:developmentfrom
Alicepoltora:fix/dex-copy-orderid
Open

fix(lib): copy OrderId in DexLimitOrder.Copy#588
Alicepoltora wants to merge 1 commit into
canopy-network:developmentfrom
Alicepoltora:fix/dex-copy-orderid

Conversation

@Alicepoltora

Copy link
Copy Markdown

Description

DexLimitOrder has four fields (amountForSale, requestedAmount, address, OrderId), but DexLimitOrder.Copy() only copies the first three - OrderId is silently dropped.

DexBatch.CopyOrders builds both order slices via order.Copy(), so every consumer downstream of it sees OrderId == nil. In fsm/dex.go that value is passed straight into the emitted swap event:

if err = s.EventDexSwap(order.Address, order.OrderId, dX, dY, chainId, false, dY != 0); err != nil {

The OrderId is populated correctly upstream (fsm/transaction.go sets it to the first 20 bytes of the tx hash, and fsm/message.go carries it into the batch), so the local-origin settlement path reads it off the batch directly and works. Only the remote-origin path goes through Copy() and loses it.

The result is that cross-chain DEX swap events are emitted with an empty orderId while local ones carry the correct value. Since orderId is part of the public event JSON, off-chain indexers and API consumers cannot correlate a remote swap back to its originating order.

This is deterministic across nodes and does not affect consensus - events are not part of the state root or TransactionRoot - so the impact is observability/indexing correctness rather than funds or liveness.

Related Issues

None found - I searched open and closed issues and PRs for DexLimitOrder / OrderId / dex copy semantics and found nothing covering this.

Changes Made

  • DexLimitOrder.Copy() now copies OrderId via bytes.Clone, matching how Address is already handled.
  • Strengthened the existing TestDexLimitOrder_Copy: it now sets OrderId, asserts both Address and OrderId round-trip, and asserts the copy is genuinely deep by mutating the original's slices afterwards.

The existing test never set OrderId, which is why the omission went unnoticed.

Checklist

  • I have tested the changes locally and verified they work as intended.
  • I have appropriately titled my branch issue-#<issue-number>. (No issue exists for this; happy to rename if you'd like one opened first.)
  • I have run re-built the web-wallet and/or block explorer (if applicable). (Not applicable - Go only.)
  • I have run npm run prettier to format the web-wallet and/or block explorer (if applicable). (Not applicable.)
  • I have updated documentation (if applicable). (Not applicable.)
  • I have included tests for the changes (if applicable).

Additional Notes

Verification on development:

  • The strengthened test fails before the fix (expected orderId 6f726465722d69642d32302d62797465732d3030, got - empty) and passes after it.
  • go test ./lib/ passes in full.
  • go test $(go list ./... | grep -v cmd/auto-update) - the CI test command - passes across the repository.
  • go build ./... succeeds; gofmt reports no changes for either touched file.

One adjacent observation I deliberately left out to keep this PR single-purpose: DexBatch.Copy() is shallow - Orders/Deposits/Withdrawals/Receipts alias the original slices. I traced the current processing paths and found no in-place mutation of those slices today, so it is latent fragility rather than a live bug. Happy to follow up separately if you'd like it hardened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant