Pause and emergency behaviour
Two emergency switches
Picture a bank branch during a power cut. It stops handing out new loans, because it cannot check anything. It still lets you pay back what you owe and take your own belongings home.
Farmenta has two switches that work in that spirit. The guardian, an account the owner names for incidents, can throw either one at once. Turning them back is the owner's alone, and the owner is a timelock contract whose calls run two days after they are scheduled. See the guardian.
- Pausing a market stops every action in that market that adds risk or depends on a price. It is meant for moments when prices cannot be trusted, such as a sequencer outage or an oracle failure.
- Freezing a pool stops new exposure to one pool only. It is how a pool is delisted. Everything that concerns existing loans keeps running, including liquidations.
Neither switch can stop you from repaying, from withdrawing collateral that has no debt, or from withdrawing supplied USDG up to the available cash.
A small example
Budi has a position worth $10,000 and a debt of 7,000 USDG in a pool with an LT of 75%. His health factor is 10,000 × 0.75 / 7,000 = 1.07.
The sequencer has trouble and the guardian pauses the Blue-chip market. While the market is paused, ETH falls and Budi's position is worth $9,000. His health factor is now 9,000 × 0.75 / 7,000 = 0.96.
- Nobody can liquidate Budi while the pause lasts.
- Budi can still repay. If he repays 1,000 USDG, his health factor becomes
9,000 × 0.75 / 6,000 = 1.13. - If he does nothing, he can be liquidated in the first block after the market is unpaused.
What a pause stops
| Stopped while paused | Why |
|---|---|
depositCollateral, depositCollateralWithPermit, mintAndDeposit, and sending a position NFT to the market with safeTransferFrom | New collateral is new risk, accepted at a price that cannot be trusted |
Vault deposit and mint | The market should not take new money during an emergency |
borrow | New debt, sized by a price |
increaseLiquidity, collectFees, decreaseLiquidity | Each one checks the position's health at oracle prices |
liquidate | Seizes collateral at oracle prices |
What always stays open
| Open while paused | Limit |
|---|---|
repay | None. Reduces risk and reads no price. |
withdrawCollateral | Only when the position's debt is zero. Reads no price. |
Vault withdraw and redeem | Limited by the cash in the market, as always. |
Interest keeps accruing during a pause. Debt grows every second whether or not the market is paused.
Why the line is drawn there
When the oracle or the sequencer cannot be trusted, the price used to value a position cannot be trusted either. So no action that depends on a price should run: not borrowing, not removing value from a position with debt, and not liquidating.
Actions that only reduce risk, or that return an asset nobody has a claim on, need no price. Blocking them would protect no one and would turn an emergency switch into a way to trap users' assets. That is why repay, withdrawCollateral and the vault exits have no pause check at all.
This is an accepted risk. Prices can keep falling while the market is paused, and a loan that was only unhealthy when the pause began can be worth less than its debt when the market reopens. That shortfall is bad debt: it is taken from the reserve first and then from the lenders of that market.
A pause has no maximum duration, and each market is paused on its own. The guardian's pause takes effect at once. unpause is the owner's alone and passes through the owner's queue: a call scheduled ahead of time lifts a pause in one transaction, and a call scheduled after the pause began lifts it two days later. Both are public. Paused(account) names who paused, and the timelock's CallScheduled event shows an unpause that is waiting.
Market paused compared with pool frozen
| Function | Market paused | Pool frozen |
|---|---|---|
Vault deposit, mint | Stopped | Open |
Vault withdraw, redeem | Open, limited by cash | Open, limited by cash |
depositCollateral | Stopped | Stopped for that pool |
depositCollateralWithPermit | Stopped | Stopped for that pool |
mintAndDeposit | Stopped | Stopped for that pool |
NFT pushed with safeTransferFrom | Stopped, the transfer reverts | Stopped for that pool, the transfer reverts |
borrow | Stopped | Stopped for positions in that pool |
increaseLiquidity | Stopped | Stopped for that pool |
collectFees | Stopped | Open |
decreaseLiquidity | Stopped | Open |
repay | Open | Open |
withdrawCollateral (debt is zero) | Open | Open |
liquidate | Stopped | Open |
| Interest accrual | Continues | Continues |
TWAP record on the TwapRecorder | Open, it is a separate contract | Open |
A pause covers a whole market. A freeze covers one pool and has no effect on the vault or on other pools. Both can be active at the same time, and then the stricter column applies.
The "Pool frozen" column also describes a pool that is closed for another reason: one of its tokens is disabled, or its hook was taken off the allowlist. The same actions stop and the same actions stay open. The difference is the reach. Disabling a token closes every pool that holds it, and the pool's own frozen flag stays as it was.
A frozen pool is often combined with a falling liquidation threshold. The owner can schedule an LT ramp or lower LT in one step, and liquidations run throughout. Freezing a pool is not a grace period for borrowers.
How to tell which state you are in
| Check | Where |
|---|---|
| Is the market paused? | paused() on the market. The market emits Paused and Unpaused. |
| Does my pool take new collateral and new borrowing? | acceptsNewPositions(poolId) on the CollateralPolicy. |
| Is my pool frozen? | listingOf(poolId) shows the frozen flag. The policy emits PoolFrozen. |
| Is a token of my pool disabled, or its hook off the allowlist? | tokenConfig(currency) and hookAllowlist(hooks). The policy emits TokenConfigured and HookAllowlisted. |
| Is an LT ramp running? | listingOf(poolId) shows the start value, target, start time and duration. effectiveLt(poolId) gives the LT in force now. |
A call that is stopped by a pause reverts with EnforcedPause. A deposit or an addition to a frozen pool reverts with PoolFrozenForNewPositions. In a pool closed by a token or by its hook it reverts with TokenNotEnabled or HookNotPermitted. A borrow reverts with PoolNotOpenForBorrowing in all three cases. See Errors.
What to do
When the market is paused
If you borrow:
- Check your health factor with current market prices, not only the number the contract reports.
- Repay part of your debt if you are close to
HF = 1. Liquidations resume at the moment of unpause, at the prices of that moment. - If you planned to leave, repay in full and call
withdrawCollateral. Both work during a pause. - You cannot add liquidity, remove liquidity or collect fees until the market reopens.
If you lend:
- You can withdraw up to the available cash. New deposits are refused.
- Remember that unhealthy loans are not being liquidated. If prices are falling sharply, the risk of bad debt grows with the length of the pause.
If you liquidate:
liquidatereverts. Watch for theUnpausedevent and re-read each position's liquidation health factor from theMarketLensbefore you act. Several positions may have become liquidatable, some of them deeply.
When your pool is frozen
If you borrow:
- You cannot borrow more, add liquidity, or deposit new positions from that pool.
- You can still repay, collect fees, remove liquidity within the usual limits, and withdraw your NFT once the debt is zero.
- Read the pool's listing. If an LT ramp is scheduled, compute when your position crosses
HF = 1and repay or exit before then.
If you lend: nothing changes for deposits and withdrawals. A freeze usually means the owner wants less exposure to that pool.
If you liquidate: liquidations in the pool run as usual. During a ramp, positions become liquidatable on a known schedule.
Halts that are not a pause
Some outside events stop actions even when the market is not paused:
- A Chainlink price older than 25 hours. Every action that reads that price reverts, including
liquidate.repay,withdrawCollateraland vault withdrawals keep working. - USDG paused by its issuer. Every USDG transfer fails, so
repay,liquidate,borrowand vault deposits and withdrawals revert until the token is unpaused. - A sequencer outage. No transaction can be submitted at all.
These are described in Oracle, market and chain risks.