-
Notifications
You must be signed in to change notification settings - Fork 22
[BUG] matchRate assigns orders to providers outside their min/max order amount limits #688
Description
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
- Set up a provider with
minOrderAmount = 2.5for a token (e.g. USDC) - Initiate an order for
1 USDCtargeting the same currency/network - Let the order go through assignment (either initial assignment or reassignment via cancelled/stale order paths)
- 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.go→matchRatefunction
Additional context
There are 4 call paths into AssignPaymentOrder → matchRate:
| # | 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 AssignPaymentOrder → matchRate 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