Skip to main content
The Open Nile Protocol operates in one of four modes at any given time, with increasing levels of restriction. The mode system allows the protocol to gracefully degrade functionality in response to oracle issues, market stress, or administrative actions, rather than failing abruptly.
Mode transitions are managed by the ModeController contract. In the M2 (External Testnet) deployment, mode changes are controlled by admin roles. M3 plans include multi-sig governance for mode transitions and automated escalation based on additional risk metrics.

Operating Modes

The four modes form an escalation path from normal operations to full pause:

NORMAL (0)

All operations available. This is the default operating state. Traders can open, close, increase, and reduce positions. LPs can deposit and withdraw. Settlements and liquidations proceed normally.

DEGRADED (1)

Restricted operations. New position opens and increases are blocked. Closes, reductions, margin adjustments, settlements, and liquidations continue. Entered when oracle degradation is detected.

REDUCE_ONLY (2)

Wind-down mode. Same restrictions as DEGRADED — no new positions or increases. Designed for administrative wind-down scenarios where the protocol needs to reduce exposure without full pause.

PAUSED (3)

All operations suspended. No trading, no settlements, no liquidations, no deposits, no withdrawals. This is the emergency mode for severe oracle failures or critical incidents.

Operation Restriction Matrix

Each mode progressively restricts available operations:
OperationNORMALDEGRADEDREDUCE_ONLYPAUSED
openPositionYesNoNoNo
increasePositionYesNoNoNo
closePositionYesYesYesNo
reducePositionYesYesYesNo
addPositionMarginYesYesYesNo
removePositionMarginYesYesYesNo
settleMaturedYesYesYesNo
liquidateYesYesYesNo
Vault depositYesYesYesNo
Vault withdrawYesYesYesNo
In PAUSED mode, all operations are suspended including liquidations and settlements. This means positions that should be liquidated will not be processed until the protocol exits PAUSED mode. The pause is intended to be temporary while the root cause is investigated.

State Transition Diagram

                setReduceOnly(true)
    NORMAL <────────────────────────> REDUCE_ONLY
      |  ^                             |  ^
      |  | exitDegradedMode()          |  |
      |  |                             |  |
      v  |   setDegraded()             v  | setDegraded()
      DEGRADED ────────────────────────/
      |
      | enterPausedMode()
      | or DEGRADED_TIMEOUT
      v
                    PAUSED  <── enterPausedMode() from NORMAL or REDUCE_ONLY
                      |
                      | exitPausedMode(target)
                      v
              NORMAL or REDUCE_ONLY

Transition Functions

TransitionFunctionRequired Role
Any (except PAUSED) to PAUSEDenterPausedMode(reasonCode)PAUSER_ROLE
PAUSED to NORMAL or REDUCE_ONLYexitPausedMode(target, reasonCode)PAUSER_ROLE
The PAUSER_ROLE can enter pause from any non-paused mode. This is the emergency brake. When exiting pause, the operator specifies the target mode (either NORMAL or REDUCE_ONLY). The protocol cannot exit pause directly into DEGRADED mode.

Auto-Escalation

The checkOracleAndPause() function implements automated mode transitions based on oracle health. It is designed to be called periodically by the keeper service or by any holder of PAUSER_ROLE.
1

Check Oracle Validity

The function calls oracleModule.isOracleValid() via staticcall to determine if the oracle is providing fresh, valid forward prices.
2

Oracle Invalid Path

If the oracle is invalid (stale forward prices, disabled pair, or no forward ever published):
  • From NORMAL or DEGRADED: escalate to PAUSED with reason ORACLE_INVALID
  • From REDUCE_ONLY: escalate to PAUSED with reason ORACLE_INVALID
  • Already PAUSED: no change
3

Oracle Valid + DEGRADED Path

If the oracle is valid and the current mode is DEGRADED, two sub-checks occur:
  1. Duration check: If degradedEnteredAt + degradedDurationSeconds <= block.timestamp, the degraded state has lasted too long. Escalate to PAUSED with reason DEGRADED_TIMEOUT.
  2. Recovery: If the duration has not been exceeded, recover to NORMAL with reason ORACLE_RECOVERED.
4

Return Value

The function returns true if the oracle is valid, false otherwise. This allows callers to take additional action based on the oracle state.

Reason Codes

Every mode transition includes a reason code for auditability and monitoring. Reason codes are bytes32 values computed as keccak256 hashes:
Reason CodeValueTrigger
REASON_ADMINkeccak256("ADMIN")Manual admin action (pause, unpause, mode change)
REASON_ORACLE_INVALIDkeccak256("ORACLE_INVALID")Oracle staleness detected by checkOracleAndPause()
REASON_ORACLE_DEGRADEDkeccak256("ORACLE_DEGRADED")Oracle price deviation above degradedThresholdBps
REASON_ORACLE_RECOVEREDkeccak256("ORACLE_RECOVERED")Oracle recovered from degraded state
REASON_DEGRADED_TIMEOUTkeccak256("DEGRADED_TIMEOUT")Degraded mode duration exceeded without recovery
Mode transitions emit a ModeTransition event with the old mode, new mode, and reason code. These events are indexed by the subgraph and available in the ModeTransition entity, allowing historical analysis of all mode changes.

Degraded Mode Configuration

DEGRADED mode has its own configuration parameters that control how the protocol behaves when oracle quality is reduced:
DegradedConfig {
    degradedThresholdBps: 500      // 5% price deviation threshold
    degradedDurationSeconds: 3600  // 1 hour max before auto-escalation
    autoDegradeOnDeviation: true   // Enabled in M2
}
ParameterDefaultDescription
degradedThresholdBps500 (5%)Price deviation threshold to trigger degraded mode
degradedDurationSeconds3,600 (1 hour)Maximum time in degraded mode before auto-escalation to PAUSED
autoDegradeOnDeviationtrueWhether to automatically enter degraded mode on price deviation
DEGRADED mode is a temporary state designed for transient oracle issues. If the oracle cannot recover within one hour, the issue is likely more serious than a temporary glitch. The 1-hour timeout ensures that a “stuck” degraded state does not persist indefinitely with reduced risk protection. The auto-escalation to PAUSED forces human intervention to investigate and resolve the root cause.
Open positions remain active. Traders can close positions, reduce exposure, and adjust margin. Settlements and liquidations continue normally. The key restriction is that no new positions can be opened and no existing positions can be increased. This prevents traders from taking on new exposure with potentially degraded oracle quality.
Both modes block new position opens and increases. The primary difference is the trigger and intent:
  • DEGRADED is triggered by oracle quality issues and has an automatic timeout that escalates to PAUSED. It includes a degradedEnteredAt timestamp for duration tracking.
  • REDUCE_ONLY is an administrative decision (e.g., planned wind-down, risk parameter change) with no automatic timeout. It persists until explicitly toggled back to NORMAL.
DEGRADED mode is automatic and temporary; REDUCE_ONLY is manual and persistent.
Yes. The enterPausedMode() function can be called from any non-paused mode, including NORMAL. This is the emergency brake for critical situations that require immediate halting of all operations. Additionally, checkOracleAndPause() can escalate directly from NORMAL to PAUSED if the oracle becomes invalid.

Escalation Scenarios

  1. Publisher stops sending forward price updates
  2. Forward price becomes stale after 60 seconds (maxForwardAge)
  3. isOracleValid() returns false
  4. checkOracleAndPause() escalates to PAUSED with ORACLE_INVALID
  5. Admin investigates, restarts publisher
  6. Publisher resumes updates, prices become fresh
  7. Admin calls exitPausedMode(NORMAL, REASON_ADMIN) to resume operations

M2 vs M3 Governance

In the current M2 deployment, mode transitions are controlled by EOA (Externally Owned Account) addresses assigned the PAUSER_ROLE and DEFAULT_ADMIN_ROLE. This provides fast response times but relies on trust in the protocol operators.For M3 (Mainnet Ready), the plan includes:
  • Multi-sig governance for admin mode transitions (timelock + multi-sig)
  • Automated oracle monitoring with onchain health metrics
  • Decentralized keeper network for checkOracleAndPause() calls
  • Graduated pause powers with different timelocks for different severity levels
These changes will decentralize mode control while maintaining the ability to respond quickly to emergencies.