> ## 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.

# Global Configuration

> Program-wide configuration management for admin, fees, and pause control

## 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

```rust theme={null}
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.

```rust theme={null}
pub fn init_global_config(
    ctx: Context<InitGlobalConfig>,
    fee_wallet: Pubkey,
    protocol_fees_bps: u16,
) -> Result<()>
```

#### Parameters

| Parameter           | Type     | Description                             |
| ------------------- | -------- | --------------------------------------- |
| `fee_wallet`        | `Pubkey` | Wallet to receive claimed protocol fees |
| `protocol_fees_bps` | `u16`    | Protocol fee in basis points (0-9900)   |

#### Required Accounts

```rust theme={null}
#[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

```typescript theme={null}
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.

```rust theme={null}
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_wallet`        | `Option<Pubkey>` | New fee wallet (None to keep current)   |
| `paused`            | `Option<bool>`   | New pause state (None to keep current)  |
| `protocol_fees_bps` | `Option<u16>`    | New protocol fee (None to keep current) |

#### Required Accounts

```rust theme={null}
#[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

```typescript theme={null}
// 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).

```rust theme={null}
pub fn set_new_admin(
    ctx: Context<SetNewAdmin>,
    new_admin: Pubkey,
) -> Result<()>
```

#### Parameters

| Parameter   | Type     | Description                |
| ----------- | -------- | -------------------------- |
| `new_admin` | `Pubkey` | Proposed new admin address |

#### Required Accounts

```rust theme={null}
#[derive(Accounts)]
pub struct SetNewAdmin<'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

* 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

```typescript theme={null}
await program.methods
  .setNewAdmin(newAdminPubkey)
  .accounts({
    globalConfig,
    admin: currentAdmin.publicKey,
  })
  .rpc();
```

***

### confirm\_new\_admin

Accept the admin role (second step of two-step transfer).

```rust theme={null}
pub fn confirm_new_admin(
    ctx: Context<ConfirmNewAdmin>,
) -> Result<()>
```

#### Required Accounts

```rust theme={null}
#[derive(Accounts)]
pub struct ConfirmNewAdmin<'info> {
    #[account(
        mut,
        seeds = [GLOBAL_CONFIG_PREFIX],
        bump = global_config.bump,
    )]
    pub global_config: Account<'info, GlobalConfig>,

    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

```typescript theme={null}
await program.methods
  .confirmNewAdmin()
  .accounts({
    globalConfig,
    newAdmin: newAdminWallet.publicKey,
  })
  .rpc();
```

***

### claim\_fees

Claim accumulated protocol fees from a fee vault.

```rust theme={null}
pub fn claim_fees(
    ctx: Context<ClaimFees>,
    fee_wallet: Pubkey,
) -> Result<()>
```

#### Parameters

| Parameter    | Type     | Description                                       |
| ------------ | -------- | ------------------------------------------------- |
| `fee_wallet` | `Pubkey` | The fee wallet address configured in GlobalConfig |

#### Required Accounts

```rust theme={null}
#[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,
        associated_token::mint = stable_coin_mint_address,
        associated_token::authority = program_authority,
        associated_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 the `program_authority`-owned fee-vault ATA to the 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

<Note>
  While anyone can trigger fee claims, the fees are always sent to the `fee_wallet` configured in GlobalConfig, not to the caller.
</Note>

#### Example

```typescript theme={null}
await program.methods
  .claimFees(feeWallet)
  .accounts({
    stableCoinMintAddress: stableMint,
    feeWalletTokenAccount,
    programAuthority,
    feeTokenAccount,
    globalConfig,
    tokenProgram: TOKEN_PROGRAM_ID,
  })
  .rpc();
```

***

## Error Codes

| Error             | Description                                 |
| ----------------- | ------------------------------------------- |
| `Unauthorized`    | Caller is not admin or pending admin        |
| `OutOfRange`      | Protocol fees exceed 9900 BPS               |
| `ProgramPaused`   | Operation blocked by global pause           |
| `InvalidNewAdmin` | Proposed admin is already the current admin |

***

<Card title="Next: Asset Configuration" icon="file-code" href="/svm/instructions/asset-config">
  Learn about per-token NAV configuration and asset management
</Card>
