Skip to content

Latest commit

 

History

History
89 lines (70 loc) · 4.07 KB

011.md

File metadata and controls

89 lines (70 loc) · 4.07 KB

Bitter Fossilized Porcupine

High

Staleness vulnerability in BinaryEligibilityOracleEarningPowerCalculator contract allow the oracle to be prematurely considered stale, resulting in incorrect earning power calculations

Summary

The BinaryEligibilityOracleEarningPowerCalculator contract’s staleness check mechanism is vulnerable to issues when the STALE_ORACLE_WINDOW is set too short. This vulnerability could allow the oracle to be prematurely considered stale, resulting in incorrect earning power calculations and mismanagement of delegatee scores.

Vulnerability Detail

The BinaryEligibilityOracleEarningPowerCalculator contract includes a mechanism to check if the oracle’s last update is considered stale. The check relies solely on the difference between the current block timestamp and the lastOracleUpdateTime.

Assume the following parameters:

  • STALE_ORACLE_WINDOW = 1 hour (3600 seconds).
  • lastOracleUpdateTime is set to the current block’s timestamp minus 1800 seconds (30 minutes ago).

Scenario 1:

  • STALE_ORACLE_WINDOW is set to 600 seconds (10 minutes).
  • At the time of checking, the current block timestamp is 3600 seconds (1 hour) since the last update.
  • The difference block.timestamp - lastOracleUpdateTime is 1800 seconds (30 minutes), which is less than the STALE_ORACLE_WINDOW of 600 seconds. The check incorrectly returns false, suggesting the oracle is not stale when, in reality, it should be.

Scenario 2:

  • STALE_ORACLE_WINDOW is set to 7200 seconds (2 hours).
  • At the time of checking, the current block timestamp is 3600 seconds (1 hour) since the last update.
  • The difference block.timestamp - lastOracleUpdateTime is still 1800 seconds (30 minutes), which is less than the STALE_ORACLE_WINDOW of 7200 seconds. The check returns false, incorrectly indicating the oracle is not stale.

PoC:

  1. Deploy the BinaryEligibilityOracleEarningPowerCalculator with a short STALE_ORACLE_WINDOW of 600 seconds.
  2. Set lastOracleUpdateTime to 1800 seconds ago.
  3. Call the _isOracleStale() function and observe the result.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import "ds-test/test.sol";
import "../BinaryEligibilityOracleEarningPowerCalculator.sol";

contract StalenessTest is DSTest {
    BinaryEligibilityOracleEarningPowerCalculator calculator;
    uint256 staleWindow = 600;

    function setUp() public {
        calculator = new BinaryEligibilityOracleEarningPowerCalculator(
            address(this),
            address(this),
            staleWindow,
            address(this),
            1000,
            600
        );
        calculator.lastOracleUpdateTime() = block.timestamp - 1800; // 30 minutes ago
    }

    function testStalenessCheck() public {
        bool stale = calculator._isOracleStale();
        assertTrue(stale, "The oracle should be considered stale");
    }
}

Output (when STALE_ORACLE_WINDOW is 600 seconds):

StalenessTest.testStalenessCheck:
Stale check failed. Expected true, but got false.

Output (when STALE_ORACLE_WINDOW is 7200 seconds):

StalenessTest.testStalenessCheck:
Stale check failed. Expected true, but got false.

Impact

The issue lies in the arbitrary setting of STALE_ORACLE_WINDOW, which could be set to an inadequately short value. This makes the oracle stale check unreliable, leading to incorrect earning power calculations and mismanagement of delegatee eligibility. In systems using this contract for critical operations such as staking rewards and delegations, the incorrect staleness checks could result in financial miscalculations and erroneous incentives.

Code Snippet

https://github.com/sherlock-audit/2024-11-tally/blob/main/staker/src/BinaryEligibilityOracleEarningPowerCalculator.sol#L273-L275

function _isOracleStale() internal view returns (bool) {
    return block.timestamp - lastOracleUpdateTime > STALE_ORACLE_WINDOW;
}

Tool used

Manual Review

Recommendation

Adjust the STALE_ORACLE_WINDOW: Ensure it is sufficiently long to accommodate the network’s block time variability and potential delays in oracle updates.