The `OrderBook` contract stores all orders in a global orders mapping indexed by order ID. Each Order struct contains the seller address, but there is no mapping or mechanism to track which orders were created by a specific user. As a result, on-chain queries to retrieve all orders created by a specific user are not possible without scanning the entire orders mapping.
This design choice limits efficient user-specific order analytics, auditing, and UI/UX features that require user-specific filtering of order data. Off-chain systems must iterate through all order IDs and filter by the seller field, which becomes increasingly expensive and impractical as the number of orders grows.
Risk
Impact:
- Degraded on-chain queryability: user-specific order lookups are not feasible.
- Poor UX for dApps requiring order history per user.
- Analytics and auditing tools need to perform full scans, impacting performance.
- Limits contract extensibility for features like user dashboards, portfolio summaries, or per-user notifications.
Proof of Concept
1. Civil creates three sell orders.
2. Newton creates two sell orders.
There is no on-chain method to fetch “all orders by Civil”.
Frontend or analytics tools must iterate over all existing orderIds and check orders[id].seller == Civil.
Recommended Mitigation
Add a mapping that associates each user with the order IDs they’ve created:
Then in `createSellOrder()`:
+ mapping(address => uint256[]) public userOrders;