To improve practicality and accessibility, consider the following solutions:
- Enable Partial Order Filling: Update the protocol (e.g., the buyOrder function) to allow buyers to specify a desired token amount, up to the total available in the order.
- Proportional Pricing: Calculate the cost based on the portion purchased (e.g., buying 2.5 WETH from the example order would cost 6,000 USDC).
- Update Order State: After a partial purchase, adjust the order’s amountToSell to reflect the remaining tokens (e.g., reduce it from 5 WETH to 3.75 WETH after a 1.25 WETH purchase).
- Adjust Fees: Base any transaction fees on the purchased amount, not the full order, to maintain fairness.
These changes would make the protocol more flexible, inclusive, and efficient, likely increasing user adoption and market activity.
// --- Constants ---
//resr of contrants
+ uint256 public constant MIN_PARTIAL_AMOUNT = 1000; // Minimum amount for partial orders (adjustable)
// --- Events ---
//rest of events
event OrderCreated(
+ uint256 pricePerUnit,
);
event OrderFilled(
//rest of params
+ uint256 amountBought,
+ uint256 totalPrice,
+ bool orderFullyFilled
);
event OrderPartiallyFilled(
+ uint256 indexed orderId,
+ address indexed buyer,
+ address indexed seller,
+ uint256 amountBought,
+ uint256 remainingAmount,
+ uint256 totalPrice
);
// --- Errors ---
// rest of error logs
+ error InsufficientOrderAmount();
+ error AmountTooSmall();
+ function buyOrder(uint256 _orderId, uint256 _amountToBuy) public {
Order storage order = orders[_orderId];
// Validation checks
if (order.seller == address(0)) revert OrderNotFound();
if (!order.isActive) revert OrderNotActive();
if (block.timestamp >= order.deadlineTimestamp) revert OrderExpired();
+ if (_amountToBuy == 0) revert InvalidAmount();
+ if (_amountToBuy > order.amountToSell) revert InsufficientOrderAmount();
+ // Check minimum partial amount (prevents dust orders)
+ if (_amountToBuy < MIN_PARTIAL_AMOUNT && _amountToBuy != order.amountToSell) {
+ revert AmountTooSmall();
}
+ // Calculate total price for the amount being bought
+ uint256 totalPrice = (_amountToBuy * order.pricePerUnit) / (10 ** 18); // Assuming 18 decimals for most tokens
uint256 protocolFee = (totalPrice * FEE) / PRECISION;
uint256 sellerReceives = totalPrice - protocolFee;
// Update order state
+ order.amountToSell -= _amountToBuy;
+ bool orderFullyFilled = (order.amountToSell == 0);
+ if (orderFullyFilled) {
+ order.isActive = false;
+ }
// Execute transfers
iUSDC.safeTransferFrom(msg.sender, address(this), protocolFee);
iUSDC.safeTransferFrom(msg.sender, order.seller, sellerReceives);
- IERC20(order.tokenToSell).safeTransfer(msg.sender, order.amountToSell); //external call
+ IERC20(order.tokenToSell).safeTransfer(msg.sender, _amountToBuy);
totalFees += protocolFee;
// Emit appropriate events
+ if (orderFullyFilled) {
+ emit OrderFilled(_orderId, msg.sender, order.seller, _amountToBuy, totalPrice, true);
+ } else {
+ emit OrderPartiallyFilled(_orderId, msg.sender, order.seller, _amountToBuy, order.amountToSell, totalPrice);
+ }
}