Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ mintlify
mintlify-docs/
/CLAUDE.md
.windsurf.context/
.claude
.context
251 changes: 251 additions & 0 deletions compressed-token-program/Extensions/compressible.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
---
title: Compressible
description: The compressible extension sponsors rent-exemption for any type of Solana account except mints.
---

<table>
<thead>
<tr>
<th style={{width: '20%', textAlign: 'left'}}></th>
<th style={{width: '20%', textAlign: 'left'}}>Supported Accounts</th>
<th style={{width: '45%', textAlign: 'left'}}>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td style={{textAlign: 'left'}}>**Compressible**</td>
<td style={{textAlign: 'left'}}>
cToken accounts
</td>
<td style={{textAlign: 'left'}}>
* **Sponsored rent-exemption**
* 200x cheaper than SPL tokens
* Must be **added at account creation**
</td>
</tr>
</tbody>
</table>

## Key Points
Compressible accounts maintain the **functionality of Solana accounts** but with **rent-exemption sponsorship**:

1. The protocol funds the account's rent exemption (rent sponsor) at creation.
2. The account creator top-ups the lamport balance with rent for at least two epochs (12,600 slots / 84 min)
3. The transaction payer top-ups the lamports balance with transactions that write to compressible accounts to keep the account decompressed.
4. The account will be compressed when inactive for a period of 12,600 slots (84 min).
5. When the account is written to, it's automatically decompressed.

### Cost Comparison
This extension makes cToken accounts 200x cheaper than SPL token accounts

| | cToken | SPL |
|-----------|--------|-----|
| allocate | 0.000011 | 0.002 |
| rent for 24h | 0.000005 | - |

<Accordion title="Core Concepts: Solana Rent vs Compressible Accounts">

The **creator of Solana accounts** pays the **rent exemption balance equal to 2 years of rent**.
The rent-exempt balance is proportional to account size (calculated in lamports):

``` rust
minimum_balance = (ACCOUNT_STORAGE_OVERHEAD + data_len) * lamports_per_byte * exemption_threshold

/// Example 100 byte account:
/// minimum_balance = (128 + 100) * 6960 = 1,586,880 lamports
```
<Note>
* Most Solana accounts are rarely accessed after creation, but continue to lock up SOL for the account's lifetime.
* The creator still must pay the rent-exemption balance.
</Note>

**Compressible accounts** build on top of Solana's rent system, but use epochs with a length of 6300 slots to calculate rent.
The **creator pays** the account with **rent for at least two epochs**:

``` rust
rent_per_epoch = base_rent + (data_len * lamports_per_byte_per_epoch)
/// Example 100 byte account: 128 + (100 * 1) = 228 rent per epoch
```

</Accordion>

## Create a cToken Account with Compressible Extension

Here are the steps to create a compressible account:

1. **Set the initial lamports balance** to N epochs (must be at least 2 epochs)
* Customize N **based on expected account activity**.
* The account stays decompressed for N epochs.

* Paid by the **account creator**.
2. **Set the top-up amount** for writes when the account balance falls below the set lamports balance.
* Determines how much lamports are added when the account needs a top-up.
* Top-ups are made by the **transaction fee payer** when the account is written to and is below the set lamports balance.

<Note>
* Accounts become compressible when they advance two epochs without new transactions that add lamports.
* A forester node compresses the account after these two epochs and the protocol can reclaim the rent.
</Note>

```rust
use light_token_client::actions::{
create_compressible_token_account,
CreateCompressibleTokenAccountInputs,
};
use light_ctoken_types::state::TokenDataVersion;

let token_account_pubkey = create_compressible_token_account(
&mut rpc,
CreateCompressibleTokenAccountInputs {
owner: owner_pubkey,
mint: mint_pubkey,
payer: &payer_keypair,
num_prepaid_epochs: 10, // 0 or ≥2
lamports_per_write: Some(5_000), // lamports added per top-up
token_account_version: TokenDataVersion::ShaFlat,
token_account_keypair: None, // SDK generates keypair
}
).await?;
```

