Skip to content

[BUG] matchRate assigns orders to providers outside their min/max order amount limits #688

@onahprosper

Description

@onahprosper

Describe the bug

The matchRate function in services/priority_queue.go does not validate a provider's minOrderAmount / maxOrderAmount before assigning an order. This causes providers to receive orders outside their configured range — for example, a provider with minOrderAmount=2.5 USDC was assigned a 1 USDC order.

A misleading comment in matchRate stated:

"amount limits and OTC checks already done by ValidateRate/findSuitableProviderRate"

This is incorrect. ValidateRate / findSuitableProviderRate are not called before matchRate in most code paths, and even when they are, they do not pre-filter the Redis queue that matchRate iterates.

To Reproduce

  1. Set up a provider with minOrderAmount = 2.5 for a token (e.g. USDC)
  2. Initiate an order for 1 USDC targeting the same currency/network
  3. Let the order go through assignment (either initial assignment or reassignment via cancelled/stale order paths)
  4. Observe the order is assigned to the provider despite 1 < 2.5

This is most reliably triggered via reassignment paths (cancelled or stale orders) since those skip ValidateRate entirely.

Expected behavior

The provider should be skipped during matchRate iteration because the order amount (1 USDC) is below their configured minimum (2.5 USDC). The order should be assigned to another eligible provider whose limits accommodate the amount.

Screenshots

N/A — backend logic bug, no UI involved.

Environment:

  • OS: Linux (production server)
  • Service: aggregator
  • Component: services/priority_queue.gomatchRate function

Additional context

There are 4 call paths into AssignPaymentOrdermatchRate:

# Call path ValidateRate called before?
1 Blockchain order creation (order.go:983) Yes
2 Reassign cancelled order (order_requests.go:126) No
3 Reassign stale order (order_requests.go:284) No
4 Recursive reassignment from matchRate itself (priority_queue.go:1265) No

Paths 2, 3, and 4 call AssignPaymentOrdermatchRate with zero amount limit validation beforehand.

Even for Path 1, ValidateRate picks the best rate from the Redis queue and returns a single result — it does NOT modify or filter the queue. matchRate can then match a completely different provider whose min/max limits don't fit the order.

Fix: #687

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions