Skip to content
This repository was archived by the owner on Jan 7, 2024. It is now read-only.
This repository was archived by the owner on Jan 7, 2024. It is now read-only.

0xbepresent - The Vault._to_usd_oracle_price() function uses the same ORACLE_FRESHNESS_THRESHOLD for all token prices feeds which is incorrect #104

Description

@sherlock-admin

0xbepresent

medium

The Vault._to_usd_oracle_price() function uses the same ORACLE_FRESHNESS_THRESHOLD for all token prices feeds which is incorrect

Summary

The same ORACLE_FRESHNESS_THRESHOLD is used for all the token prices feeds which can be dangerous because different pairs of tokens have different freshness intervals.

Vulnerability Detail

The ORACLE_FRESHNESS_THRESHOLD is 24 hours constant. It is used to check if the Oracle price is fresh in the 580 code line.

File: Vault.vy
562: def _to_usd_oracle_price(_token: address) -> uint256:
...
...
576:     round_id, answer, started_at, updated_at, answered_in_round = ChainlinkOracle(
577:         self.to_usd_oracle[_token]
578:     ).latestRoundData()
579: 
580:     assert (block.timestamp - updated_at) < ORACLE_FRESHNESS_THRESHOLD, "oracle not fresh"
...
...

The problem is that different pairs have diferrent heartbeats. For example the LINK/USD has a heartbeat of 3600 seconds so since the ORACLE_FRESHNESS_THRESHOLD is set to 24 hours, the check for LINK/USD is useless since the its hearbeat is 3600 seconds. The same behaivour in CRV/USD which has a heartbeat of 3600 seconds.

Impact

Using the same ORACLE_FRESHNESS_THRESHOLD (heartbeat) for all the price feeds is not correct becuase the freshness validation would be useless for some pairs which can return stale data.

Code Snippet

The Vault._to_usd_oracle_price() function:

File: Vault.vy
562: def _to_usd_oracle_price(_token: address) -> uint256:
563:     """
564:     @notice
565:         Retrieves the latest Chainlink oracle price for _token.
566:         Ensures that the Arbitrum sequencer is up and running and
567:         that the Chainlink feed is fresh.
568:     """
569:     assert self._sequencer_up(), "sequencer down"
570: 
571:     round_id: uint80 = 0
572:     answer: int256 = 0
573:     started_at: uint256 = 0
574:     updated_at: uint256 = 0
575:     answered_in_round: uint80 = 0
576:     round_id, answer, started_at, updated_at, answered_in_round = ChainlinkOracle(
577:         self.to_usd_oracle[_token]
578:     ).latestRoundData()
579: 
580:     assert (block.timestamp - updated_at) < ORACLE_FRESHNESS_THRESHOLD, "oracle not fresh"
581: 
582:     usd_price: uint256 = convert(answer, uint256)  # 8 dec
583:     return usd_price

Tool used

Manual review

Recommendation

Use the corresponding heartbeat ORACLE_FRESHNESS_THRESHOLD for each token in the Vault._to_usd_oracle_price() function.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Fix SubmittedFix to the issue has been submittedHas DuplicatesA valid issue with 1+ other issues describing the same vulnerabilityMediumA valid Medium severity issueRewardA payout will be made for this issueSponsor ConfirmedThe sponsor acknowledged this issue is validWill FixThe sponsor confirmed this issue will be fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions