Skip to Content
Program ReferenceOracle & Admin

Oracle & Admin Instructions

UpdateOraclePrice

Discriminator: 0x14 (20)

Read the current aggregate price from a Pyth legacy push-oracle account and cache it in the pool. This instruction is permissionless — anyone can call it to refresh the price.

The first call to UpdateOraclePrice on a pool anchors the Pyth feed address. Subsequent calls with a different feed address return OraclePriceFeedMismatch. Once anchored, the feed cannot be changed without an UpdatePool call from the authority.

Accounts

#NameFlagsDescription
0poolwritableLendingPool to update
1pyth_price_feedreadonlyPyth legacy push-oracle account

Instruction Data

OffsetSizeFieldDescription
01discriminator0x14

No additional data — price, confidence, and expo are read directly from the Pyth account.

Oracle Validation

The program validates these fields from the Pyth price account before writing:

Offset in Pyth accountFieldRequired value
0magic0xa1b2c3d4
8atype3 (Price)
20expoAny i32
208agg.price> 0
216agg.confprice / 50 (max 2% of price)
224agg.status1 (Trading)

The confidence interval check (conf ≤ price / 50) is a critical oracle-manipulation defence. See Oracle Security for details.

Pool Fields Updated

pool.pyth_price_feed ← accounts[1].address() (only on first call) pool.oracle_price ← agg.price pool.oracle_conf ← agg.conf pool.oracle_expo ← expo

USD Value Calculation

// price_usd = oracle_price * 10^oracle_expo const priceUsd = Number(pool.oracle_price) * Math.pow(10, pool.oracle_expo);

Pyth Price Feed IDs (devnet)

AssetFeed ID
SOL/USD0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d
BTC/USD0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43
ETH/USD0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace
XAU/USD0x765d2ba906dbc32ca17cc11f5310a89e9ee1f6420508c63861f2f8ba4ee34bb2

Example

import { updateOraclePriceIx } from './lib/veil/instructions'; const PYTH_SOL_USD = new PublicKey( 'H6ARHf6YXhGYeQfUzQNGk6rDNnLBQKrenN712K4AQJEG' // devnet SOL/USD ); const ix = updateOraclePriceIx(pool, PYTH_SOL_USD); await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer]);

Errors

ErrorCodeCondition
OracleInvalid6024Bad magic, wrong account type, or negative price
OraclePriceStale6025agg.status != 1 (not Trading)
OraclePriceFeedMismatch6026Feed address differs from anchored address
OracleConfTooWide6027agg.conf > price / 50 (> 2% uncertainty)

UpdatePool

Discriminator: 0x0D (13)

Update risk and interest rate parameters for a pool. Requires the pool authority signature.

Accounts

#NameFlagsDescription
0authoritysignerMust match pool.authority
1poolwritable

Instruction Data

OffsetSizeFieldType
01discriminator0x0D
116base_rateu128 LE (WAD-scaled)
1716optimal_utilizationu128 LE (WAD-scaled)
3316slope1u128 LE (WAD-scaled)
4916slope2u128 LE (WAD-scaled)
6516reserve_factoru128 LE (WAD-scaled)
8116ltvu128 LE (WAD-scaled)
9716liquidation_thresholdu128 LE (WAD-scaled)
11316liquidation_bonusu128 LE (WAD-scaled)
12916protocol_liq_feeu128 LE (WAD-scaled)
14516close_factoru128 LE (WAD-scaled)
1618flash_fee_bpsu64 LE

Total: 169 bytes

Validation

  • ltv < liquidation_threshold — LTV must be strictly below the liquidation threshold
  • flash_fee_bps ≤ 10_000 — fee rate must be ≤ 100%

PausePool

Discriminator: 0x0E (14)

Pause a pool, blocking all deposits and borrows. Requires the authority. Liquidations and withdrawals remain available.

Accounts

#NameFlagsDescription
0authoritysigner
1poolwritablepool.paused is set to 1

Instruction Data

OffsetSizeField
01discriminator 0x0E

ResumePool

Discriminator: 0x0F (15)

Clear the pause flag on a pool.

Accounts

#NameFlagsDescription
0authoritysigner
1poolwritablepool.paused is set to 0

Instruction Data

OffsetSizeField
01discriminator 0x0F

CollectFees

Discriminator: 0x10 (16)

Transfer all accumulated protocol fees from the vault to the treasury. The fee balance (pool.accumulated_fees) is zeroed after collection.

Accounts

#NameFlagsDescription
0authoritysignerMust match pool.authority
1poolwritable
2vaultwritableSource
3treasurywritableDestination SPL token account
4pool_authorityreadonlyPDA that signs the vault transfer
5token_programreadonly

Instruction Data

OffsetSizeField
01discriminator 0x10

Errors

  • NoFeesToCollectaccumulated_fees == 0
  • Unauthorized — signer is not the pool authority
Last updated on