if numberOfReserves is zero then the _getSlotsOffset function will be get DOS, it can get out of gas.
function _getSlotsOffset(uint256 numberOfReserves) internal pure returns (uint256 _slotsOffset) {
_slotsOffset = ((numberOfReserves - 1) / 2 + 1) << 5;
}
function update(uint256[] calldata reserves, bytes calldata data) external {
(bytes16 alpha, uint256 capInterval, CapReservesParameters memory crp) =
abi.decode(data, (bytes16, uint256, CapReservesParameters));
uint256 numberOfReserves = reserves.length;
PumpState memory pumpState;
// All reserves are stored starting at the msg.sender address slot in storage.
bytes32 slot = _getSlotForAddress(msg.sender);
// Read: Last Timestamp & Last Reserves
(, pumpState.lastTimestamp, pumpState.lastReserves) = slot.readLastReserves();
// If the last timestamp is 0, then the pump has never been used before.
if (pumpState.lastTimestamp == 0) {
_init(slot, uint40(block.timestamp), reserves);
return;
}
bytes16 alphaN;
bytes16 deltaTimestampBytes;
uint256 capExponent;
// Isolate in brackets to prevent stack too deep errors
{
uint256 deltaTimestamp = _getDeltaTimestamp(pumpState.lastTimestamp);
// If no time has passed, don't update the pump reserves.
if (deltaTimestamp == 0) return;
alphaN = alpha.powu(deltaTimestamp);
deltaTimestampBytes = deltaTimestamp.fromUInt();
// Round up in case capInterval > block time to guarantee capExponent > 0 if time has passed since the last update.
capExponent = calcCapExponent(deltaTimestamp, capInterval);
}
pumpState.lastReserves = _capReserves(msg.sender, pumpState.lastReserves, reserves, capExponent, crp);
// Read: Cumulative & EMA Reserves
// Start at the slot after `pumpState.lastReserves`
@>> uint256 numSlots = _getSlotsOffset(numberOfReserves);
assembly {
slot := add(slot, numSlots)
function _init(bytes32 slot, uint40 lastTimestamp, uint256[] memory reserves) internal {
uint256 numberOfReserves = reserves.length;
bytes16[] memory byteReserves = new bytes16;
// Skip {_capReserve} since we have no prior reference
for (uint256 i; i < numberOfReserves; ++i) {
uint256 _reserve = reserves[i];
if (_reserve == 0) return;
byteReserves[i] = _reserve.fromUIntToLog2();
}
// Write: Last Timestamp & Last Reserves
slot.storeLastReserves(lastTimestamp, reserves);
// Write: EMA Reserves
// Start at the slot after `byteReserves`
@>> uint256 numSlots = _getSlotsOffset(numberOfReserves);
Many function will get out of gas due to zero input to the getSlotsOffset.
check numberOfReserves is greater than 0.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.