Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: medium
Valid

Array index out-of-bound access in vault configuration

Bug description

src/market-making/leaves/Market.sol
function configureConnectedVaults(Data storage self, uint128[] memory vaultsIds) internal {
EnumerableSet.UintSet[] storage connectedVaults = self.connectedVaults;
for (uint256 i; i < vaultsIds.length; i++) {
// @audit-issue out-of-bound access
connectedVaults[connectedVaults.length].add(vaultsIds[i]);
}
}

The function contains a critical array index calculation error where it attempts to access connectedVaults[connectedVaults.length]. Since array indices are 0-based, this always references an invalid index position:

  1. When array is empty (length=0): Attempts to access index 0

  2. When array has N elements: Attempts to access index N (valid indices are 0..N-1)

This violates Solidity's array bounds checking, causing the tx to revert.

PoC

Deploy the following code in Remix IDE:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
contract MarketPoC {
using EnumerableSet for EnumerableSet.UintSet;
struct MarketData { EnumerableSet.UintSet[] connectedVaults; }
MarketData internal market;
function configureConnectedVaults(uint128[] memory vaultsIds) public {
EnumerableSet.UintSet[] storage connectedVaults = market.connectedVaults;
for (uint256 i; i < vaultsIds.length; i++) {
connectedVaults[connectedVaults.length].add(vaultsIds[i]); // Will revert
}
}
function test() external {
uint128[] memory ids = new uint128[](1);
ids[0] = 123;
configureConnectedVaults(ids); // Transaction reverts
}
}

Call test() and the tx reverts.

Recommendation

Use push() to create new empty set at end of array and write to that new set:

function configureConnectedVaults(Data storage self, uint128[] memory vaultsIds) internal {
// Create a NEW UintSet instance and add to array
self.connectedVaults.push(); // Creates new empty set at end
// Get reference to the last element (newly created set)
EnumerableSet.UintSet storage currentVaultSet =
self.connectedVaults[self.connectedVaults.length - 1];
// Add all vault IDs to the new set
for (uint256 i; i < vaultsIds.length; i++) {
currentVaultSet.add(vaultsIds[i]);
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

`Market::configureConnectedVaults` Will Always Fail with Array Out of Bounds Error

Support

FAQs

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