All posts

ORACLE

When the oracle cannot see

Corpus trusts a price for 80 hours. After that it refuses to borrow, to let you withdraw against debt, or to liquidate anyone — while deposits, repayments and harvests keep working. Why the line is drawn there.

5 min read5 sections
On this page

A lending protocol is a machine for turning a price into a permission. Take away the price and you have to decide what the machine does. Most of Corpus's staleness policy follows from one rule, which we will state up front:

Anything that can only make a position safer is never blocked. Anything that needs a valuation stops until there is one.

Everything below is that rule applied.

Eighty hours

Corpus reads Chainlink feeds and accepts a price as fresh for 80 hours — 288,000 seconds — after the aggregator's last update. Past that, the price is stale for that market.

Eighty hours is a long time for a crypto protocol and a short time for an equity. These feeds track assets that trade on a schedule: they update through the trading week and go quiet at every close, every weekend and every market holiday. A window of a few minutes, sensible for a perpetually traded asset, would put every market into permanent refusal overnight.

So the window has to clear an ordinary weekend, which is about 65.5 hours from a Friday close to a Monday open. Eighty hours clears it with roughly fifteen hours to spare. It does not clear a three-day holiday weekend, which runs about 89.5 hours. That is not an oversight — see What happens on weekends.

What stops

Operation With a stale price
Deposit collateral Allowed
Repay, or repay for someone else Allowed
Harvest Allowed
Claim credit Allowed
Fund the treasury Allowed
Withdraw collateral with no debt Allowed
Borrow Blocked
Withdraw collateral while you have debt Blocked
Liquidate Blocked

Borrowing stops, obviously

Borrowing means asking the protocol to value your collateral and hand you money against it. With a stale feed, the protocol does not know what the collateral is worth. A price that is 81 hours old is a fact about the past, and lending against it is how a protocol ends up holding collateral worth less than the loan it wrote.

Withdrawing with debt stops, less obviously

Taking collateral out of a position that owes money is the same question in reverse: will what remains still cover the debt? That also needs a valuation. Withdrawing without debt is different — no valuation is needed to conclude that an unencumbered deposit belongs to its owner — so that stays open.

If you have debt and want your collateral out during a stale period, repay first. Repayment is never blocked. Once the debt is zero, the withdrawal needs no price at all.

Liquidation stops, and this one is a choice

This is the part people ask about. If a position is unhealthy, why not let it be liquidated on the last known price?

Because the last known price does not demonstrate that the position is unhealthy. It demonstrates that it was, at some point up to several days ago. Seizing collateral is the most damaging thing the protocol can do to a user, and permitting it on evidence the protocol has itself declared unreliable is not a trade we are willing to make. A wrong liquidation cannot be undone; a late liquidation can.

The cost is real and we will not dress it up: a position that goes bad while the feed is dark is liquidated later than it should be, at whatever price exists when the feed resumes. If the move was large enough, the collateral may by then be worth less than the debt. That residual is a loss to the treasury, and the treasury is the common pool everyone borrows from. We are deliberately absorbing protocol risk in order not to seize user collateral on unreliable data.

Note that this cuts both ways in a stale period: the borrower cannot borrow more against a stale price either. Neither side gets to act on it.

Deposits, repayments and harvests never stop

Adding collateral raises your health factor. Repaying raises it. Harvesting can only lower your debt. None of these can be used to extract value from the protocol at a bad price, and all of them are the actions of somebody trying to save a position. A protocol that blocks them at the exact moment they are most needed is badly built.

Harvest is an interesting case, because a harvest values yield at the oracle price in order to bound the swap. Today the question is academic — every market uses a 1:1 custody vault, the surplus is zero, and a harvest returns zero whether the price is fresh or not. When there is a surplus to sell, a harvest with a stale price is still permitted: the worst it can do is convert yield at a price bound that has drifted, and the outcome can only reduce somebody's debt. Blocking it would leave value stranded for no benefit.

This runs deeper than the staleness rule. Repayment is also permitted while a market is closed, and while the protocol is paused. There is no state in which Corpus prevents you from paying off your debt.

What else the oracle refuses

Staleness is only one failure mode. The oracle adapter also rejects an answer that is zero or negative, and a round that has not completed. It can be given a per-asset ceiling that rejects any price above it, though no ceilings are configured at launch. When any of these checks fail, the price is treated exactly as stale: the same operations stop, the same ones continue.

What the oracle cannot do is recognise a feed that is fresh, well formed and simply wrong. There is one feed per asset and no second opinion. If a feed publishes a materially incorrect price, Corpus will act on it: a healthy position could be liquidated, or an unhealthy one could borrow. That risk is on the risk page and it is not small.

What you see in the app

Each market carries a Stale badge when its price is outside the window, and the market page shows how long ago the feed last updated. Buttons that the contract would reject are disabled with the reason spelled out, because a transaction that fails on chain costs you gas to learn something the interface already knew.

If the app shows a market as fresh and the transaction reverts as stale, trust the chain: the app reads it a few seconds behind.

The summary

Eighty hours of trust, then the protocol stops pretending. It will not lend, it will not release encumbered collateral, and it will not let anyone seize yours. It will always take your repayment. That is the whole policy.