Overview
The Global Configuration manages program-wide settings including the admin address, fee wallet, protocol fees, and global pause state. These instructions are primarily admin-only operations.
Account Structure
pub struct GlobalConfig {
pub admin : Pubkey , // Program administrator
pub fee_wallet : Pubkey , // Protocol fee collection wallet
pub protocol_fees_bps : u16 , // Protocol fees (0-9900 BPS)
pub paused : bool , // Program-wide pause flag
pub pending_new_admin : Option < Pubkey >, // Two-step admin transfer
pub bump : u8 , // PDA bump seed
}
PDA Seeds : ["global_config"]
Instructions
init_global_config
Initialize the program’s global configuration. This is a one-time operation called immediately after deployment.
pub fn init_global_config (
ctx : Context < InitGlobalConfig >,
fee_wallet : Pubkey ,
protocol_fees_bps : u16 ,
) -> Result <()>
Parameters
Parameter Type Description fee_walletPubkeyWallet to receive claimed protocol fees protocol_fees_bpsu16Protocol fee in basis points (0-9900)
Required Accounts
#[derive( Accounts )]
pub struct InitGlobalConfig <' info > {
#[account(
init,
payer = admin,
space = 8 + GlobalConfig :: INIT_SPACE ,
seeds = [ GLOBAL_CONFIG_PREFIX ],
bump ,
)]
pub global_config : Account <' info , GlobalConfig >,
#[account( mut )]
pub admin : Signer <' info >,
pub system_program : Program <' info , System >,
}
Behavior
Creates the GlobalConfig PDA account
Sets caller as admin
Sets program to paused by default
Validates protocol_fees_bps is within range
Access Control
Access : Permissionless (one-time only)
The first caller becomes the admin. Subsequent calls will fail as the account already exists.
Example
await program . methods
. initGlobalConfig (
feeWallet ,
100 // 1% protocol fee (100 BPS)
)
. accounts ({
globalConfig ,
admin: wallet . publicKey ,
systemProgram: SystemProgram . programId ,
})
. rpc ();
update_global_config
Update program-wide configuration settings.
pub fn update_global_config (
ctx : Context < UpdateGlobalConfig >,
fee_wallet : Option < Pubkey >,
paused : Option < bool >,
protocol_fees_bps : Option < u16 >,
) -> Result <()>
Parameters
Parameter Type Description fee_walletOption<Pubkey>New fee wallet (None to keep current) pausedOption<bool>New pause state (None to keep current) protocol_fees_bpsOption<u16>New protocol fee (None to keep current)
Required Accounts
#[derive( Accounts )]
pub struct UpdateGlobalConfig <' info > {
#[account(
mut ,
seeds = [ GLOBAL_CONFIG_PREFIX ],
bump = global_config . bump,
has_one = admin ,
)]
pub global_config : Account <' info , GlobalConfig >,
pub admin : Signer <' info >,
}
Behavior
Updates only the fields provided (non-None values)
Validates protocol_fees_bps if provided
Access Control
Access : Admin only
Example
// Unpause the program and update fees
await program . methods
. updateGlobalConfig (
null , // Keep current fee wallet
false , // Unpause
50 // 0.5% protocol fee (50 BPS)
)
. accounts ({
globalConfig ,
admin: adminWallet . publicKey ,
})
. rpc ();
set_new_admin
Propose a new admin address (first step of two-step transfer).
pub fn set_new_admin (
ctx : Context < SetNewAdmin >,
new_admin : Pubkey ,
) -> Result <()>
Parameters
Parameter Type Description new_adminPubkeyProposed new admin address
Required Accounts
#[derive( Accounts )]
pub struct SetNewAdmin <' info > {
#[account(
mut ,
seeds = [ GLOBAL_CONFIG_PREFIX ],
bump = global_config . bump,
)]
pub global_config : Account <' info , GlobalConfig >,
#[account(
constraint = global_config . admin == admin . key()
@ MultiliquidError :: Unauthorized
)]
pub admin : Signer <' info >,
}
Behavior
Sets pending_new_admin to proposed address
Current admin remains in control
Can be called multiple times to change proposed admin
Access Control
Access : Current admin only
Example
await program . methods
. setNewAdmin ( newAdminPubkey )
. accounts ({
globalConfig ,
admin: currentAdmin . publicKey ,
})
. rpc ();
confirm_new_admin
Accept the admin role (second step of two-step transfer).
pub fn confirm_new_admin (
ctx : Context < ConfirmNewAdmin >,
) -> Result <()>
Required Accounts
#[derive( Accounts )]
pub struct ConfirmNewAdmin <' info > {
#[account(
mut ,
seeds = [ GLOBAL_CONFIG_PREFIX ],
bump = global_config . bump,
)]
pub global_config : Account <' info , GlobalConfig >,
#[account(
constraint = global_config . pending_new_admin == Some (new_admin . key())
@ MultiliquidError :: Unauthorized
)]
pub new_admin : Signer <' info >,
}
Behavior
Verifies caller matches pending_new_admin
Updates admin to new address
Clears pending_new_admin
Access Control
Access : Pending new admin only
Example
await program . methods
. confirmNewAdmin ()
. accounts ({
globalConfig ,
newAdmin: newAdminWallet . publicKey ,
})
. rpc ();
claim_fees
Claim accumulated protocol fees from a fee vault.
pub fn claim_fees (
ctx : Context < ClaimFees >,
fee_wallet : Pubkey ,
) -> Result <()>
Parameters
Parameter Type Description fee_walletPubkeyThe fee wallet address configured in GlobalConfig
Required Accounts
#[derive( Accounts )]
#[instruction(fee_wallet : Pubkey )]
pub struct ClaimFees <' info > {
pub stable_coin_mint_address : InterfaceAccount <' info , Mint >,
#[account(
mut ,
token :: mint = stable_coin_mint_address,
token :: authority = fee_wallet,
token :: token_program = token_program,
)]
pub fee_wallet_token_account : InterfaceAccount <' info , TokenAccount >,
/// CHECK: checked by seeds
#[account(seeds = [ PROGRAM_AUTHORITY_PREFIX ], bump )]
pub program_authority : UncheckedAccount <' info >,
#[account(
mut ,
seeds = [ FEE_VAULT_PREFIX , stable_coin_mint_address . key() . as_ref()],
bump ,
token :: mint = stable_coin_mint_address ,
token :: authority = program_authority ,
token :: token_program = token_program ,
)]
pub fee_token_account : InterfaceAccount <' info , TokenAccount >,
#[account(
seeds = [ GLOBAL_CONFIG_PREFIX ],
bump = global_config . bump,
has_one = fee_wallet ,
)]
pub global_config : Account <' info , GlobalConfig >,
pub token_program : Interface <' info , TokenInterface >,
}
Behavior
Requires program to be unpaused
Transfers all tokens from fee vault to fee wallet
Fee vault remains open for future fee collection
Anyone can call, but fees always go to configured fee_wallet
Access Control
Access : Permissionless
While anyone can trigger fee claims, the fees are always sent to the fee_wallet configured in GlobalConfig, not to the caller.
Example
await program . methods
. claimFees ( feeWallet )
. accounts ({
stableCoinMintAddress: stableMint ,
feeWalletTokenAccount ,
programAuthority ,
feeTokenAccount ,
globalConfig ,
tokenProgram: TOKEN_PROGRAM_ID ,
})
. rpc ();
Error Codes
Error Description UnauthorizedCaller is not admin or pending admin OutOfRangeProtocol fees exceed 9900 BPS ProgramPausedOperation blocked by global pause
Next: Asset Configuration Learn about per-token NAV configuration and asset management