🧀Stale Prices

.latestRoundData() does not update the oracle - ExchangeRate.sol

Vulnerability Details

Impact

The function .latestRoundData() employed on an oracle retrieves the most recently updated price. However, it's crucial to understand that this retrieved price isn't necessarily reflective of the asset's current market value. To obtain an accurate and real-time price, it’s imperative to actively query the oracle and then patiently await a callback to complete the request, thereby confirming the data’s receipt and accuracy.

Failure to procure precise, real-time data can lead to immediate and substantial financial losses. Consider a scenario wherein an asset's market price experiences a 5% decline, but the oracle’s data remains stagnant, not reflecting this change. In this instance, a user might deposit funds and inadvertently receive a 5% credit due to the oracle’s outdated data. Once .latestRoundData() is eventually updated (either organically or through user initiation), reflecting the accurate asset price, the user might proceed to withdraw the funds in the original asset form, effectively gaining an unwarranted 5% windfall.

Proof of Concept

The vulnerability is illustrated within the code at the following link: ExchangeRate.sol Code

Recommended Mitigation Steps

To remedy and prevent the outlined financial risks and inaccuracies:

  • Avoid Relying Solely on .latestRoundData(): Refrain from solely depending on the .latestRoundData() for fetching the latest asset prices as this approach doesn't guarantee real-time accuracy.

  • Active Oracle Query: Initiate an active query to the oracle to request updated asset prices.

  • Await Callback Confirmation: After initiating the query, it’s vital to await a callback, which serves as a confirmation that the request is fulfilled, ensuring you receive and work with the most accurate and current price data available.

Implementing these steps ensures that your contract relies on accurate, up-to-date data, effectively safeguarding against potential losses stemming from outdated or inaccurate oracle price feeds.

Vulnerability Details

Impact

A malicious user could exploit stale pricePerShare data to secure risk-free profits at the contract's expense. If the SetPricePerShare event hasn't been triggered recently, and the market has shifted, the contract's pricePerShare might be outdated. An exploitative user can leverage this by executing mint() at the outdated pricePerShare, waiting for the price to update, and then executing burn() at the refreshed rate.

Proof of Concept

The contract's pricePerShare variable is updated via the updatePricePerShare function but is used in mint/burn/transfer functions without verification of its timeliness. This vulnerability is exploitable when the external updatePricePerShare function stalls for any reason.

The risk arises if there's a failure in the system's off-chain script which updates the price, leading to a price stall in the contract. Failures could occur due to internal bugs or external factors like network outages or systemic dependencies.

Recommended Mitigation Steps

The core issue stems from the system design. While wrapping price updates at the contract level minimizes gas costs, it introduces risk if not paired with appropriate safeguard mechanisms. Implement the following to reduce risk:

  1. Introduce a Time Threshold: Add a variable representing the maximum allowable time since the last pricePerShare update.

  2. Create Two Transfer Function Variants: Each should check the condition {now - time since last price update < threshold}. If the condition is met, both variants execute the transfer. If not, the first variant should revert, while the second should trigger a price update.

    • The first variant is a “light” transfer function that operates at low cost but requires recent pricing.

    • The second variant, or “full” transfer function, behaves like the first but also updates pricing when necessary. Although usually operating at low cost, it requires more gas when executing a price update due to stalled pricing.

With these changes, if the scheduled price update fails (due to network conditions, for example), the financial risk is limited to market volatility during the threshold time, effectively capping the potential loss.

Malt Protocol Uses Stale Results From MaltDataLab Which Can Be Abused By Users

Impact Overview

MaltDataLab incorporates multiple MovingAverage contracts to retrieve critical data integral to the functionality of the Malt protocol, including real LP token values, average Malt prices, and average reserve ratios. Data updating functions - trackMaltPrice, trackPoolReserves, and trackPool - are exclusively called by an account with the UPDATER_ROLE, which is an Externally Owned Account (EOA) rather than a contract.

Vulnerability Insight

The continuous and accurate updating of these functions is crucial for providing current values, creating a dependency on the designated EOA to perform regular updates. However, this process is susceptible to miner interference. Miners have the capability to censor calls to MaltDataLab, which could lead to the utilization of outdated values in various protocol areas, creating an opportunity for value extraction.

Proof of Concept

Consider a potential attack scenario:

  1. The Malt price rises above the lower bound threshold, allowing any user to invoke the stabilize function.

  2. The _stabilityWindowOverride function conditions are met, executing the function.

  3. The exchangeRate state variable calls maltPriceAverage but may utilize an outdated exchange rate due to lack of updates.

  4. The _startAuction function activates, rewarding the msg.sender with 100 Malt as an incentive for initiating an auction.

  5. Without subsequent price updates, malicious actors could collaborate with miners to prevent further pool updates and repeatedly call stabilize during every fastAveragePeriod interval, extracting incentive payments in the process.

  6. If these incentive payments surpass the amount the UPDATER_ROLE is willing to expend for calling trackMaltPrice, sustained attacks of this nature become feasible, posing a serious threat to the protocol's stability.

Additional Concerns

The reliance of MaltDataLab on spot price data points for calculating the Moving Average also warrants attention. Well-capitalized malicious actors could potentially manipulate the MovingAverage contract. This could be achieved by strategically placing calls to trackMaltPrice, trackPool, and trackPoolReserves in between other transactions, further compounding the vulnerability.

Last updated