29348 - [SC - Insight] Token price returned by PriceConsumer may be in...

Submitted on Mar 14th 2024 at 19:19:29 UTC by @greed for Boost | Immunefi Arbitration

Report ID: #29348

Report type: Smart Contract

Report severity: Insight

Target: https://github.com/immunefi-team/vaults/blob/main/src/RewardTimelock.sol

Impacts:

  • Contract fails to deliver promised returns, but doesn't lose value

Description

Impact

Considering its likelihood the issue is marked as LOW

  1. The reward distribution function RewardTimelock::executeRewardTransaction() may revert while it should not due to the estimated USD price of tokens being out of bounds.

  2. The protocol may send more or less rewards in USD than the promised payout to the whitehat. This will either result in a loss for the protocol and a win for the researcher or a win for the protocol and a loss for the researcher.

Vulnerability details

When the reward transaction is fired through RewardTimelock::executeRewardTransaction(), the price of the tokens being sent to the whitehat is calculated in _checkRewardDollarValue() and relies on PriceConsumer::tryGetSaneUsdPrice18Decimals().

This function uses different feed to calculate the price of an asset depending on if it has been configured or not.

Under certain circumstances, a feed can return an outdated price which in period of high volatility (where a pump or dump can happen in a matter of minutes) can be a critical issue.

In order to get a price that is as accurate as possible, PriceConsumer::tryGetSaneUsdPrice18Decimals() has the following check

https://github.com/immunefi-team/vaults/blob/main/src/oracles/PriceConsumer.sol#L54

The function _getFeedTimeout(base) can return 1 days if the corresponding customFeedTimeout[base] has not been configured.

The check basically accepts a price that is at worse 1 days old.

Lower the value of FEED_TIMEOUT to make the transaction revert in case the price may not be accurate enough

Proof of Concept

In order to test the execution reverts when it should not case, the following script (based on testQueuesAndExecutesRewardTx()) can be added in test/foundry/RewardTimelock.t.sol

The comments describe the events that occur during the lifecycle of the payout


In order to test the win or loss of rewards case, the following script (based on testQueuesAndExecutesRewardTx()) can be added in test/foundry/RewardTimelock.t.sol

The comments describe the events that occur during the lifecycle of the payout

Last updated

Was this helpful?