#59054 [SC-Low] periodattimestamp returns incorrect period number

Submitted on Nov 8th 2025 at 07:41:35 UTC by @dldLambda for Audit Comp | Firelight

  • Report ID: #59054

  • Report Type: Smart Contract

  • Report severity: Low

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

  • Impacts:

Description

Brief/Intro

The function periodAtTimestamp(uint48 timestamp) is intended to return the period number corresponding to a given timestamp. It uses _sinceEpoch(periodConfiguration.epoch) to compute the offset.

_sinceEpoch() always uses Time.timestamp() (the current timestamp) instead of the provided timestamp. As a result, no matter what historical timestamp is queried, the function calculates the period offset from the present, always returning the current period or a future period.

Vulnerability Details

The periodAtTimestamp(uint48 timestamp) function promises to return the period number for any timestamp, but in reality it always returns current period:

    /**
     * @notice Returns the period number for the timestamp given.
     * @dev Return value may be unreliable if period number given is far away in the future
     * @dev given that new period configurations can be added after nextPeriodEnd().
     * @return The period number corresponding to the given timestamp.
     */
    function periodAtTimestamp(uint48 timestamp) public view returns (uint256) {
        PeriodConfiguration memory periodConfiguration = periodConfigurationAtTimestamp(timestamp);
        // solhint-disable-next-line max-line-length
        return periodConfiguration.startingPeriod + _sinceEpoch(periodConfiguration.epoch) / periodConfiguration.duration;
    }

For example:

  1. Vault deployed at epoch = 1,000,000, startingPeriod = 0

  2. Period duration = 100 seconds

  3. Historical timestamp: timestamp = 1,003,600

  4. Correct period calculation: (timestamp - epoch) / duration = (1,003,600 - 1,000,000) / 100 = 36

  5. Contract calculation: _sinceEpoch(epoch) = Time.timestamp() - epoch = 1,010,000 - 1,000,000 = 10,000

  6. Returned period: startingPeriod + _sinceEpoch(epoch)/duration = 0 + 10,000 / 100 = 100

The same problem will occur if you pass a future timestamp.

However, at the moment, the function is only called in the currentPeriod function, which implies the current epoch. However, in the future, it may be used elsewhere, called in other places, and since it doesn't do what it says, this could cause major problems.

Impact Details

The function doesn't perform as expected, always returning the current period. If used elsewhere, any logic that relies on periodAtTimestamp() for historical accounting, rewards, or entitlement calculations will be broken.

References

https://github.com/firelight-protocol/firelight-core/blob/db36312f1fb24efc88c3fde15a760defbc3e6370/contracts/FirelightVault.sol#L246

Proof of Concept

Proof of Concept

Please add and run this test:

You will see:

Was this helpful?