This repository has been archived by the owner on Jan 7, 2024. It is now read-only.
0x52 - Funding settlement will be DOS'd for a time after the phaseID change of an underlying chainlink aggregator #177
Labels
Medium
A valid Medium severity issue
Reward
A payout will be made for this issue
Sponsor Confirmed
The sponsor acknowledged this issue is valid
Won't Fix
The sponsor confirmed this issue will not be fixed
0x52
medium
Funding settlement will be DOS'd for a time after the phaseID change of an underlying chainlink aggregator
Summary
Oracle incorrectly assumes that roundID is always incremented by one but this is not the case. Chainlink's roundID is actually two values packed together: phaseId and aggregatorRoundId. When the phaseID is incremented the roundID increases by 2 ** 64. After a phaseID increment all calls to settle funding will revert until an entire funding interval has elapsed. Since all markets are settled simultaneously, even a single oracle incrementing will result in all market funding being DOS'd. Although this funding can be made up later it will user different TWAP values which will result in users being paid differently causing loss of yield to a portion of all users.
Vulnerability Detail
https://snowtrace.io/address/0x976b3d034e162d8bd72d6b9c989d545b839003b0#code#L206
The above code is from the ETH/USD aggregator on AVAX, It can be seen that the roundId is made up of 2 packed components, the phaseId and aggregatorRoundId. As explained in the summary, when the phaseId is incremented 2 ** 64 "rounds" will be skipped. When
currentRound - 1
is inevitably queried after this increment, the call will revert because that round doesn't exist this DOS will last for up to 24 hours depending on market settings. After the DOS ends, settingFunding will be able to catch up but it will now calculate the funding rate with different TWAP values.Impact
Loss of yield to a portion of all users in every market each time there is a phaseId shift
Code Snippet
Tool used
Manual Review
Recommendation
I would recommend using a try block when calling the aggregator. If the roundID is nonzero and is reverting then the oracle needs try again with a lower phaseId
The text was updated successfully, but these errors were encountered: