Skip to content

Potential issues with use of Tellor as fallback oracle

Low
bingen published GHSA-5x6p-646h-mmgj Jun 1, 2023

Package

contracts (Solidity)

Affected versions

1.0.0

Patched versions

None

Description

Description

Original reason for use of Tellor as fallback

Tellor was chosen as Liquity’s fallback oracle as it offered a pure ETH-USD price, was built with a level of decentralization baked in from the start, and had a credible path to full decentralization and immutability.

Shortcomings of Liquity<>Tellor integration

The main issue with Liquity’s Tellor usage is that it requires consumption of a delayed price which has been subject to some dispute period. Tellor’s dispute mechanism game theory should ensure that only valid prices survive in the Tellor feed: dishonest prices get swiftly disputed, and valid disputes should earn profits through stake slashing of the dishonest reporter.

However, Liquity was economically designed to consume the most current ETH-USD price. In fact, Liquity originally used Tellor’s most current ETH-USD price with no enforced lag - this exposed Liquity to dishonest Tellor prices, and was fixed by the Tellor team in their Tellor360 update, whereby they implemented a 15 minute lag on the ETH-USD price that Liquity sees [LINK].

Even though Liquity now integrates Tellor correctly - with a lagged price - potential issues may still arise if Liquity does switch to using Tellor’s price data, since Liquity is economically tuned for the most current ETH price.

Impacts

Potential issues if Liquity does fall back to using Tellor

As long as Chainlink is operating correctly and Liquity is consuming Chainlink ETH-USD data, then Liquity functions entirely correctly.

However, if Chainlink fails or freezes and Liquity falls back to Tellor, the system will see a lagged ETH-USD price from Tellor, which leads to some issues:

  1. Potential for creation of undercollateralized troves with CR < 100%
  2. Potential for prevention of resync with Chainlink
  3. Potential value leakage via redemptions

Note: in the case where Chainlink freezes, then Liquity sees a lagged price until the system either switches to Tellor or Chainlink comes back online. So the above issues arise in that interval also.

We define price_delta as the percentage difference between the current market ETH price and the lagged ETH price seen by Liquity, with the current price as denominator.

1) Undercollateralized troves

If the price_delta is positive, ETH is overvalued by the system. If the price_delta is > 9%, then assuming LUSD trades at $1, it is possible to create undercollateralized Troves in a risk-free manner:

  • Deposit <$x worth of ETH
  • Due to the price_delta, the system prices the collateral at at least $1.1x
  • Borrow $x worth of LUSD

The system falsely views this Trove as having a CR of 110%, when in reality it is 100%. The user can instantly sell their LUSD for profit.

The larger the price_delta, the more underwater a Trove could be at creation. This is systemically unhealthy.

If/when the system liquidates this Trove, it may constitute a loss for the recipients (i.e. Stability Pool depositors and/or Troves receiving a redistribution liquidation), since the Trove may be liquidated at <100% CR, based on the true ETH market price.

2) Preventing re-sync with Chainlink

When using Tellor, Liquity will switch back to using Chainlink if both oracles are live and their prices are within 5% of each other.

Let’s assume that Chainlink recovers and resumes serving entirely accurate ETH prices.

When the price_delta is >5%, the Liquity system sees a price that is not close enough to the Chainlink price to trigger the switch back to using Chainlink. In this case, the Liquity system continues using Tellor longer than it should.

3) Value extraction via redemptions

When the price delta is negative, ETH is undervalued by the system. This means that redemptions pay out >$1 worth of ETH per 1 LUSD redeemed.

Normally, it is profitable to redeem LUSD when LUSD_market_price < $(1 - redemption_fee).

However, when the system sees a lagged price, it is profitable to redeem when the LUSD_market_price < $(1 + price_delta - redemption_fee).

Therefore a lagged ETH price below the market ETH price potentially enables value leakage via redemptions.

The effect should however be self-limiting, since redemptions push up the base fee. The value extracted from the system in a given redemption is capped by price_delta - redemption_fee.

The larger the negative price_delta, the greater the value that can be extracted from the system. Larger price deltas are rarer.

How likely are these scenarios?

The likelihood depends on the magnitude and sign of the price_delta.

An analysis of historical price data shows that for a 15 minute lag, ~0.05% of lagged prices would have a large enough delta with the current price to create undercollateralized Troves, and only ~0.4% of lagged prices would have a large enough delta to prevent resyncs with Chainlink if it was live again.

However, even with a relatively short 15 minute lag, up to 22% of lagged prices would have a large enough delta to allow for redemptions that pay out $1.01 worth of ETH per LUSD.

The total extractable value would be rate limited by the dynamic redemption fee, which increases with redemption volumes.

Thus we consider the 15 minute lag acceptable: it gives the system a decent chance of returning to Chainlink if it comes live again, albeit with some potential value leakage to distorted redemptions.

Can someone force Liquity to consume an even older Tellor price?

It is possible, due to Tellor’s dispute mechanism.

When a value is disputed, it is instantly removed from Tellor’s feed. As such, an attacker with some resources could dispute multiple prices, and make the system use a price from further back in time than the minimum 15 minute lag.

The furthest back in time the attacker can go is 4 hours - since beyond that, Liquity considers Tellor frozen and uses the last good price seen.

An attack could be of this form:

  • Dispute multiple prices, making the last good price on Tellor significantly older than 15 minutes, with a price_delta that enables an exploit from 1-3
  • Perform a Liquity transaction that benefits from the price delta: opening a trove, redemption, etc

The further back in time the attacker goes, the greater the likelihood of a large delta between the lagged price and the current price. As per historical price data, the greater the lag, the greater the chance that an exploit of a form 1-3 is possible at a given point in time.

Would Liquity have been better off without a fallback oracle?

Potentially not - though it is debatable. With no fallback, then if Chainlink failed or froze permanently, then the best the system could do is use the last good price seen.

This would still expose the system to potential exploits 1-3, since the frozen price will be above or below the current price, and the delta can increase over time as the real ETH price diverges.

Without a fallback oracle, it would be prudent to wind the system down - e.g. allow only withdrawals and redemptions, no liquidations or new borrowing - to minimize detrimental effects. However, this would be the end of Liquity, and no recovery would be possible even after a temporary Chainlink freeze.

With the fallback oracle, the system has at least some chance of recovery if Chainlink comes back online, even though the system is less stable using the fallback than the primary.

Workarounds

Even if Liquity were to check the timestamp on the Tellor price to verify a small maximum price age, the system could still be griefed via disputes. Liquity would need to either rely on a “last good price seen”, or wind down. Relying on a last good price seen suffers from the same issues 1-3 anyway, since it is by definition a lagged price.

The more frequent the Tellor price reports are, the more prices that need to be disputed for the attacker to make Liquity consume a price which is a given amount of time in the past.

At Liquity launch, the hope was that many other projects would eventually use the Tellor ETH-USD price feed on Ethereum mainnet, and the ecosystem of price reporters would grow to a robust size. In practice this has not panned out - Liquity is only 1 of 2 projects using this Tellor ETH-USD feed, and the price reports are not particularly frequent.

As such, the attack costs associated with Tellor have not grown in tandem with Liquity.

Growth of the reporter-disputer ecosystem would at least increase attack costs for a malicious actor seeking to dispute multiple prices to “go back in time”.

Summary

  • Liquity is considered to be working safely and correctly as long as it is consuming the Chainlink ETH-USD price. If it ever switches to using Tellor, it may experience instability.

  • Liquity only switches to Tellor if Chainlink’s flagship ETH-USD feed fails or freezes, which has never occurred (and if it did, much of DeFi would break - which could in itself adversely affect Liquity, regardless of the oracle it used)

  • If Liquity falls back to using Tellor, the necessary price lag opens the door to some potential value extraction via redemptions and a lesser chance of creation of undercollateralized Troves. Users should be aware that these exploits may be possible if Liquity switches to using Tellor as the fallback.

  • Viability of these exploits depends on short-term ETH price volatility and the maximum price_delta available within a four-hour lookback window.

  • The longer Liquity uses Tellor as primary oracle, the greater the chance of some issue 1-3 occurring.

  • Without frequent price reports, the cost of making Liquity consume a lagged price (up to 4 hours behind the current price) is low.

  • Having Tellor as a fallback is still potentially better than no fallback at all: with no fallback, all the same exploits are possible if Chainlink were to fail, and a fallback oracle gives at least some chance of system recovery

Severity

Low

CVE ID

No known CVE

Weaknesses

No CWEs