<Note>
For associated cToken accounts derive the address with [owner, compressed_token_program_id, mint](https://solscan.io/account/cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m).
</Note>

### Creation Cost

Creating a compressible cToken account (260 bytes) incurs these costs:

<table>
<thead>
<tr>
<th style={{width: '25%', textAlign: 'left'}}>Component</th>
<th style={{width: '25%', textAlign: 'left'}}>Amount</th>
<th style={{width: '23%', textAlign: 'left'}}>Paid By</th>
<th style={{width: '27%', textAlign: 'left'}}>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>Solana rent exemption</td>
<td>~2,700,480 lamports</td>
<td>Rent sponsor PDA</td>
<td>Rent-exemption balance</td>
</tr>
<tr>
<td>Prepaid rent</td>
<td>388 × N epochs*</td>
<td>Payer <br />(Account creator)</td>
<td>Rent for N epochs</td>
</tr>
<tr>
<td>Compression incentive</td>
<td>10,000 lamports <br /> + 1,000 lamports</td>
<td>Payer <br />(Account creator)</td>
<td>Base compression cost<br />+ protocol incentive</td>
</tr>
<tr>
<td>Transaction fee</td>
<td>5,000-10,000 lamports</td>
<td>Payer <br />(Account creator)</td>
<td>Standard Solana tx fees</td>
</tr>
</tbody>
</table>

\* `N` = `num_prepaid_epochs` parameter (0 or 2+, set at creation).

### Top-ups per Transaction

When creating a compressible account, you can configure `lamports_per_write` to automatically add rent on each write ("Top-Up").
This keeps accounts decompressed while active.

The payer's cost depends on the account's funding state:

<table>
<thead>
<tr>
<th style={{width: '30%', textAlign: 'left'}}>Account State</th>
<th style={{width: '25%', textAlign: 'left'}}>Payer Cost</th>
<th style={{width: '45%', textAlign: 'left'}}>Example</th>
</tr>
</thead>
<tbody>
<tr>
<td>Funded for 2+ epochs</td>
<td>0 lamports</td>
<td>No top-up required</td>
</tr>
<tr>
<td>Funded for less than 2 epochs</td>
<td>`lamports_per_write`</td>
<td>Configured as 5,000 lamports <br />→ payer pays 5,000 lamports</td>
</tr>
<tr>
<td>Compressible<br />(ran out of rent)</td>
<td>`lamports_per_write + rent_deficit`</td>
<td>Configured top-up: 5,000 lamports<br />Rent deficit: 3,000 lamports<br />Total payer cost: 8,000 lamports</td>
</tr>
</tbody>
</table>

<Note>
Top-ups are additional to standard Solana transaction fees (typically &lt;10,000 lamports).
</Note>

### Closing compressible accounts

Compressible accounts can be closed by two parties. How rent and lamports balance are distributed depends on which party closes the account.

1. The **Account Owner** can close the account at any time, regardless of rent status. The account is not compressed in this case.

<table>
<thead>
<tr>
<th style={{width: '35%', textAlign: 'left'}}>Component and Amount</th>
<th style={{width: '35%', textAlign: 'left'}}>Recipient</th>
</tr>
</thead>
<tbody>
<tr>
<td>Rent exemption + completed epoch rent</td>
<td>Rent sponsor</td>
</tr>
<tr>
<td>Remaining lamports from top-up (partial epoch)</td>
<td>Account Owner</td>
</tr>
</tbody>
</table>

2. The **Compression Authority** can compress and close the account when it becomes compressible

<table>
<thead>
<tr>
<th style={{width: '35%', textAlign: 'left'}}>Component and Amount</th>
<th style={{width: '35%', textAlign: 'left'}}>Recipient</th>
</tr>
</thead>
<tbody>
<tr>
<td>Rent exemption + remaining lamports<br />(all account lamports)</td>
<td>Rent sponsor</td>
</tr>
<tr>
<td>Compression incentive<br />(11,000 lamports)</td>
<td>Forester node</td>
</tr>
</tbody>
</table>

## Next Steps

<Card
title=" Learn about all relevant actions to cMints"
icon="chevron-right"
color="#0066ff"
href="/compressible/mint-actions"
horizontal
>
</Card>
Loading