DittoETH

Ditto
DeFiFoundryOracle
55,000 USDC
View results
Submission Details
Severity: medium
Invalid

Unbounded loop used in findOrderHintId() function

Summary

The function libOrders.sol::findOrderHintId() contains an unbounded loop. Such loops are potential targets for Denial of Service (DoS) attacks, especially when the function is externally accessible.

Vulnerability Details

A malicious user might exploit this by invoking the libOrders.sol::findOrderHintId() function with an excessively large orderHintsArrayvia libOrders.sol::addAsk, libOrders.sol::addBid or libOrders.sol::addShort functions. This could cause the function to execute for an extended period, possibly exhausting the transaction's gas allowance. As a result, the gas expenses might become exorbitant, rendering the function infeasible for regular use.

Impact

Should an attacker repeatedly dispatch transactions with large arrays, it might congest the network. Consequently, other users might experience delays in their transactions or face escalated gas fees. The heightened gas costs might discourage both everyday users and the contract developers from invoking the combineShorts function, especially if they foresee potential transaction failures due to the attacker's actions.

Tools Used

Manual Review
Foundry

Recommendations

To mitigate this, a hard limit should be set on orderHintArray elements to restrict the number of loops that can be performed. A rough maximum number should be enough; e.g. < 8

function findOrderHintId(
mapping(address => mapping(uint16 => STypes.Order)) storage orders, // s.asks or s.shorts
address asset,
MTypes.OrderHint[] memory orderHintArray
) internal returns (uint16 hintId) {
>>> for (uint256 i; i < 8; i++) {
MTypes.OrderHint memory orderHint = orderHintArray[i];
O hintOrderType = orders[asset][orderHint.hintId].orderType;
if (hintOrderType == O.Cancelled || hintOrderType == O.Matched) {
emit Events.FindOrderHintId(0);
continue;
} else if (
orders[asset][orderHint.hintId].creationTime ==
orderHint.creationTime
) {
emit Events.FindOrderHintId(1);
return orderHint.hintId;
} else if (
orders[asset][orderHint.hintId].prevOrderType == O.Matched
) {
emit Events.FindOrderHintId(2);
return Constants.HEAD;
}
}
revert Errors.BadHintIdArray();
}
Updates

Lead Judging Commences

0xnevi Lead Judge
almost 2 years ago
0xnevi Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Other

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.