Lendlexyz

Lendlexyz reused its last good Pyth price when the historical feed rejected a response

Lendlexyz used a stored last good price when its historical PythPriceFeed rejected the Pyth response. That covered failed or invalid responses and prices older than the adapter's configured timeout. The age check used the Pyth publication timestamp, so reading a price again did not make it newer. This behavior belonged to the Mantle lending market known as Lendle, whose shutdown notice asked users to close positions and remove liquidity.

Updated -

Both price paths supplied a price for valuation

Whether the adapter accepted a Pyth response or used retained data, its output supplied an asset-price input. The difference concerned the origin and age of that input. An accepted response passed the adapter's checks; a fallback value came from storage after those checks failed. Its market relevance still depended on the observation's age and subsequent price movement. This behavior concerned the Mantle Mainnet contracts covered by SourceHat's Lendle Smart Contract Audit Report. The report was dated September 8, 2023, and updated September 25, 2023, to reflect the mainnet deployment.


Response validity and publication age controlled the fallback

The historical PythPriceFeed returned its stored last good price when its Pyth response failed the applicable checks.

A response had to pass validity checks

The broken-response check covered a failed call, a zero or future timestamp, and a non-positive price.

A valid response also had to be timely

A successful call could still supply an observation that exceeded the timeout.

The publication timestamp supplied the starting point

The adapter calculated response age by subtracting Pyth's publishTime from the block timestamp.

The cutoff belonged to the adapter instance

TIMEOUT was an immutable constructor input for that adapter instance. Its duration was specific to that deployment.


Asset-source changes and pool-oracle changes had different scope

AaveOracle read the price reported by an asset's configured source. The historical AaveOracle owner could change the configured source for an individual asset. The retained-price rule therefore followed a particular source implementation. Applying it to a reserve required that reserve's configured pricing path to use the adapter. Another source could have different behavior.

Graphic: Lendlexyz: Asset-source changes and pool-oracle changes had different scope

Open full-size image

Changing the pool's overall price oracle required a separate privileged update through LendingPoolAddressesProvider. That change concerned the oracle used for LendingPool price calculations, whereas an asset-source setting concerned a particular asset. Those permissions allowed the pricing path to change independently of the adapter's fallback logic.

Quote age affected collateral and debt valuations

A price expressed per unit of an asset converted its quantity into a value in the quote's denomination. Keeping both quantity and quote unchanged kept that calculated value unchanged. A later market price could have produced a higher or lower valuation. The difference depended on the quantity and the price movement. A retained collateral quote could overstate value after a market-price fall, or understate it after a rise, without any change in the deposited quantity.

The lending pool also valued debt and applied configured liquidation thresholds. An unchanged collateral quote could coexist with changing debt values or liquidation settings. The affected price could have belonged to an asset on either side of the position, depending on the reserve's source configuration. Those distinctions mattered when interpreting borrowing capacity and liquidation exposure. A price fallback supplied one input; the position calculation still needed the relevant balances and pool settings.

The same quoted number could represent different feed states

If an accepted Pyth response and the saved fallback showed the same number, their feed states still differed. The number alone could not show whether the adapter accepted a response or returned a retained value. Compare the conditions attached to each quote:

The shutdown notice concerned positions and liquidity

Lendle's shutdown notice asked users to close positions and remove liquidity. Its earlier fallback behavior described price selection, while pool controls also governed transaction availability. The historical Emergency Admin could pause pool transactions. A retained quote could therefore explain a historical valuation without showing that a lending operation remained available during the wind-down.

What to know about Lendlexyz

Did reading the historical PythPriceFeed also update lastGoodPrice?

The historical fetchPrice function read a result without writing lastGoodPrice. The separate updatePrice function stored the returned price and updated status when necessary. Reading a computed price and updating the saved fallback were distinct operations in this implementation.

Was a response exactly at TIMEOUT already frozen?

The historical runtime check classified a response as frozen only when its age exceeded TIMEOUT. Equality alone did not trigger that age test, although the other response-validity checks still applied.

Could a stable borrowing rate keep an affected collateral quote current?

A stable borrowing rate did not refresh an oracle quote. The historical stable-rate model concerned borrowing interest, while PythPriceFeed supplied an asset-price input. Choosing that rate mode did not remove the feed's response-validity or age conditions, or turn its stored fallback into a newer market observation.

Did returning a fallback quote suspend interest on historical loans?

Returning a fallback quote did not suspend borrowing interest. Interest continued adding to the historical loan obligation as time passed, so debt could change while a quoted price remained unchanged. Oracle pricing and interest accrual supplied separate inputs to the position's valuation.

Was the saved oracle price a guaranteed sale price for withdrawn assets?

The saved oracle price did not guarantee sale proceeds. Historical lending withdrawals burned the corresponding aTokens and returned underlying assets. Receiving those assets differed from selling them at an oracle quote, so a fallback valuation did not fix the proceeds of a separate sale.

How did the September 2023 audit classify oracle issues?

SourceHat marked the Oracle Issues category as PASS in its September 2023 audit of the reviewed Mantle Mainnet contracts. The report also carried a centralization warning for privileged controls. That result concerned the reviewed deployment; it did not certify the freshness of each price returned afterward.