Uniswap V2 Median
1. Summary
The UniswapConsecutiveSlotsPriceFeedMedianizer
is integrated with Uniswap V2 in order to provide a price feed for one of the tokens in a pool. It is also connected to a converterFeed
in order to get the fiat value of the price quoted by the pool.
2. Contract Variables & Functions
Variables
defaultAmountIn
- default amount oftargetToken
used when calculating thedenominationToken
outputtargetToken
- the token which the contract calculates themedianPrice
fordenominationToken
- pair token fortargetToken
uniswapPair
- the address of the Uniswap V2 pairuniswapFactory
- the address of the Uniswap V2 factoryuniswapObservations[observation: UniswapObservation]
- array of prices taken from the Uniswap pool and the timestamps associated with each of themconverterPriceCumulative
- the snapshot of the latest sum of prices fetched from theconverterFeed
since the contract has been deployedconverterFeed
- address of the contract that offers fiat price feeds for thedenominationToken
converterFeedObservations[observation: ConverterFeedObservation]
- array of fiat price feeds for thedenominationToken
symbol
- the symbol of the price feed offered by the contractgranularity
- how many price observations are stored for thewindowSize.
As granularity increases from 1, more frequent updates are needed, but moving averages become more precise.lastUpdateTime
- when the price feed was last updatedupdates
- total number of updates up until nowwindowSize
- the desired amount of time over which the moving average should be computed, e.g. 24 hoursmaxWindowSize
- max window over which the moving average can be computedperiodSize
- this is redundant withgranularity
andwindowSize
, but stored for gas savings & informational purposes. It is the minimum amount of time that must pass between two updates.converterFeedScalingFactor
- this is the denominator that correctly scales themedianPrice
according to how many decimals thedenominationToken
hasmedianPrice
- the latesttargetToken
median pricevalidityFlag
- flag that indicates whether the median is valid or notrelayer
- address of the contract that rewards others for updating the median
Modifiers
isAuthorized
**** - checks whether an address is part ofauthorizedAddresses
(and thus can call authed functions).
Functions
modifyParameters
- allows governance to modify parameters.timeElapsedSinceFirstObservation() public view returns (uint256)
- returns the time passed since the first observation in the window.earliestObservationIndex() public view returns (uint256)
- returns the index of the earliest observation in the window.getObservationListLength() public view returns (uint256, uint256)
- get the observation list lengthuniswapComputeAmountOut(priceCumulativeStart: uint256
,priceCumulativeEnd: uint256
,timeElapsed: uint256
,amountIn: uint256) public pure returns (amountOut: uint256)
- given the Uniswap V2 cumulative prices of the start and end of a period, and the length of the period, compute the average price in terms of how much amount out is received for the amount in.converterComputeAmountOut(amountIn: uint256) public view returns (amountOut: uint256)
- calculate the price of an amount of tokens using the converter price feed. Used internally after the contract determines the amount of denomination tokens fordefaultAmountIn
target tokens.updateResult(feeReceiver: address)
- update themedianPrice
and pay thefeeReceiver
afterwards.read
- gets a non-zero price or failsgetResultWithValidity
- gets the price and its validity
Events
AddAuthorization
- emitted when a new address becomes authorized. Contains:account
- the new authorized account
RemoveAuthorization
- emitted when an address is de-authorized. Contains:account
- the address that was de-authorized
ModifyParameters
**** - emitted when a parameter is updatedUpdateResult
- emitted whenupdateResult
is called. Contains:medianPrice
- the latest median price fortargetToken
lastUpdateTime
- the current timestamp
FailedConverterFeedUpdate
- emitted when the contract fails to pull a price from theconverterFeed
. Contains:reason
- the failure reason
FailedUniswapPairSync
- emitted when the contract fails to sync the Uniswap V2 pool that it's connected to. Contains:reason
- the reason why the sync failed
3. Walkthrough
updateResult
first tries to update the converterFeed
and the Uniswap pool before it stores new observations and computes the latest median.
read
will only return a result if the median is non-null, if updateResult
has been successfully called at least granularity
times, if the validityFlag
is 1
and if timeElapsedSinceFirstObservation() <= maxWindowSize
. getResultWithValidity
will return the median price and its validity (determined using the same checks as read
).
4. Gotchas
This oracle depends on a pinger call within a defined frequency. THe calls should be properly incentivised.
5. Failure Modes (Bounds on Operating Conditions & External Risk Factors)
Uniswap V2 is vulnerable to oracle manipulation attacks. A motivated attacker could push the price in the wrong direction and update the oracle. For TWAPs that is less of an issue (it would require multiple successful calls from an attacker).