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++) {
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:
When array is empty (length=0): Attempts to access index 0
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:
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]);
}
}
function test() external {
uint128[] memory ids = new uint128[](1);
ids[0] = 123;
configureConnectedVaults(ids);
}
}
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 {
self.connectedVaults.push();
EnumerableSet.UintSet storage currentVaultSet =
self.connectedVaults[self.connectedVaults.length - 1];
for (uint256 i; i < vaultsIds.length; i++) {
currentVaultSet.add(vaultsIds[i]);
}
}