|
| 1 | +--- |
| 2 | +title: Compressed Token Program |
| 3 | +sidebarTitle: Compressed Token Program |
| 4 | +description: Overview of cMints, cTokens, and compressed token accounts. |
| 5 | +--- |
| 6 | + |
| 7 | +# Overview |
| 8 | + |
| 9 | +The [Compressed Token Program](https://github.com/Lightprotocol/light-protocol/tree/main/programs/compressed-token) extends existing Solana token standards and is **fully compatible with SPL mints and tokens**. |
| 10 | + |
| 11 | +<table> |
| 12 | + <thead> |
| 13 | + <tr> |
| 14 | + <th style={{width: '15%', textAlign: 'left'}}></th> |
| 15 | + <th style={{width: '22%', textAlign: 'left'}}>Account Type</th> |
| 16 | + <th style={{width: '63%', textAlign: 'left'}}>Key Features</th> |
| 17 | + </tr> |
| 18 | + </thead> |
| 19 | + <tbody> |
| 20 | + <tr> |
| 21 | + <td style={{textAlign: 'left'}}>**[cMint](#cmint-accounts)**</td> |
| 22 | + <td style={{textAlign: 'left'}}>Compressed account</td> |
| 23 | + <td style={{textAlign: 'left'}}> |
| 24 | + <ul> |
| 25 | + <li>**Rent-free mint accounts** (similar to SPL mints)</li> |
| 26 | + <li>Optional [Token Metadata](#token-metadata) **extension**</li> |
| 27 | + </ul> |
| 28 | + </td> |
| 29 | + </tr> |
| 30 | + <tr> |
| 31 | + <td style={{textAlign: 'left'}}>**[cToken](#ctoken-account)**</td> |
| 32 | + <td style={{textAlign: 'left'}}>Solana account</td> |
| 33 | + <td style={{textAlign: 'left'}}> |
| 34 | + <ul> |
| 35 | + <li>**Token accounts** derived from cMints (**SPL-compatible**)</li> |
| 36 | + <li>Optional **sponsored rent** exemption via [compressible extension](#compressible) (200x cheaper than SPL tokens)</li> |
| 37 | + <li>Use for token accounts with **frequent writes** (trading, etc.)</li> |
| 38 | + </ul> |
| 39 | + </td> |
| 40 | + </tr> |
| 41 | + <tr> |
| 42 | + <td style={{textAlign: 'left'}}>**[Compressed Token](#compressed-token-account)**</td> |
| 43 | + <td style={{textAlign: 'left'}}>Compressed account</td> |
| 44 | + <td style={{textAlign: 'left'}}> |
| 45 | + <ul> |
| 46 | + <li>**Compressed account** with `TokenData` field</li> |
| 47 | + <li>**Rent-free** and SPL-compatible</li> |
| 48 | + <li>Use for **token distribution** (airdrops, payments, etc.)</li> |
| 49 | + <li>cToken accounts with the **[compressible extension](#compressible) are automatically compressed/decompressed** when active/inactive.</li> |
| 50 | + </ul> |
| 51 | + </td> |
| 52 | + </tr> |
| 53 | + </tbody> |
| 54 | +</table> |
| 55 | + |
| 56 | +<Tip> |
| 57 | +**SPL mints and tokens** owned by the [Token Program](https://github.com/solana-program/token) or [Token-2022](https://github.com/solana-program/token-2022) **require rent** by default. |
| 58 | +</Tip> |
| 59 | + |
| 60 | +# cMint Accounts |
| 61 | + |
| 62 | +<Note> |
| 63 | +* **cMints are compressed accounts** and **cannot be decompressed**. |
| 64 | +* SPL mints can not be compressed to cMints. |
| 65 | +</Note> |
| 66 | + |
| 67 | +cMints **store data and uniquely identify tokens**, similar to SPL mint accounts with two core differences: |
| 68 | +1. cMint accounts are **rent-free**. |
| 69 | +2. Tokens created from cMints are **cTokens** (fully compatible with SPL tokens). |
| 70 | + |
| 71 | +<Tip> |
| 72 | +[Token Metadata](compressible/token-metadata) can be added to cMints in the `extensions` field. |
| 73 | +</Tip> |
| 74 | + |
| 75 | +<Tabs> |
| 76 | + <Tab title="Diagram"> |
| 77 | + <Frame> |
| 78 | + <img |
| 79 | + src="/images/token-explainer.png" |
| 80 | + alt="Diagram showing cMint compressed account structure with three components: Hash (identifier for cMint in purple box), Account (struct containing BaseMint with SPL-compatible fields, cMint Data for program state, and optional Extensions for Token Metadata), and BasemintData (containing Supply, Decimals, Mint Authority, and Freeze Authority fields) with Token Metadata extension" |
| 81 | + /> |
| 82 | + </Frame> |
| 83 | + </Tab> |
| 84 | + <Tab title="Source Code"> |
| 85 | + ```rust |
| 86 | + pub struct CompressedMint { |
| 87 | + // SPL mint layout |
| 88 | + pub base: BaseMint, |
| 89 | + // cMint state used by the Compressed Token Program |
| 90 | + pub metadata: CompressedMintMetadata |
| 91 | + // Field for Token Metadata extension |
| 92 | + pub extensions: Option<Vec<ExtensionStruct>>, |
| 93 | + } |
| 94 | + ``` |
| 95 | + </Tab> |
| 96 | +</Tabs> |
| 97 | + |
| 98 | +<Info> |
| 99 | +Find the [source code of cMints here](https://github.com/Lightprotocol/light-protocol/blob/main/program-libs/ctoken-types/src/state/mint/compressed_mint.rs). |
| 100 | +</Info> |
| 101 | + |
| 102 | +The `metadata` field is used by the Compressed Token Program to store the internal state of a cMint. |
| 103 | + |
| 104 | +The `BaseMint` field replicates the field layout and serialization format of [SPL Mint accounts](https://solana.com/docs/tokens#mint-account). The struct is serialized with Borsh to match the on-chain format of SPL tokens and mints. |
| 105 | + |
| 106 | +Here is how cMints and SPL mints compare: |
| 107 | +<table> |
| 108 | + <thead> |
| 109 | + <tr> |
| 110 | + <th style={{width: '10%', textAlign: 'left'}}>Field</th> |
| 111 | + <th style={{width: '45%', textAlign: 'center'}}>cMint</th> |
| 112 | + <th style={{width: '30%', textAlign: 'center'}}>SPL Mint</th> |
| 113 | + </tr> |
| 114 | + </thead> |
| 115 | + <tbody> |
| 116 | + <tr> |
| 117 | + <td>mint_authority</td> |
| 118 | + <td style={{textAlign: 'center'}}>✓</td> |
| 119 | + <td style={{textAlign: 'center'}}>✓</td> |
| 120 | + </tr> |
| 121 | + <tr> |
| 122 | + <td>supply</td> |
| 123 | + <td style={{textAlign: 'center'}}>✓</td> |
| 124 | + <td style={{textAlign: 'center'}}>✓</td> |
| 125 | + </tr> |
| 126 | + <tr> |
| 127 | + <td>decimals</td> |
| 128 | + <td style={{textAlign: 'center'}}>✓</td> |
| 129 | + <td style={{textAlign: 'center'}}>✓</td> |
| 130 | + </tr> |
| 131 | + <tr> |
| 132 | + <td>is_initialized</td> |
| 133 | + <td style={{textAlign: 'center'}}>✓</td> |
| 134 | + <td style={{textAlign: 'center'}}>✓</td> |
| 135 | + </tr> |
| 136 | + <tr> |
| 137 | + <td>freeze_authority</td> |
| 138 | + <td style={{textAlign: 'center'}}>✓</td> |
| 139 | + <td style={{textAlign: 'center'}}>✓</td> |
| 140 | + </tr> |
| 141 | + <tr> |
| 142 | + <td>cMint Data</td> |
| 143 | + <td style={{textAlign: 'center'}}>✓</td> |
| 144 | + <td style={{textAlign: 'center'}}>-</td> |
| 145 | + </tr> |
| 146 | + <tr> |
| 147 | + <td>Extensions</td> |
| 148 | + <td style={{textAlign: 'center'}}>✓</td> |
| 149 | + <td style={{textAlign: 'center'}}>via Token-2022</td> |
| 150 | + </tr> |
| 151 | + </tbody> |
| 152 | +</table> |
| 153 | + |
| 154 | +# cToken Account |
| 155 | + |
| 156 | +<Note> |
| 157 | +**cToken accounts are Solana accounts**, not compressed accounts. |
| 158 | +</Note> |
| 159 | + |
| 160 | +A cToken account holds token balances like SPL Token accounts: |
| 161 | +* A wallet needs a cToken account for each cMint it wants to hold, with the wallet address set as the cToken account owner. |
| 162 | +* Each wallet can own multiple cToken accounts for the same cMint. |
| 163 | +* A cToken account can only have one owner and hold units of one cMint. |
| 164 | + |
| 165 | +<Tip> |
| 166 | +* Use the **[compressible extension](/compressible/compressible) for sponsored rent exemption**. |
| 167 | +* cToken accounts with this extension are **automatically compressed** with no writes in 6300 slots (1.75 hours), **and decompressed** with new writes. |
| 168 | +</Tip> |
| 169 | + |
| 170 | +<Tabs> |
| 171 | + <Tab title="Diagram"> |
| 172 | + <Frame> |
| 173 | + <img |
| 174 | + src="/images/ctoken-explainer.png" |
| 175 | + alt="Diagram showing cToken Solana account structure with three components: Address (identifier for cToken account in purple box), Account (struct containing Data bytes, Executable flag, Lamports balance, and Owner set to Compressed Token Program), and AccountData (containing Mint, Owner, Amount, and Extensions fields)" |
| 176 | + /> |
| 177 | + </Frame> |
| 178 | + </Tab> |
| 179 | + <Tab title="Source Code"> |
| 180 | + ```rust |
| 181 | + /// Ctoken account structure (with extensions). |
| 182 | + pub struct CToken { |
| 183 | + pub mint: Pubkey, |
| 184 | + pub owner: Pubkey, |
| 185 | + pub amount: u64, |
| 186 | + pub delegate: Option<Pubkey>, // instruction not implemented yet |
| 187 | + pub state: u8, |
| 188 | + pub is_native: Option<u64>, |
| 189 | + pub delegated_amount: u64, // instruction not implemented yet |
| 190 | + pub close_authority: Option<Pubkey>, |
| 191 | + pub extensions: Option<Vec<ExtensionStruct>>, // Optional extensions e.g. compressible |
| 192 | + } |
| 193 | + ``` |
| 194 | + </Tab> |
| 195 | +</Tabs> |
| 196 | + |
| 197 | +<Info> |
| 198 | +Find the [source code of cToken here](https://github.com/Lightprotocol/light-protocol/blob/main/program-libs/ctoken-types/src/state/ctoken/ctoken.rs). |
| 199 | +</Info> |
| 200 | + |
| 201 | +cToken accounts replicate the field layout and serialization format of [SPL Token accounts](https://solana.com/docs/tokens#token-account). The struct is serialized with Borsh to match the on-chain format of SPL tokens. |
| 202 | + |
| 203 | +Here is how cTokens and SPL tokens compare: |
| 204 | +<table> |
| 205 | + <thead> |
| 206 | + <tr> |
| 207 | + <th style={{width: '10%', textAlign: 'left'}}>Field</th> |
| 208 | + <th style={{width: '45%', textAlign: 'center'}}>cToken</th> |
| 209 | + <th style={{width: '30%', textAlign: 'center'}}>SPL Token Account</th> |
| 210 | + </tr> |
| 211 | + </thead> |
| 212 | + <tbody> |
| 213 | + <tr> |
| 214 | + <td>mint</td> |
| 215 | + <td style={{textAlign: 'center'}}>✓</td> |
| 216 | + <td style={{textAlign: 'center'}}>✓</td> |
| 217 | + </tr> |
| 218 | + <tr> |
| 219 | + <td>owner</td> |
| 220 | + <td style={{textAlign: 'center'}}>✓</td> |
| 221 | + <td style={{textAlign: 'center'}}>✓</td> |
| 222 | + </tr> |
| 223 | + <tr> |
| 224 | + <td>amount</td> |
| 225 | + <td style={{textAlign: 'center'}}>✓</td> |
| 226 | + <td style={{textAlign: 'center'}}>✓</td> |
| 227 | + </tr> |
| 228 | + <tr> |
| 229 | + <td>delegate</td> |
| 230 | + <td style={{textAlign: 'center'}}>unimplemented</td> |
| 231 | + <td style={{textAlign: 'center'}}>✓</td> |
| 232 | + </tr> |
| 233 | + <tr> |
| 234 | + <td>state</td> |
| 235 | + <td style={{textAlign: 'center'}}>✓</td> |
| 236 | + <td style={{textAlign: 'center'}}>✓</td> |
| 237 | + </tr> |
| 238 | + <tr> |
| 239 | + <td>is_native</td> |
| 240 | + <td style={{textAlign: 'center'}}>✓</td> |
| 241 | + <td style={{textAlign: 'center'}}>✓</td> |
| 242 | + </tr> |
| 243 | + <tr> |
| 244 | + <td>delegated_amount</td> |
| 245 | + <td style={{textAlign: 'center'}}>unimplemented</td> |
| 246 | + <td style={{textAlign: 'center'}}>✓</td> |
| 247 | + </tr> |
| 248 | + <tr> |
| 249 | + <td>close_authority</td> |
| 250 | + <td style={{textAlign: 'center'}}>✓</td> |
| 251 | + <td style={{textAlign: 'center'}}>✓</td> |
| 252 | + </tr> |
| 253 | + <tr> |
| 254 | + <td>extensions</td> |
| 255 | + <td style={{textAlign: 'center'}}>✓</td> |
| 256 | + <td style={{textAlign: 'center'}}>via Token-2022</td> |
| 257 | + </tr> |
| 258 | + </tbody> |
| 259 | +</table> |
| 260 | + |
| 261 | +# Associated cToken Account |
| 262 | + |
| 263 | +**Associated cToken** accounts follow the same pattern as [associated token accounts](https://docs.solana.com/developing/programming-model/associated-token-account) (ATA): |
| 264 | +* Each wallet needs its own cToken account to hold tokens from the same cMint. |
| 265 | +* It's derived from the owner's address and the cMint account's address. |
| 266 | +* The only **difference** in ATA derivation is the **program ID parameter**. |
| 267 | + |
| 268 | +<table> |
| 269 | + <thead> |
| 270 | + <tr> |
| 271 | + <th style={{width: '10%', textAlign: 'left'}}>Parameter</th> |
| 272 | + <th style={{width: '45%', textAlign: 'left'}}>cToken ATA</th> |
| 273 | + <th style={{width: '30%', textAlign: 'left'}}>SPL ATA</th> |
| 274 | + </tr> |
| 275 | + </thead> |
| 276 | + <tbody> |
| 277 | + <tr> |
| 278 | + <td>owner</td> |
| 279 | + <td colspan="2" style={{textAlign: 'center'}}>wallet address</td> |
| 280 | + </tr> |
| 281 | + <tr> |
| 282 | + <td>program_id</td> |
| 283 | + <td>COMPRESSED_TOKEN_PROGRAM_ID</td> |
| 284 | + <td>SPL_TOKEN_PROGRAM_ID</td> |
| 285 | + </tr> |
| 286 | + <tr> |
| 287 | + <td>mint</td> |
| 288 | + <td colspan="2" style={{textAlign: 'center'}}>mint address</td> |
| 289 | + </tr> |
| 290 | + </tbody> |
| 291 | +</table> |
| 292 | + |
| 293 | +<Info> |
| 294 | +Find the [source code to associated cToken accounts here](https://github.com/Lightprotocol/light-protocol/blob/main/programs/compressed-token/program/src/create_associated_token_account.rs). |
| 295 | +</Info> |
| 296 | + |
| 297 | +<Tip> |
| 298 | +cToken ATAs can implement the **[compressible extension](/compressible/compressible) for sponsored rent exemption**. |
| 299 | +</Tip> |
| 300 | + |
| 301 | +# Compressed Token Account |
| 302 | + |
| 303 | +<Note> |
| 304 | +* Compressed token accounts are stored as `TokenData` in **compressed accounts**. |
| 305 | +* Leading **wallets** like Phantom and Backpack **support compressed tokens**. The UI does not distinguish between SPL and compressed tokens. |
| 306 | +</Note> |
| 307 | + |
| 308 | +Compressed token accounts store token balance, owner, and other information for SPL tokens and cTokens. Any cToken or SPL token can be compressed at will. |
| 309 | + |
| 310 | +<Tip> |
| 311 | +**cToken accounts** with the **[compressible extension](/compressible/compressible) are automatically compressed** with no writes in 6300 slots (1.75 hours), and decompressed with new writes. |
| 312 | +</Tip> |
| 313 | + |
| 314 | +<Tabs> |
| 315 | + <Tab title="Diagram"> |
| 316 | + <Frame> |
| 317 | + <img |
| 318 | + src="/images/compressed-token-explainer.png" |
| 319 | + alt="Diagram showing compressed token account structure with three components: Hash (identifier for compressed token account in purple box), Account (struct containing Data bytes, Executable flag, Lamports balance, and Address set to None), and AccountData (containing Mint, Owner, Amount, and Extensions fields marked as unimplemented)" |
| 320 | + /> |
| 321 | + </Frame> |
| 322 | + </Tab> |
| 323 | + <Tab title="Source Code"> |
| 324 | + ```rust |
| 325 | + pub struct TokenData { |
| 326 | + pub mint: Pubkey, |
| 327 | + pub owner: Pubkey, |
| 328 | + pub amount: u64, |
| 329 | + pub delegate: Option<Pubkey>, |
| 330 | + pub state: u8, |
| 331 | + /// Placeholder for TokenExtension tlv data (unimplemented) |
| 332 | + pub tlv: Option<Vec<u8>>, |
| 333 | + } |
| 334 | + ``` |
| 335 | + </Tab> |
| 336 | +</Tabs> |
| 337 | + |
| 338 | +<Info> |
| 339 | +* Compressed token accounts use the hash as identifier by default. Find the [source code here](https://github.com/Lightprotocol/light-protocol/blob/main/programs/compressed-token/program/src/compressed_token_account.rs). |
| 340 | +* Addresses are optional, since ensuring that the address of a new account is unique incurs additional computational overhead. |
| 341 | +* This is different from cToken and SPL token accounts, which use the address as unique identifier. |
| 342 | +</Info> |
| 343 | + |
| 344 | +# Next Steps |
| 345 | + |
| 346 | +<Card |
| 347 | + title=" Learn how to create cMints" |
| 348 | + icon="chevron-right" |
| 349 | + color="#0066ff" |
| 350 | + href="/compressible/mint-actions" |
| 351 | + horizontal |
| 352 | +> |
| 353 | +</Card> |
0 commit comments