> ## Documentation Index
> Fetch the complete documentation index at: https://www.zkcompression.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Program Integration

> Build high-performance DeFi programs with rent-free accounts

The Light-SDK sponsors rent-exemption for your PDAs, token accounts, and mints. Your program logic stays the same.

|                       | Before | After    |
| --------------------- | ------ | -------- |
| Rent (avg. DeFi pool) | \~\$2  | \~\$0.02 |

## What Changes

| Area                                        | Change                                                                            |
| ------------------------------------------- | --------------------------------------------------------------------------------- |
| State struct                                | Derive `LightAccount` and add a `compression_info: Option<CompressionInfo>` field |
| Accounts                                    | Derive `LightAccounts` and add `#[light_account]` on init accounts                |
| Program module                              | Add `#[light_program]` on top of `#[program]`                                     |
| Instructions (swap, deposit, withdraw, ...) | No changes                                                                        |

Audit overhead is minimal as your program logic is mostly untouched. The rest is
macro-generated.

If you don't use Anchor, see the [Pinocchio Programs](./programs-pinocchio) guide.

***

<Accordion title="Agent skill">
  Use the [light-sdk](https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk) agent skill to build rent-free DeFi programs:

  ```
  npx skills add Lightprotocol/skills
  ```

  For orchestration, install the [general skill](https://zkcompression.com/skill.md):

  ```bash theme={null}
  npx skills add https://zkcompression.com
  ```
</Accordion>

<Callout type="info">
  You can find a complete rent-free AMM reference implementation [here](https://github.com/Lightprotocol/cp-swap-reference).
</Callout>

<Tabs>
  <Tab title="Guide">
    ## Step 1: Dependencies

    ```toml theme={null}
    [dependencies]

    light-sdk = { version = "0.23.0", features = ["anchor", "v2", "cpi-context"] }
    light-sdk-macros = "0.23.0"
    light-token = { version = "0.23.0", features = ["anchor"] }
    light-anchor-spl = "0.31"    # TokenInterface uses light_token::ID
    anchor-lang = "0.31"
    ```

    ## Step 2: State Struct

    Add `compression_info` field and derive `LightAccount`:

    ```rust theme={null}
    use light_sdk::compressible::CompressionInfo;
    use light_sdk_macros::LightAccount;

    #[derive(Default, Debug, InitSpace, LightAccount)]
    #[account]
    pub struct PoolState {
        /// Add this:
        pub compression_info: Option<CompressionInfo>,
        
        /// Your existing fields
        /// ...
    }
    ```

    ## Step 3: Program

    Add `#[light_program]` above `#[program]`:

    ```rust theme={null}
    use light_sdk_macros::light_program;

    #[light_program]
    #[program]
    pub mod my_amm {
        use super::*;

        pub fn initialize_pool(ctx: Context<InitializePool>, params: InitializeParams) -> Result<()> {
            process_initialize_pool(ctx, params)
        }

        // These don't change
        pub fn swap(ctx: Context<Swap>, amount_in: u64, min_out: u64) -> Result<()> {
            process_swap(ctx, amount_in, min_out)
        }
    }
    ```

    ## Step 4: Accounts Struct

    Derive `LightAccounts` on your `Accounts` struct and add `#[light_account(...)]` next to `#[account(...)]`.

    <Tabs>
      <Tab title="PDAs">
        ```rust theme={null}
        #[account(
            init, 
            seeds = [...], 
            bump, 
            payer = creator, 
            space = 8 + PoolState::INIT_SPACE
        )]
        #[light_account(init)]
        pub pool_state: Box<Account<'info, PoolState>>,
        ```
      </Tab>

      <Tab title="Token Account">
        ```rust theme={null}
        #[account(
            mut, 
            seeds = [b"vault", pool_state.key().as_ref(), mint.key().as_ref()], 
            bump,
            payer = creator,
            space = 8 + TokenAccount::INIT_SPACE
        )]
        #[light_account(
            init, 
            token, 
            authority = [AUTH_SEED.as_bytes()], 
            mint = token_mint, 
            owner = authority,
        )]
        pub token_vault: UncheckedAccount<'info>,
        ```

        <Accordion title="Manual">
          ```rust theme={null}
          #[account(
              mut, 
              seeds = [b"vault", pool_state.key().as_ref(), mint.key().as_ref()], 
              bump,
              payer = creator,
              space = 8 + TokenAccount::INIT_SPACE
          )]
          #[light_account(
              token, 
              authority = [AUTH_SEED.as_bytes()], 
              mint = token_mint, 
              owner = authority,
          )]
          pub token_vault: UncheckedAccount<'info>,
          ```

          Use without `init` to create manually in the instruction handler via
          `CreateTokenAccountCpi`.
        </Accordion>
      </Tab>

      <Tab title="Associated Token Account (ATA)">
        ```rust theme={null}
        #[light_account(
            init, 
            associated_token, 
            owner = creator, mint = lp_mint,
        )]
        pub creator_lp_token: UncheckedAccount<'info>,
        ```
      </Tab>

      <Tab title="Mint">
        ```rust theme={null}
        #[account(mut)]
        #[light_account(
            init,
            mint,
            mint_signer = lp_mint_signer,
            authority = authority,
            decimals = 9,
            mint_seeds = &[LP_MINT_SIGNER_SEED, pool_state.key().as_ref(), &[params.mint_signer_bump]],
            authority_seeds = &[AUTH_SEED.as_bytes(), &[params.authority_bump]]
        )]
        pub lp_mint: UncheckedAccount<'info>,
        ```

        <Accordion title="Mint with Metadata">
          ```rust theme={null}
          #[light_account(
              init,
              mint,
              mint_signer = mint_signer,
              authority = fee_payer,
              decimals = 9,
              mint_seeds = &[MINT_SIGNER_SEED, authority.key().as_ref(), &[params.mint_signer_bump]],
              name = params.name.clone(),
              symbol = params.symbol.clone(),
              uri = params.uri.clone(),
              // Optional
              update_authority = authority,
              additional_metadata = params.additional_metadata.clone()
          )]
          pub mint: UncheckedAccount<'info>,
          ```
        </Accordion>
      </Tab>
    </Tabs>

    <Accordion title="Full Accounts Struct">
      We also need to add `light_token_interface_config`, `rent_sponsor`, and `light_token_cpi_authority`.

      ```rust theme={null}
      use light_sdk::interface::CreateAccountsProof;
      use light_sdk_macros::LightAccounts;
      use light_token::instruction::{COMPRESSIBLE_CONFIG_V1, RENT_SPONSOR as LIGHT_TOKEN_RENT_SPONSOR};

      #[derive(AnchorSerialize, AnchorDeserialize, Clone)]
      pub struct InitializeParams {
          pub create_accounts_proof: CreateAccountsProof,
          pub lp_mint_signer_bump: u8,
          pub creator_lp_token_bump: u8,
          pub authority_bump: u8,
      }

      #[derive(Accounts, LightAccounts)]
      #[instruction(params: InitializeParams)]
      pub struct InitializePool<'info> {
          #[account(mut)]
          pub creator: Signer<'info>,

          #[account(mut, seeds = [AUTH_SEED.as_bytes()], bump)]
          pub authority: UncheckedAccount<'info>,

          #[account(
              init,
              seeds = [POOL_SEED.as_bytes(), token_0_mint.key().as_ref(), token_1_mint.key().as_ref()],
              bump,
              payer = creator,
              space = 8 + PoolState::INIT_SPACE
          )]
          #[light_account(init)]
          pub pool_state: Box<Account<'info, PoolState>>,

          pub token_0_mint: Box<InterfaceAccount<'info, Mint>>,
          pub token_1_mint: Box<InterfaceAccount<'info, Mint>>,

          #[account(seeds = [POOL_LP_MINT_SIGNER_SEED, pool_state.key().as_ref()], bump)]
          pub lp_mint_signer: UncheckedAccount<'info>,

          #[account(mut)]
          #[light_account(init, mint,
              mint_signer = lp_mint_signer,
              authority = authority,
              decimals = 9,
              mint_seeds = &[POOL_LP_MINT_SIGNER_SEED, self.pool_state.to_account_info().key.as_ref(), &[params.lp_mint_signer_bump]],
              authority_seeds = &[AUTH_SEED.as_bytes(), &[params.authority_bump]]
          )]
          pub lp_mint: UncheckedAccount<'info>,

          #[account(mut, seeds = [POOL_VAULT_SEED.as_bytes(), pool_state.key().as_ref(), token_0_mint.key().as_ref()], bump)]
          #[light_account(token, authority = [AUTH_SEED.as_bytes()])]
          pub token_0_vault: UncheckedAccount<'info>,

          #[account(mut, seeds = [POOL_VAULT_SEED.as_bytes(), pool_state.key().as_ref(), token_1_mint.key().as_ref()], bump)]
          #[light_account(token, authority = [AUTH_SEED.as_bytes()])]
          pub token_1_vault: UncheckedAccount<'info>,

          #[account(mut)]
          pub creator_lp_token: UncheckedAccount<'info>,


          pub light_interface_config: AccountInfo<'info>,
          #[account(address = COMPRESSIBLE_CONFIG_V1)]
          pub light_token_interface_config: AccountInfo<'info>,
          #[account(mut, address = LIGHT_TOKEN_RENT_SPONSOR)]
          pub rent_sponsor: AccountInfo<'info>,
          pub light_token_program: AccountInfo<'info>,
          pub light_token_cpi_authority: AccountInfo<'info>,
          pub system_program: Program<'info, System>,
      }
      ```
    </Accordion>

    ## Step 5: Instructions

    Replace `spl_token` with `light_token` instructions as you need. The API is a superset of SPL-token so switching is straightforward.

    Examples include: `MintToCpi`, `TransferCpi`, `TransferInterfaceCpi`,
    `CreateTokenAccountCpi`, and `CreateTokenAtaCpi`.

    <Accordion title="Example: Initialize">
      ```rust theme={null}
      use light_token::instruction::{CreateTokenAccountCpi, CreateTokenAtaCpi, MintToCpi};

      pub fn process_initialize_pool(ctx: Context<InitializePool>, params: InitializeParams) -> Result<()> {
          let pool_key = ctx.accounts.pool_state.key();
          
          // Create rent-free token vault
          CreateTokenAccountCpi {
              payer: ctx.accounts.creator.to_account_info(),
              account: ctx.accounts.token_0_vault.to_account_info(),
              mint: ctx.accounts.token_0_mint.to_account_info(),
              owner: ctx.accounts.authority.key(),
          }
          .rent_free(
              ctx.accounts.light_token_interface_config.to_account_info(),
              ctx.accounts.rent_sponsor.to_account_info(),
              ctx.accounts.system_program.to_account_info(),
              &crate::ID,
          )
          .invoke_signed(&[
              POOL_VAULT_SEED.as_bytes(),
              pool_key.as_ref(),
              ctx.accounts.token_0_mint.key().as_ref(),
              &[ctx.bumps.token_0_vault],
          ])?;

          // Create rent-free ATA for LP tokens
          CreateTokenAtaCpi {
              payer: ctx.accounts.creator.to_account_info(),
              owner: ctx.accounts.creator.to_account_info(),
              mint: ctx.accounts.lp_mint.to_account_info(),
              ata: ctx.accounts.creator_lp_token.to_account_info(),
              bump: params.creator_lp_token_bump,
          }
          .idempotent()
          .rent_free(
              ctx.accounts.light_token_interface_config.to_account_info(),
              ctx.accounts.rent_sponsor.to_account_info(),
              ctx.accounts.system_program.to_account_info(),
          )
          .invoke()?;

          // Mint LP tokens (standard CPI, no changes)
          MintToCpi {
              mint: ctx.accounts.lp_mint.to_account_info(),
              destination: ctx.accounts.creator_lp_token.to_account_info(),
              amount: 1000,
              authority: ctx.accounts.authority.to_account_info(),
              system_program: ctx.accounts.system_program.to_account_info(),
              max_top_up: None,
          }
          .invoke_signed(&[&[AUTH_SEED.as_bytes(), &[ctx.bumps.authority]]])?;

          // Populate pool state (unchanged)
          let pool = &mut ctx.accounts.pool_state;
          pool.token_0_vault = ctx.accounts.token_0_vault.key();
          pool.lp_mint = ctx.accounts.lp_mint.key();
          // ...

          Ok(())
      }
      ```
    </Accordion>
  </Tab>

  <Tab title="AI Prompt">
    <Prompt description="Add rent-free accounts to an Anchor DeFi program" actions={["copy", "cursor"]}>
      {`---
            description: Add rent-free accounts to an Anchor DeFi program
            allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression
            ---

            ## Add rent-free accounts to an Anchor DeFi program

            Context:
            - Guide: https://zkcompression.com/light-token/defi/programs
            - Skills and resources index: https://zkcompression.com/skill.md
            - Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk
            - Crates: light-sdk (features: anchor, v2, cpi-context), light-sdk-macros, light-token (features: anchor), light-anchor-spl
            - AMM reference: https://github.com/Lightprotocol/cp-swap-reference

            Key macros/APIs: #[light_program], LightAccount, LightAccounts, #[light_account(init)], CompressionInfo

            ### 1. Index project
            - Grep \`#\[program\]|anchor_lang|Account<|Accounts|InitSpace|seeds|init|payer\` across src/
            - Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure
            - Identify: existing program module, account structs, PDA seeds, token accounts, init instructions
            - Read Cargo.toml — note existing dependencies and framework version
            - Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel

            ### 2. Read references
            - WebFetch the guide above
            - WebFetch skill.md — check for a dedicated skill and resources matching this task
            - TaskCreate one todo per phase below to track progress

            ### 3. Clarify intention
            - AskUserQuestion: what is the goal? (new program from scratch, migrate existing program to rent-free, add rent-free accounts to specific instructions)
            - AskUserQuestion: which account types need to be rent-free? (PDAs, token accounts, ATAs, mints)
            - Summarize findings and wait for user confirmation before implementing

            ### 4. Create plan
            - Based on steps 1–3, draft an implementation plan
            - Follow the guide's step order: Dependencies → State Struct → Program Module → Accounts Struct → Instructions
            - Identify which existing structs need changes (CompressionInfo field, LightAccount derive, etc.)
            - If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion)
            - Present the plan to the user for approval before proceeding

            ### 5. Implement
            - Add deps if missing: Bash \`cargo add light-sdk@0.23 --features anchor,v2,cpi-context\` and \`cargo add light-sdk-macros@0.23\` and \`cargo add light-token@0.23 --features anchor\` and \`cargo add light-anchor-spl@0.31\`
            - Follow the guide and the approved plan
            - Write/Edit to create or modify files
            - TaskUpdate to mark each step done

            ### 6. Verify
            - Bash \`anchor build\`
            - Bash \`anchor test\` if tests exist
            - TaskUpdate to mark complete

            ### Tools
            - mcp__zkcompression__SearchLightProtocol("<query>") for API details
            - mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "<q>") for architecture
            - Task subagent with Grep/Read/WebFetch for parallel lookups
            - TaskList to check remaining work`}
    </Prompt>

    ```text theme={null}
    ---
    description: Add rent-free accounts to an Anchor DeFi program
    allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression
    ---

    ## Add rent-free accounts to an Anchor DeFi program

    Context:
    - Guide: https://zkcompression.com/light-token/defi/programs
    - Skills and resources index: https://zkcompression.com/skill.md
    - Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk
    - Crates: light-sdk (features: anchor, v2, cpi-context), light-sdk-macros, light-token (features: anchor), light-anchor-spl
    - AMM reference: https://github.com/Lightprotocol/cp-swap-reference

    Key macros/APIs: #[light_program], LightAccount, LightAccounts, #[light_account(init)], CompressionInfo

    ### 1. Index project
    - Grep `#\[program\]|anchor_lang|Account<|Accounts|InitSpace|seeds|init|payer` across src/
    - Glob `**/*.rs` and `**/Cargo.toml` for project structure
    - Identify: existing program module, account structs, PDA seeds, token accounts, init instructions
    - Read Cargo.toml — note existing dependencies and framework version
    - Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel

    ### 2. Read references
    - WebFetch the guide above
    - WebFetch skill.md — check for a dedicated skill and resources matching this task
    - TaskCreate one todo per phase below to track progress

    ### 3. Clarify intention
    - AskUserQuestion: what is the goal? (new program from scratch, migrate existing program to rent-free, add rent-free accounts to specific instructions)
    - AskUserQuestion: which account types need to be rent-free? (PDAs, token accounts, ATAs, mints)
    - Summarize findings and wait for user confirmation before implementing

    ### 4. Create plan
    - Based on steps 1–3, draft an implementation plan
    - Follow the guide's step order: Dependencies → State Struct → Program Module → Accounts Struct → Instructions
    - Identify which existing structs need changes (CompressionInfo field, LightAccount derive, etc.)
    - If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion)
    - Present the plan to the user for approval before proceeding

    ### 5. Implement
    - Add deps if missing: Bash `cargo add light-sdk@0.23 --features anchor,v2,cpi-context` and `cargo add light-sdk-macros@0.23` and `cargo add light-token@0.23 --features anchor` and `cargo add light-anchor-spl@0.31`
    - Follow the guide and the approved plan
    - Write/Edit to create or modify files
    - TaskUpdate to mark each step done

    ### 6. Verify
    - Bash `anchor build`
    - Bash `anchor test` if tests exist
    - TaskUpdate to mark complete

    ### Tools
    - mcp__zkcompression__SearchLightProtocol("<query>") for API details
    - mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "<q>") for architecture
    - Task subagent with Grep/Read/WebFetch for parallel lookups
    - TaskList to check remaining work
    ```
  </Tab>
</Tabs>

***

## Client SDK

To make it easy for clients to integrate with your program, implement the
`LightProgramInterface` trait in your program's SDK crate.

For a detailed example of how clients use this trait, check out the [Router Integration](./routers.mdx) page.

<Accordion title="Example: Trait Implementation">
  ```rust theme={null}
  pub struct AmmSdk {
      pub pool_state_pubkey: Pubkey,
      pub observation_key: Pubkey,
      pub token_0_vault: Pubkey,
      pub token_1_vault: Pubkey,
      pub token_0_mint: Pubkey,
      pub token_1_mint: Pubkey,
      pub lp_mint: Pubkey,
      pub amm_config: Pubkey,
  }

  pub enum AmmInstruction {
      Swap,
      Deposit,
      Withdraw,
  }

  impl LightProgramInterface for AmmSdk {
      type Variant = LightAccountVariant;
      type Instruction = AmmInstruction;

      fn program_id() -> Pubkey {
          PROGRAM_ID
      }

      fn instruction_accounts(&self, ix: &Self::Instruction) -> Vec<Pubkey> {
          match ix {
              AmmInstruction::Swap => vec![
                  self.pool_state_pubkey,
                  self.observation_key,
                  self.token_0_vault,
                  self.token_1_vault,
                  self.token_0_mint,
                  self.token_1_mint,
              ],
              AmmInstruction::Deposit | AmmInstruction::Withdraw => vec![
                  self.pool_state_pubkey,
                  self.observation_key,
                  self.token_0_vault,
                  self.token_1_vault,
                  self.token_0_mint,
                  self.token_1_mint,
                  self.lp_mint,
              ],
          }
      }

      fn load_specs(
          &self,
          cold_accounts: &[AccountInterface],
      ) -> Result<Vec<AccountSpec<Self::Variant>>, Box<dyn Error>> {
          // Build AccountSpec for each cold account by matching pubkey
          // and deserializing its data into the macro-generated variant.
          let mut specs = Vec::new();
          for account in cold_accounts {
              let pubkey = account.key();
              if pubkey == self.pool_state_pubkey || pubkey == self.observation_key {
                  let parsed: PoolState = AnchorDeserialize::deserialize(&mut &account.data()[8..])?;
                  specs.push(AccountSpec::Pda(PdaSpec { interface: account.clone(), variant: parsed.into() }));
              } else if pubkey == self.token_0_vault || pubkey == self.token_1_vault {
                  specs.push(AccountSpec::Token(account.clone()));
              }
              // ...
          }
          Ok(specs)
      }
  }
  ```
</Accordion>

| Resource                     | Link                                                                                                             |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| Trait Implementation Example | [CpSwapSdk](https://github.com/Lightprotocol/cp-swap-reference/blob/main/programs/cp-swap/tests/program.rs#L409) |

***

## Testing

<Accordion title="Example: Integration Test">
  ```rust theme={null}
  use light_program_test::{LightProgramTest, ProgramTestConfig, Rpc};
  use light_sdk::interface::rent::SLOTS_PER_EPOCH;
  use light_client::interface::{create_load_instructions, LightProgramInterface};

  #[tokio::test]
  async fn test_pool_lifecycle() {
      let config = ProgramTestConfig::new_v2(true, Some(vec![("my_amm", MY_AMM_ID)]));
      let mut rpc = LightProgramTest::new(config).await.unwrap();

      // 1. Init pool (rent-free)
      // ... build and send init instruction ...

      // 2. Swap (hot path - works normally)
      // ... build and send swap instruction ...

      // 3. Trigger compression (advance time)
      rpc.warp_slot_forward(SLOTS_PER_EPOCH * 30).await.unwrap();

      let pool_interface = rpc
          .get_account_interface(&pool_address, None)
          .await
          .unwrap()
          .value
          .unwrap();
      assert!(pool_interface.is_cold());

      // 4. Build SDK and get load instructions
      let sdk = AmmSdk::new(pool_address, pool_interface.data()).unwrap();
      let pubkeys = sdk.instruction_accounts(&AmmInstruction::Deposit);
      let accounts = rpc.get_multiple_account_interfaces(pubkeys.iter().collect(), None).await.unwrap().value;
      let cold: Vec<_> = accounts.into_iter().flatten().filter(|a| a.is_cold()).collect();

      let specs = sdk.load_specs(&cold).unwrap();
      let load_ixs = create_load_instructions(&specs, payer.pubkey(), config_pda, &rpc).await.unwrap();

      // 5. Send transaction
      rpc.create_and_send_transaction(&load_ixs, &payer.pubkey(), &[&payer]).await.unwrap();
  }
  ```
</Accordion>

| Resource     | Link                                                                                                         |
| ------------ | ------------------------------------------------------------------------------------------------------------ |
| Test example | [program.rs](https://github.com/Lightprotocol/cp-swap-reference/blob/main/programs/cp-swap/tests/program.rs) |

***

## How it works

The SDK pays the rent-exemption cost. After extended inactivity, cold accounts auto-compress. Your program only ever
interacts with hot accounts. Clients can safely load cold accounts back into the
onchain Solana account space when needed via `create_load_instructions`.

Under the hood, clients use `AccountInterface` - a superset of Solana's
`Account` that unifies hot and cold state. See [Router Integration](./routers)
for details.

|                   | Hot (active) | Cold (inactive)   |
| ----------------- | ------------ | ----------------- |
| Storage           | On-chain     | Compressed        |
| Latency/CU        | No change    | +load instruction |
| Your program code | No change    | No change         |

## Existing programs

If you want to migrate your program to rent-free accounts and would like hands-on support, [join our tech Discord](https://discord.com/invite/7cJ8BhAXhu),
or [email us](mailto:support@lightprotocol.com).

## FAQ

<Accordion title="How does it prevent re-init attacks?"> When creating an
account for the first time, the SDK provides a proof that the account doesn't
exist in the cold address space. The SVM already verifies this for the onchain
space. Both address spaces are checked before creation, preventing re-init
attacks, even if the account is currently cold. </Accordion>

<Accordion title="Who triggers compression?">
  Miners (Forester nodes) compress accounts that have been inactive for an extended period of time (when their virtual rent balance drops below threshold).
  In practice, having to load cold accounts should be rare. The common path (hot) has no extra overhead and does not increase CU or txn size.
</Accordion>

<Accordion title="How is the SDK able to sponsor rent exemption?">
  When accounts compress after extended inactivity, the on-chain rent-exemption is released back
  to the rent sponsor. This creates a revolving lifecycle: active "hot" accounts hold a
  rent-exempt lamports balance, inactive "cold" accounts release it back. The
  rent sponsor must be derived from the program owner. For all mint, ATA, and
  token accounts, the Light Token Program is the rent sponsor. For your own program-owned PDAs, the SDK derives a rent sponsor address automatically.
</Accordion>

<Accordion title="Do rent-free accounts increase CU?">
  **Hot path (e.g. swap, deposit, withdraw):** No. Active accounts do not add CU overhead to your instructions.

  **First time init + loading cold accounts:** Yes, adds up to 15k-400k CU,
  depending on number and type of accounts being initialized or loaded.
</Accordion>

***

<Callout type="info">
  Questions or need hands-on support? [Telegram](https://t.me/swen_light) | [email](mailto:support@lightprotocol.com) | [Discord](https://discord.com/invite/7cJ8BhAXhu)
</Callout>
