Documentation Index Fetch the complete documentation index at: https://docs.multiliquid.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Asset Configuration accounts store the NAV (Net Asset Value) pricing sources and settings for each token in the protocol. Every RWA and stablecoin must have an AssetConfig account before it can be used in trading pairs.
Account Structure
pub struct AssetConfig {
pub mint_address : Pubkey , // Token mint address
pub nav_data : Vec < NavData >, // Up to 5 NAV pricing sources
pub price_difference_bps : u16 , // Maximum price divergence tolerance
pub paused : bool , // Asset-level pause flag
pub version : u8 , // Configuration version
pub asset_type : AssetType , // Rwa or Stable
pub used_in_pairs_count : u16 , // Number of pairs using this asset
pub bump : u8 , // PDA bump seed
}
PDA Seeds : ["asset", mint_address]
Asset Type
pub enum AssetType {
Rwa , // Real World Asset token
Stable , // Stablecoin token
}
Instructions
init_asset_config_account
Register a new token for use in the protocol.
pub fn init_asset_config_account (
ctx : Context < InitAssetConfigAccount >,
nav_data : Vec < NavData >,
price_difference_bps : u16 ,
asset_type : AssetType ,
) -> Result <()>
Parameters
Parameter Type Description nav_dataVec<NavData>1-5 NAV pricing sources price_difference_bpsu16Maximum allowed price divergence (0-9900 BPS) asset_typeAssetTypeWhether token is RWA or Stablecoin
Required Accounts
#[derive( Accounts )]
pub struct InitAssetConfigAccount <' info > {
#[account(
init,
payer = admin,
space = 8 + AssetConfig :: INIT_SPACE ,
seeds = [ ASSET_CONFIG_PREFIX , mint_address . key() . as_ref()],
bump ,
)]
pub asset_config : Account <' info , AssetConfig >,
pub mint_address : InterfaceAccount <' info , Mint >,
#[account( mut )]
pub admin : Signer <' info >,
// Fee vault ATA owned by the global program authority
#[account(
init_if_needed,
payer = admin,
associated_token :: mint = mint_address,
associated_token :: authority = program_authority,
associated_token :: token_program = token_program,
)]
pub fee_vault_token_account : InterfaceAccount <' info , TokenAccount >,
/// CHECK: Global PDA used as the protocol fee-vault authority
#[account(
seeds = [ PROGRAM_AUTHORITY_PREFIX ],
bump ,
)]
pub program_authority : UncheckedAccount <' info >,
#[account(
seeds = [ GLOBAL_CONFIG_PREFIX ],
bump = global_config . bump,
has_one = admin
)]
pub global_config : Account <' info , GlobalConfig >,
pub system_program : Program <' info , System >,
pub token_program : Interface <' info , TokenInterface >,
pub associated_token_program : Program <' info , AssociatedToken >,
}
Behavior
Creates AssetConfig PDA for the token mint
Creates the fee-vault ATA owned by program_authority for fee collection
Validates NAV data (1-5 sources, decimals ≤ 9) and price_difference_bps <= 9900
Sets paused to false by default
Sets used_in_pairs_count to 0
Access Control
Access : Admin only
Example
import { BN } from "@coral-xyz/anchor" ;
// NAV source: Read price from a fixed account address
const navData = [{
u64FixedAddress: {
navAccountAddress: priceOracleAccount ,
navPriceOffset: 0 ,
priceDecimals: 6 ,
}
}];
await program . methods
. initAssetConfigAccount (
navData ,
100 , // 1% max price divergence
{ rwa: {} } // Asset type
)
. accounts ({
assetConfig ,
mintAddress: rwaMint ,
admin: adminWallet . publicKey ,
feeVaultTokenAccount ,
programAuthority ,
globalConfig ,
systemProgram: SystemProgram . programId ,
tokenProgram: TOKEN_PROGRAM_ID ,
associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID ,
})
. rpc ();
update_asset_config_account
Update NAV sources for an existing asset.
pub fn update_asset_config_account (
ctx : Context < UpdateAssetConfigAccount >,
nav_data : Vec < NavData >,
price_difference_bps : u16 ,
asset_type : AssetType ,
) -> Result <()>
Parameters
Parameter Type Description nav_dataVec<NavData>Updated NAV pricing sources (1-5) price_difference_bpsu16Updated price divergence tolerance (0-9900 BPS) asset_typeAssetTypeNew asset type (change blocked if asset is in use)
Required Accounts
#[derive( Accounts )]
pub struct UpdateAssetConfigAccount <' info > {
#[account(
mut ,
seeds = [ ASSET_CONFIG_PREFIX , mint_address . key() . as_ref()],
bump = asset_config . bump,
)]
pub asset_config : Account <' info , AssetConfig >,
pub mint_address : InterfaceAccount <' info , Mint >,
pub admin : Signer <' info >,
#[account(
seeds = [ GLOBAL_CONFIG_PREFIX ],
bump = global_config . bump,
has_one = admin
)]
pub global_config : Account <' info , GlobalConfig >,
}
Behavior
Updates NAV sources and price divergence threshold after validating price_difference_bps <= 9900
Can update asset_type, but change is blocked if used_in_pairs_count > 0
Does not affect pause state or usage count
Access Control
Access : Admin only
Example
// Add a second NAV source (Pyth oracle)
const updatedNavData = [
{
u64FixedAddress: {
navAccountAddress: primaryOracle ,
navPriceOffset: 0 ,
priceDecimals: 6 ,
}
},
{
pythPush: {
pythPushAccountAddress: pythAccount ,
feedId: Array . from ( Buffer . from ( "40ac3329933a6b5b65cf31496018c5764ac0567316146f7d0de00095886b480d" , "hex" )),
maxAgeSecs: new BN ( 86_400 ),
maxConfBps: 100 ,
}
}
];
await program . methods
. updateAssetConfigAccount (
updatedNavData ,
50 , // 0.5% max divergence
{ rwa: {} } // Asset type
)
. accounts ({
assetConfig ,
admin: adminWallet . publicKey ,
mintAddress: rwaMint ,
globalConfig ,
})
. rpc ();
set_paused_for_asset
Set the pause state for a specific asset.
pub fn set_paused_for_asset (
ctx : Context < SetPausedForAsset >,
paused : bool ,
) -> Result <()>
Parameters
Parameter Type Description pausedboolNew pause state
Required Accounts
#[derive( Accounts )]
pub struct SetPausedForAsset <' info > {
#[account(
seeds = [ GLOBAL_CONFIG_PREFIX ],
bump = global_config . bump,
has_one = admin ,
)]
pub global_config : Account <' info , GlobalConfig >,
#[account(
mut ,
seeds = [ ASSET_CONFIG_PREFIX , mint_address . key() . as_ref()],
bump = asset_config . bump,
)]
pub asset_config : Account <' info , AssetConfig >,
pub mint_address : UncheckedAccount <' info >,
#[account( mut )]
pub admin : Signer <' info >,
}
Behavior
Updates asset’s pause state
When paused, all swaps involving this asset are blocked
Does not affect other assets or global state
Access Control
Access : Admin only
Example
// Pause an asset
await program . methods
. setPausedForAsset ( true )
. accounts ({
globalConfig ,
assetConfig ,
mintAddress: rwaMint ,
admin: adminWallet . publicKey ,
})
. rpc ();
NAV Data Types
The program supports three types of NAV pricing sources:
U64FixedAddress
Read price from a fixed byte offset in an on-chain account.
NavData :: U64FixedAddress {
nav_account_address : Pubkey , // Account containing price data
nav_price_offset : u16 , // Byte offset to read price
price_decimals : u8 , // Decimal places (0-9)
}
Use Cases :
Custom price oracle accounts
RWA issuer-published NAV accounts
Any account with a u64 price at known offset
Hardcoded
Static price value for stable-value assets.
NavData :: Hardcoded {
hardcoded_price : u64 , // Fixed price value
price_decimals : u8 , // Decimal places (0-9)
}
Use Cases :
Dollar-pegged stablecoins (price = 1.0)
Assets with contractually fixed prices
Testing and development
PythPush
Pyth Network oracle integration.
NavData :: PythPush {
pyth_push_account_address : Pubkey , // Pyth receiver price update account
feed_id : [ u8 ; 32 ], // Expected Pyth feed id
max_age_secs : u64 , // Maximum accepted price age
max_conf_bps : u16 , // Maximum accepted confidence ratio
}
Use Cases :
Market-priced assets
Assets with Pyth price feeds
High-frequency price updates
View Price Source Details Complete documentation on NAV pricing configuration and validation
Price Aggregation
When multiple NAV sources are configured:
Read All Sources : Each source returns a price
Normalize : All prices converted to 9 decimal places
Validate Divergence : Check all prices within price_difference_bps
Average : Return average of all valid prices
If any source diverges beyond threshold, the function returns 0, blocking swaps.
Error Codes
Error Description UnauthorizedCaller is not admin MustProvideAtLeastOneNavDataNo NAV sources provided Max5NavDataMore than 5 NAV sources PriceDecimalsTooLargeDecimals exceed 9 MustProvideHardcodedPriceHardcoded price is zero NavMustBePositiveNAV source returned a non-positive price InvalidAccountPublicKeyRequired NAV source account was not passed InvalidFeedId / InvalidMaxAge / MaxAgeTooLarge / ConfBpsTooLargePyth configuration failed scalar validation MissingPythAccount / FeedIdMismatchPyth receiver account was missing or did not match the configured feed OutOfRangeprice_difference_bps exceeds 9900
Next: Pair Management Learn about trading pair creation and configuration