---
title: Account Structure
description:
  Account addresses, the five fields every Solana account contains — lamports,
  data, owner, executable, and rent_epoch — with interactive code walkthrough.
url: /docs/core/accounts/account-structure
type: conceptual
prerequisites:
  - /docs/core/accounts
related:
  - /docs/core/accounts/account-types
  - /docs/core/accounts/modification-rules
  - /docs/core/pda
  - /docs/core/constants-reference
---

{/* TOC: Account Address, Account Fields, ScrollyCoding walkthrough (Lamports, Data, Owner, Executable, Rent Epoch), AccountSharedData, Rent State Machine */}

<Callout type="info" title="Summary">
  Accounts have 5 fields: lamports, data, owner, executable, and rent_epoch.
  Each account is identified by a unique 32-byte address. Accounts must hold a
  minimum lamport balance proportional to their data size to stay onchain.
</Callout>

## Account address

Every account address is a 32-byte value, displayed as a base58-encoded string.
An address can be one of two types:

1. **Public key**: corresponds to an [Ed25519](https://ed25519.cr.yp.to/)
   keypair (has a private key)
2. **Program derived address (PDA)**: deterministically derived from a program
   ID and seeds (no private key)

![An account with its base58 encoded public key address](/assets/docs/core/accounts/account-address.svg)

### Public key

A _rs`Keypair`_ consists of a public key (used as the account address) and a
private key (used to sign transactions). The following example generates a
keypair using the Solana SDK.

<CodeTabs storage="accounts" flags="r">

```ts !! title="Kit"
import { generateKeyPairSigner } from "@solana/kit";

// Kit does not enable extractable private keys
const keypairSigner = await generateKeyPairSigner();
console.log(keypairSigner);
```

```ts !! title="Legacy"
import { Keypair } from "@solana/web3.js";

const keypair = Keypair.generate();
console.log(`Public Key: ${keypair.publicKey}`);
console.log(`Secret Key: ${keypair.secretKey}`);
```

```rs !! title="Rust"
use solana_sdk::signer::{keypair::Keypair, Signer};

#[tokio::main]
async fn main() {
    let keypair = Keypair::new();
    println!("Public Key: {}", keypair.pubkey());
    println!("Secret Key: {:?}", keypair.to_bytes());
}
```

</CodeTabs>

### Program derived address

A [program derived address](/docs/core/pda) (PDA) is deterministically derived
from a program ID and one or more optional seeds. PDAs do not have a
corresponding private key. The following example derives a PDA using the Solana
SDK.

<CodeTabs storage="accounts" flags="r">

```ts !! title="Kit"
import { Address, getProgramDerivedAddress } from "@solana/kit";

const programAddress = "11111111111111111111111111111111" as Address;

const seeds = ["helloWorld"];
const [pda, bump] = await getProgramDerivedAddress({
  programAddress,
  seeds
});

console.log(`PDA: ${pda}`);
console.log(`Bump: ${bump}`);
```

```ts !! title="Legacy"
import { PublicKey } from "@solana/web3.js";

const programAddress = new PublicKey("11111111111111111111111111111111");

const seeds = [Buffer.from("helloWorld")];
const [pda, bump] = await PublicKey.findProgramAddressSync(
  seeds,
  programAddress
);

console.log(`PDA: ${pda}`);
console.log(`Bump: ${bump}`);
```

```rs !! title="Rust"
use solana_sdk::pubkey; // macro
use solana_sdk::pubkey::Pubkey;

#[tokio::main]
async fn main() {
    let program_address = pubkey!("11111111111111111111111111111111");
    let seeds = [b"helloWorld".as_ref()];
    let (pda, bump) = Pubkey::find_program_address(&seeds, &program_address);
    println!("PDA: {}", pda);
    println!("Bump: {}", bump);
}
```

</CodeTabs>

## Account fields

Every
[`Account`](https://github.com/anza-xyz/solana-sdk/blob/clock%40v2.2.3/account/src/lib.rs#L32-L56)
has a maximum size of
[`MAX_ACCOUNT_DATA_LEN`](https://github.com/anza-xyz/agave/blob/v3.1.8/transaction-context/src/lib.rs#L34)
(10 MiB, equivalent to _rs`MAX_PERMITTED_DATA_LENGTH`_) and contains five
fields:

<WithMentions>

| Field                              | Type      | Description                                                         |
| ---------------------------------- | --------- | ------------------------------------------------------------------- |
| [`lamports`](mention:lamports)     | `u64`     | Balance in lamports. Owner can debit; any program can credit.       |
| [`data`](mention:data)             | `Vec<u8>` | Account state or program bytecode. Max 10 MiB. Owner-writable only. |
| [`owner`](mention:owner)           | `Pubkey`  | Program with write access. Reassignable only when data is zeroed.   |
| [`executable`](mention:executable) | `bool`    | True = program account.                                             |
| [`rent_epoch`](mention:rent_epoch) | `Epoch`   | Deprecated. Set to `u64::MAX` for rent-exempt accounts.             |

```rust title="Account"
pub struct Account {
    /// lamports in the account
    // !mention lamports
    pub lamports: u64,
    /// data held in this account
    #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
    // !mention data
    pub data: Vec<u8>,
    /// the program that owns this account. If executable, the program that loads this account.
    // !mention owner
    pub owner: Pubkey,
    /// if true, this account's data contains a program (and is now read-only)
    // !mention executable
    pub executable: bool,
    /// deprecated
    // !mention rent_epoch
    pub rent_epoch: Epoch,
}
```

</WithMentions>

<ScrollyCoding>

## !!steps Lamports

The `lamports` field holds the account's balance in
[lamports](/docs/references/terminology#lamport) (1 SOL = 1,000,000,000
lamports).

Every account must maintain a minimum lamport balance, known as the rent-exempt
balance, to keep its data stored onchain. This balance is proportional to the
account's data size.

<Callout type="info">
  Although often called "rent," the rent-exempt balance functions as a
  refundable deposit, the full balance is recovered when the account is closed.
</Callout>

See
[`minimum_balance()`](https://github.com/anza-xyz/solana-sdk/blob/clock%40v2.2.3/rent/src/lib.rs#L93)
and the rent
[constants](https://github.com/anza-xyz/solana-sdk/blob/clock%40v2.2.3/rent/src/lib.rs#L47-L80).

```rust !! title="Account Examples"
// Example Token Mint Account
Account {
    // !focus
    lamports: 1461600,
    data.len: 82,
    owner: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb,
    executable: false,
    rent_epoch: 0,
    data: 010000001e213c90625a7e643d9555bb01b6c3fe6416d7afd523ce8c7ddd9b923ceafb9d00000000000000000901010000001e213c90625a7e643d9555bb01b6,
}

// Example Token Program Account
Account {
    // !focus
    lamports: 4513200894,
    data.len: 134080,
    owner: BPFLoader2111111111111111111111111111111111,
    executable: true,
    rent_epoch: 18446744073709551615,
    data: 7f454c460201010000000000000000000300f70001000000d8f90000000000004000000000000000800902000000000000000000400038000400400009000800,
}
```

## !!steps Data

The `data` field stores an arbitrary byte array. Its contents depend on the
account type:

- **Program accounts**: Contains executable bytecode or the address of a
  [program data account](/docs/core/accounts/account-types#program-data-accounts)
  that stores the bytecode.
- **Data accounts**: Contains program-defined state data. The owning program
  defines the serialization format.

Reading account data requires two steps:

1. Fetch the account by its [address](#account-address).
2. Deserialize the `data` field from raw bytes into the program-defined data
   structure.

```rust !! title="Account Examples"
// Example Token Mint Account
Account {
    lamports: 1461600,
    // !focus
    data.len: 82,
    owner: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb,
    executable: false,
    rent_epoch: 0,
    // !focus
    data: 010000001e213c90625a7e643d9555bb01b6c3fe6416d7afd523ce8c7ddd9b923ceafb9d00000000000000000901010000001e213c90625a7e643d9555bb01b6,
}

// Example Token Program Account
Account {
    lamports: 4513200894,
    // !focus
    data.len: 134080,
    owner: BPFLoader2111111111111111111111111111111111,
    executable: true,
    rent_epoch: 18446744073709551615,
    // !focus
    data: 7f454c460201010000000000000000000300f70001000000d8f90000000000004000000000000000800902000000000000000000400038000400400009000800,
}
```

## !!steps Owner

The `owner` field contains the program ID (public key) of the program that owns
this account.

The owner program is the only program that can:

- Modify the account's `data` field
- Deduct lamports from the account's `lamports` field

Any program can add lamports to another account, but only the owner can deduct
lamports from it.

For program accounts, the owner is the account's
[loader program](/docs/core/programs/builtin-programs#loader-programs).

```rust !! title="Account Examples"
// Example Token Mint Account
Account {
    lamports: 1461600,
    data.len: 82,
    // !focus
    owner: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb,
    executable: false,
    rent_epoch: 0,
    data: 010000001e213c90625a7e643d9555bb01b6c3fe6416d7afd523ce8c7ddd9b923ceafb9d00000000000000000901010000001e213c90625a7e643d9555bb01b6,
}

// Example Token Program Account
Account {
    lamports: 4513200894,
    data.len: 134080,
    // !focus
    owner: BPFLoader2111111111111111111111111111111111,
    executable: true,
    rent_epoch: 18446744073709551615,
    data: 7f454c460201010000000000000000000300f70001000000d8f90000000000004000000000000000800902000000000000000000400038000400400009000800,
}
```

## !!steps Executable

The `executable` field is a boolean that determines whether the account is a
[program account](/docs/core/accounts/account-types#program-accounts) or a
[data account](/docs/core/accounts/account-types#data-accounts):

- `true` = program account (contains executable code)
- `false` = data account (stores state)

```rust !! title="Account Examples"
// Example Token Mint Account
Account {
    lamports: 1461600,
    data.len: 82,
    owner: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb,
    // !focus
    executable: false,
    rent_epoch: 0,
    data: 010000001e213c90625a7e643d9555bb01b6c3fe6416d7afd523ce8c7ddd9b923ceafb9d00000000000000000901010000001e213c90625a7e643d9555bb01b6,
}

// Example Token Program Account
Account {
    lamports: 4513200894,
    data.len: 134080,
    owner: BPFLoader2111111111111111111111111111111111,
    // !focus
    executable: true,
    rent_epoch: 18446744073709551615,
    data: 7f454c460201010000000000000000000300f70001000000d8f90000000000004000000000000000800902000000000000000000400038000400400009000800,
}
```

## !!steps Rent epoch

**The `rent_epoch` field is deprecated.**

Previously tracked when an account would automatically have lamports deducted to
pay for maintaining its data onchain. Since rent collection is deprecated,
`rent_epoch` is set to `u64::MAX` for all new rent-exempt accounts.

```rust !! title="Account Examples"
// Example Token Mint Account
Account {
    lamports: 1461600,
    data.len: 82,
    owner: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb,
    executable: false,
    // !focus
    rent_epoch: 0,
    data: 010000001e213c90625a7e643d9555bb01b6c3fe6416d7afd523ce8c7ddd9b923ceafb9d00000000000000000901010000001e213c90625a7e643d9555bb01b6,
}

// Example Token Program Account
Account {
    lamports: 4513200894,
    data.len: 134080,
    owner: BPFLoader2111111111111111111111111111111111,
    executable: true,
    // !focus
    rent_epoch: 18446744073709551615,
    data: 7f454c460201010000000000000000000300f70001000000d8f90000000000004000000000000000800902000000000000000000400038000400400009000800,
}
```

</ScrollyCoding>
