function createSellOrder(
address _tokenToSell,
uint256 _amountToSell,
uint256 _priceInUSDC,
uint256 _deadlineDuration
) public returns (uint256) {
uint256 orderId = _nextOrderId++;
IERC20(_tokenToSell).safeTransferFrom(msg.sender, address(this), _amountToSell);
orders[orderId] = Order({
id: orderId,
seller: msg.sender,
tokenToSell: _tokenToSell,
amountToSell: _amountToSell,
priceInUSDC: _priceInUSDC,
deadlineTimestamp: deadlineTimestamp,
isActive: true
});
}
function amendSellOrder(
uint256 _orderId,
uint256 _newAmountToSell,
uint256 _newPriceInUSDC,
uint256 _newDeadlineDuration
) public {
if (_newAmountToSell > order.amountToSell) {
uint256 diff = _newAmountToSell - order.amountToSell;
token.safeTransferFrom(msg.sender, address(this), diff);
} else if (_newAmountToSell < order.amountToSell) {
uint256 diff = order.amountToSell - _newAmountToSell;
token.safeTransfer(order.seller, diff);
}
order.amountToSell = _newAmountToSell;
order.priceInUSDC = _newPriceInUSDC;
order.deadlineTimestamp = newDeadlineTimestamp;
}
function buyOrder(uint256 _orderId) public {
order.isActive = false;
uint256 protocolFee = (order.priceInUSDC * FEE) / PRECISION;
uint256 sellerReceives = order.priceInUSDC - protocolFee;
iUSDC.safeTransferFrom(msg.sender, address(this), protocolFee);
iUSDC.safeTransferFrom(msg.sender, order.seller, sellerReceives);
IERC20(order.tokenToSell).safeTransfer(msg.sender, order.amountToSell);
totalFees += protocolFee;
}
The CEI pattern violations create multiple attack vectors that can be exploited through malicious token contracts.
Implement the CEI pattern consistently across all functions by performing all state updates before external calls and add reentrancy protection
function createSellOrder(
address _tokenToSell,
uint256 _amountToSell,
uint256 _priceInUSDC,
uint256 _deadlineDuration
) public returns (uint256) {
// ... validation checks ...
uint256 deadlineTimestamp = block.timestamp + _deadlineDuration;
uint256 orderId = _nextOrderId++;
- IERC20(_tokenToSell).safeTransferFrom(msg.sender, address(this), _amountToSell);
-
- orders[orderId] = Order({
+ // Update state BEFORE external call (CEI pattern)
+ orders[orderId] = Order({
id: orderId,
seller: msg.sender,
tokenToSell: _tokenToSell,
amountToSell: _amountToSell,
priceInUSDC: _priceInUSDC,
deadlineTimestamp: deadlineTimestamp,
isActive: true
})
+
+ // External call AFTER state update
+ IERC20(_tokenToSell).safeTransferFrom(msg.sender, address(this), _amountToSell);
emit OrderCreated(orderId, msg.sender, _tokenToSell, _amountToSell, _priceInUSDC, deadlineTimestamp);
return orderId;
}
function amendSellOrder(
uint256 _orderId,
uint256 _newAmountToSell,
uint256 _newPriceInUSDC,
uint256 _newDeadlineDuration
) public {
// ... validation checks ...
uint256 newDeadlineTimestamp = block.timestamp + _newDeadlineDuration;
IERC20 token = IERC20(order.tokenToSell);
+ // Update state BEFORE external calls (CEI pattern)
+ uint256 oldAmount = order.amountToSell;
+ order.amountToSell = _newAmountToSell;
+ order.priceInUSDC = _newPriceInUSDC;
+ order.deadlineTimestamp = newDeadlineTimestamp;
+
- if (_newAmountToSell > order.amountToSell) {
+ if (_newAmountToSell > oldAmount) {
- uint256 diff = _newAmountToSell - order.amountToSell;
+ uint256 diff = _newAmountToSell - oldAmount;
token.safeTransferFrom(msg.sender, address(this), diff);
- } else if (_newAmountToSell < order.amountToSell) {
+ } else if (_newAmountToSell < oldAmount) {
- uint256 diff = order.amountToSell - _newAmountToSell;
+ uint256 diff =