Lamports and the SOL Unit
The overview set out the question this whole part answers: on a single global state machine running at hardware speed, what does it cost to touch state, and who pays? Before we can talk about fees, rent, or rewards, we need the unit those costs are measured in. Every price in this part — the base fee, the rent-exempt minimum, a validator’s per-vote outlay, a block reward — is a count of one thing: lamports.
This page defines that unit precisely, explains why the protocol insists on counting in whole integer lamports rather than in fractional SOL, and shows that the number is not an accounting convenience but a correctness decision baked into the runtime. Get this right and every later figure reads unambiguously; get it wrong and you will be off by a factor of a billion.
SOL, and the unit underneath it
Section titled “SOL, and the unit underneath it”SOL is the token you see quoted on exchanges and in wallets — the unit a human thinks in. But SOL is a display unit. The protocol itself never stores a balance as “1.5 SOL.” Underneath, there is one indivisible base unit, and SOL is just a large, round multiple of it.
That base unit is the lamport. It is the smallest amount of value the Solana protocol can represent or move — you cannot hold, send, or burn a fraction of a lamport. The relationship is exact and fixed:
1 SOL = 1,000,000,000 lamports (10^9)
1 lamport = 0.000000001 SOL 1,000 lamports = 0.000001 SOL (one "micro-SOL") 5,000 lamports = 0.000005 SOL (Solana's base transaction fee — you'll meet it next page)So a wallet showing “2.5 SOL” is, to the runtime, holding exactly 2_500_000_000 lamports. The decimal
point you see in a wallet is applied at the last moment, for your eyes only. The chain moved integers the
whole way.
Why a base unit at all?
Section titled “Why a base unit at all?”The same reason every serious money system has one. If the protocol let balances be arbitrary decimals, two questions become impossible to answer cleanly: what is the smallest transfer? and do two independent additions of balances always agree to the last digit? A fixed indivisible unit answers both. The smallest transfer is one unit. And because everything is an integer count of that unit, arithmetic is exact — there is no “0.1 + 0.2 = 0.30000000000000004” hiding in a validator somewhere. On a machine where thousands of validators must independently compute the same balances and agree to the last bit, “exact” is not a nicety; it is the whole game. Disagreement by one lamport is a fork.
Why the protocol counts in integer lamports
Section titled “Why the protocol counts in integer lamports”Recall the Account from the account model — the struct at the heart of the runtime:
pub struct Account { pub lamports: u64, // native balance — an INTEGER count of lamports pub data: Vec<u8>, // opaque program state pub owner: Pubkey, // the program allowed to write this account}The balance field is a u64: an unsigned 64-bit integer. It is not f64, not a decimal type, not “SOL.”
It is a plain count of lamports. That single type choice carries three guarantees the state machine cannot
live without.
Exact arithmetic, no rounding drift. Floating-point numbers cannot represent most decimal fractions
exactly — 0.1 in an f64 is really a nearby binary approximation. Add millions of such approximations
across millions of transactions and the errors accumulate. For money that is fatal: balances that should
be identical on two validators drift apart, and the network can no longer agree on state. Integers have no
such error. a + b is exactly a + b, forever, on every machine. Every debit and credit in the runtime is
integer addition and subtraction on u64 lamports.
Determinism across validators. Consensus requires that every validator, replaying the same transactions,
computes bit-for-bit identical balances. Integer arithmetic is deterministic by definition. Floating-point
results can differ subtly across compilers, CPUs, and optimization settings — exactly the kind of
platform-dependent behavior that would let two honest validators reach two different states from the same
input. u64 closes that door.
A hard ceiling that the type enforces. A u64 holds values up to 2^64 − 1 ≈ 1.84 × 10^19 lamports —
about 1.8 × 10^10 SOL, roughly eighteen billion SOL, comfortably above the total supply. Because the field
is a u64, an overflow is a typed event the runtime must handle (with checked or saturating arithmetic),
not a silent wraparound. The type makes “we ran out of headroom” impossible to ignore.
Here is the transfer program from the runtime doing exactly this — moving an integer count of lamports, no floats anywhere:
impl Program for TransferProgram { fn process(&self, accounts: &mut [Account], data: &[u8]) -> Result<()> { let amount = read_u64(data)?; // amount is in lamports, a u64 let have = accounts[0].lamports; // source balance, in lamports if have < amount { return Err(SolError::InsufficientFunds { have, need: amount }); } accounts[0].lamports = have - amount; // integer subtract accounts[1].lamports = accounts[1].lamports.saturating_add(amount); // integer add Ok(()) }}The instruction data carries the amount as a little-endian u64 — again, lamports. There is no place in
this path where SOL, decimals, or floating point appear. Lamports are the native unit programs move
directly. When a transfer, a fee deduction, or a reward payout happens, what changes is an integer in an
Account.lamports field.
Named after Leslie Lamport
Section titled “Named after Leslie Lamport”The unit is named for Leslie Lamport, the computer scientist whose work underpins how distributed systems agree on anything at all — logical clocks (the “happened-before” relation that orders events without a shared wall clock), the theory of consensus, and Byzantine fault tolerance. That naming is not decoration. This entire book is about building one global state machine out of many machines that must order and agree on events, and Lamport’s work is the intellectual bedrock of that problem. Solana’s Proof of History is, in spirit, a Lamport clock made verifiable. Putting his name on the base unit is the protocol tipping its hat to the reason the whole thing can work.
The same pattern you’ve seen before
Section titled “The same pattern you’ve seen before”If you have read the sibling books, this shape is familiar. Every serious cryptocurrency separates a human-facing display unit from an integer base unit, for exactly the reasons above:
| Chain | Display unit | Base unit | Relationship | Integer type |
|---|---|---|---|---|
| Bitcoin | BTC | satoshi | 1 BTC = 100,000,000 sat (10^8) | 64-bit int |
| Ethereum | ETH | wei | 1 ETH = 1,000,000,000,000,000,000 wei (10^18) | 256-bit int |
| Solana | SOL | lamport | 1 SOL = 1,000,000,000 lamports (10^9) | u64 |
The takeaway is that lamports are not a Solana quirk — they are Solana’s instance of a universal design.
Bitcoin’s satoshi and Ethereum’s wei exist for the same first-principles reason:
money must be counted in exact integers of an indivisible smallest unit, or independent machines cannot
agree on balances. What differs is only the scale factor (10^8, 10^18, 10^9) and the integer width. Notice
Ethereum needs a 256-bit integer for wei because 10^18 is large; Solana’s 10^9 scale fits comfortably in a
u64, which is cheaper to store and to reason about — a small design economy that suits a chain optimizing
for speed.
Every figure in this part is a lamport count
Section titled “Every figure in this part is a lamport count”This is the payoff, and the reason this page comes second. From here on, every economic quantity in this part is denominated in lamports, whatever unit we quote it in for readability:
- The base transaction fee — 5,000 lamports per signature — is deducted from the fee payer’s
Account.lamportsas an integer. See Transaction Fees and Local Fee Markets. - The rent-exempt minimum — the balance an account must hold to persist — is a lamport threshold computed from the account’s byte size. See Rent and Rent-Exemption.
- Block rewards and staking yield — the new lamports minted by inflation and paid to validators and delegators — are lamport credits to accounts. See Inflation and Staking Rewards.
- A validator’s vote costs — the fees it spends to keep voting — are lamport debits every slot. See Validator Economics and Vote Costs.
When a later page says “a fee of 0.000005 SOL,” read it as “5,000 lamports,” because that is the integer the runtime actually subtracts. The SOL figure is the human gloss; the lamport figure is the ground truth.
The architect’s lens
Section titled “The architect’s lens”- Why does it exist? Because a global state machine needs one indivisible, integer base unit so that every validator computes identical balances and agrees to the last digit. The lamport is that unit; SOL is a display multiple (10^9) of it.
- What problem does it solve? Rounding drift and non-determinism. Integer lamports make every balance operation exact and bit-for-bit reproducible across every machine, which is the precondition for consensus on state.
- What are the trade-offs? You gain exactness and determinism; you give up the convenience of writing fractional amounts directly. Every human-facing amount must be scaled by 10^9 and rounded to a whole lamport before it can exist on-chain — a sub-lamport simply cannot be represented.
- When should I avoid it? Never in protocol or program logic — always compute in integer lamports there. “Avoid” only the display unit inside math: convert to SOL only at the very last step, for presentation, never mid-calculation, or you reintroduce the floating-point error the base unit exists to prevent.
- What breaks if I remove it? Exact consensus. Without a fixed integer base unit, two honest validators could compute balances that differ by a rounding error, disagree on state, and fork the chain. The lamport is what makes “the same balance everywhere” mechanically true.
Check your understanding
Section titled “Check your understanding”- State the exact relationship between SOL and lamports, and explain what it means to call the lamport “indivisible.”
- The
Account.lamportsfield is au64, not anf64. Give two distinct reasons the protocol tracks balances as integers rather than floating-point SOL. - A wallet displays a balance of
0.75 SOL. What integer does the runtime actually store, and where does the decimal point come from? - Bitcoin has the satoshi (10^8) and Ethereum the wei (10^18). What single first-principles reason do all three base units share, and what differs between them?
- A later page quotes “a base fee of 5,000 lamports.” Restate that in SOL, and explain why the page insists the lamport figure — not the SOL figure — is the “ground truth.”
Show answers
- 1 SOL = 1,000,000,000 lamports (10^9), exactly. “Indivisible” means the lamport is the smallest representable amount — you cannot hold, send, or burn a fraction of one; every on-chain amount is a whole integer number of lamports.
- Any two of: (a) exactness — integer arithmetic has no rounding drift, whereas floating point cannot
represent most decimals exactly and accumulates error; (b) determinism — integer results are
identical across compilers, CPUs, and machines, which consensus requires, whereas float results can
differ subtly; (c) enforced ceiling — a
u64makes overflow a typed event to handle rather than a silent wraparound. - It stores the integer
750_000_000lamports (0.75 × 10^9). The decimal point is a display-only conversion the wallet applies by dividing the stored lamport count by 10^9; the chain itself only ever moved and stored the integer. - The shared reason: money must be counted in exact integers of an indivisible smallest unit, or
independent machines cannot agree on balances (no rounding, deterministic arithmetic). What differs is
only the scale factor (10^8 for BTC, 10^18 for ETH, 10^9 for SOL) and the integer width used to
hold it (Ethereum needs 256-bit for wei; Solana’s 10^9 fits a
u64). - 5,000 lamports = 0.000005 SOL (5,000 / 10^9). The lamport figure is ground truth because it is the
exact integer the runtime subtracts from the fee payer’s
Account.lamports; the SOL figure is a human-readable gloss produced by dividing by 10^9, and only whole lamports can actually exist on-chain.