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
The reward distribution function
RewardTimelock::executeRewardTransaction()may revert while it should not due to the estimated USD price of tokens being out of bounds.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.
Recommended mitigation steps
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?