59124 sc insight inefficient loop direction in periodconfigurationattimestamp causes unnecessary gas consumption

Submitted on Nov 9th 2025 at 01:34:00 UTC by @ZenHunter for Audit Comp | Firelight

  • Report ID: #59124

  • Report Type: Smart Contract

  • Report severity: Insight

  • Target: https://github.com/firelight-protocol/firelight-core/blob/main/contracts/FirelightVault.sol

  • Impacts:

Description

Brief/Intro

The periodConfigurationAtTimestamp function iterates through the periodConfigurations array from the beginning (index 0) to find the matching period configuration. Since period configurations are added in chronological order and most queries are for the current or recent periods (via currentPeriodConfiguration(), currentPeriod(), currentPeriodStart(), currentPeriodEnd(), and nextPeriodEnd()), iterating from the end backwards would be significantly more gas-efficient. While periodAtTimestamp() can be called with historical timestamps, these queries for historical periods are less common than queries for the current period. For arrays with many period configurations, this causes unnecessary gas consumption when querying recent periods, as the function must iterate through all older configurations first.

Vulnerability Details

The vulnerability exists in the periodConfigurationAtTimestamp function (lines 205-217):

function periodConfigurationAtTimestamp(uint48 timestamp) public view returns (PeriodConfiguration memory) {
    uint256 length = periodConfigurations.length;
    if (length == 0) revert InvalidPeriod();

    PeriodConfiguration memory periodConfiguration;
    for (uint256 i = 0; i < length; i++) {  // Iterates from beginning
        if (timestamp < periodConfigurations[i].epoch)
            break;
        periodConfiguration = periodConfigurations[i];
    }
    if (periodConfiguration.epoch == 0) revert InvalidPeriod();
    return periodConfiguration;
}

The Problem:

  1. Period configurations are added in chronological order: The _addPeriodConfiguration function (lines 799-825) ensures that new configurations are only added after the last one, confirming they are stored chronologically.

  2. Most queries are for recent periods: Functions like currentPeriod(), currentPeriodConfiguration(), currentPeriodStart(), currentPeriodEnd(), and nextPeriodEnd() all query the current or near-future period, which will be the most recent configuration. While periodAtTimestamp() can accept historical timestamps, these queries for historical periods are less common than queries for the current period.

  3. Inefficient iteration: When querying recent periods, the function must iterate through all older configurations first, causing unnecessary gas consumption.

Gas Cost Analysis:

  • Current approach: For an array with N configurations, querying the last configuration requires N storage reads (SLOAD operations at ~2100 gas each).

  • Optimized approach: Iterating from the end backwards would require only 1 storage read for the most common case (current period).

Example Scenario:

If there are 10 period configurations:

  • Querying the current period (the last configuration at index 9) requires 10 iterations and 10 storage reads

  • With reverse iteration, it would require only 1 iteration and 1 storage read

Impact Details

This gas optimization issue causes unnecessary gas consumption when querying recent period configurations. Since most queries are for the current period (which is the most recent configuration), iterating from the beginning of the array wastes gas by reading through all older configurations. As the vault operates over time and more period configurations are added, this inefficiency compounds, making period-related queries increasingly expensive. The impact is particularly significant for frequently called functions like currentPeriod(), currentPeriodConfiguration(), currentPeriodStart(), and currentPeriodEnd(), all of which call periodConfigurationAtTimestamp internally.

References

  • contracts/FirelightVault.sol

Recommendation

Optimize the loop to iterate from the end backwards, as period configurations are stored in chronological order and most queries are for recent periods.

Fix for periodConfigurationAtTimestamp:

Proof of Concept

Proof of Concept

A runnable PoC test demonstrates the gas inefficiency by measuring gas costs for querying recent periods with varying numbers of period configurations.

PoC Test Code:

The test file test/gas_optimization_period_configuration_loops_poc.js:

Test Results:

Running npx hardhat test test/gas_optimization_period_configuration_loops_poc.js:

Gas Cost Analysis:

  • 1 configuration: ~34,280 gas

  • 5 configurations: ~51,494 gas (+17,214 gas, +50% increase)

  • 10 configurations: ~76,549 gas (+42,269 gas, +123% increase)

Was this helpful?