A lamport is the smallest indivisible unit of SOL on Solana, with exactly 1,000,000,000 lamports per SOL. Balances, transaction fees, priority fees, and rent-exempt reserves are all denominated and computed in lamports, even when wallets display SOL. This article explains the unit model, shows how lamports appear in RPC responses and transaction construction, and gives runnable procedures for converting and verifying values without floating-point drift. It also covers common failure modes such as rounding errors, insufficient rent-exempt balances, and misread fee fields, and points to where to choose an RPC endpoint for testing.
Scope and the lamport unit model
A lamport is the smallest unit of SOL, Solana's native currency. The ratio is fixed: 1 SOL equals 1,000,000,000 lamports, or 10^9. One lamport is 0.000000001 SOL. The unit is named after Leslie Lamport, whose work on distributed systems and logical clocks influenced the design of consensus and ordering systems used in blockchains.
The practical consequence is that every on-chain amount you read or write is an integer number of lamports. Wallet interfaces may render SOL with up to nine decimal places, but the underlying ledger stores integers. Transaction fees, priority fees, account balances, and rent-exempt thresholds are all expressed in lamports. When you build a transaction, you pass lamport integers to the SDK; when you query an RPC node, you receive lamport integers back.
This article assumes you have a Solana RPC endpoint available and basic familiarity with JSON-RPC or one of the Solana SDKs. It focuses on the unit mechanics and verification procedures rather than on choosing a specific provider. If you need a concrete endpoint recommendation for Solana mainnet, testnet, or devnet, the RPC Assistant guidance on the best Solana RPC provider covers that decision separately.
- 1 SOL = 1,000,000,000 lamports (exact, fixed ratio).
- 1 lamport = 0.000000001 SOL.
- Balances, fees, and rent thresholds are integers in lamports on-chain.
- Display layers convert to SOL; program logic should stay in lamports.
Why integer units matter for correctness
Floating-point numbers cannot represent most decimal fractions exactly. If you store 0.1 SOL as a float and multiply by 10^9, you may get 100000000.00000001 or a value that rounds unpredictably depending on the language and platform. On-chain programs avoid this by operating exclusively on integers. Your client code should do the same whenever it constructs or compares amounts.
The safe pattern is to keep lamport values as integers end to end. Convert user-facing SOL input to lamports once, at the boundary, using decimal-aware parsing rather than binary floating point. Convert back to SOL only for display. This avoids off-by-one lamport errors that can cause a transfer to fail a balance check or leave an account just below its rent-exempt threshold.
The same discipline applies to fee math. A base fee plus a priority fee is an integer sum of lamports. If you compute it in floating point and truncate, you may underpay and get a transaction rejected, or overpay slightly on every transaction.
Reading lamports from RPC responses
The getBalance method returns a context object and a value field that is an integer number of lamports. The getAccountInfo method returns lamports in the account's lamports field alongside data, owner, executable, and rentEpoch. These are the canonical sources for balances; do not infer balances from token amounts or from display strings.
The following curl call queries a balance. Replace RPC_URL with your endpoint and the pubkey with the account you want to inspect. The response value is in lamports, not SOL.
- getBalance returns value as an integer lamport count.
- getAccountInfo returns lamports plus the account's data length and owner.
- Commitment levels affect which slot the balance reflects; confirmed is a common default for reads.
curl -s RPC_URL -H 'Content-Type: application/json' -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getBalance",
"params": [
"YOUR_ACCOUNT_PUBKEY",
{"commitment": "confirmed"}
]
}'Expected verification result and a conversion table
After running the balance query, divide the returned integer by 10^9 to get SOL for display. For example, a value of 5000000 lamports is 0.005 SOL. A value of 1000000000 is exactly 1 SOL. The table below shows the relationship for common amounts; fill in your own measured values from your endpoint rather than assuming them.
- | Lamports | SOL | Typical meaning |
- | --- | --- | --- |
- | 1 | 0.000000001 | Smallest unit |
- | 5000 | 0.000005 | Base fee for a simple transaction (documented default) |
- | 10000 | 0.00001 | Example of a small priority fee |
- | 1000000000 | 1 | One SOL |
- | Measured value from getBalance | Divide by 10^9 | Your account balance |
Fees and priority fees in lamports
Solana transaction fees are priced in lamports. The documented base fee for a simple transaction is 5,000 lamports, which is 0.000005 SOL. Priority fees are additional lamports paid per compute unit, set by the transaction's compute budget instructions. The total fee is the base fee plus the priority fee, both integers.
When you inspect a confirmed transaction, the meta.fee field reports the fee actually charged, in lamports. That is the authoritative number to reconcile against your own accounting. Do not assume the base fee alone; priority fees and any other fee components are included in meta.fee.
The following JavaScript example uses the Solana web3.js library to convert SOL to lamports with integer math and to read a balance. It uses LAMPORTS_PER_SOL, which is defined as 1,000,000,000. Replace RPC_URL and the public key with your own values.
import { Connection, LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js';
const connection = new Connection('RPC_URL', 'confirmed');
const account = new PublicKey('YOUR_ACCOUNT_PUBKEY');
// Integer conversion: parse SOL string to lamports without float drift.
function solToLamports(solString) {
const [whole, frac = ''] = solString.split('.');
const fracPadded = (frac + '000000000').slice(0, 9);
return BigInt(whole) * BigInt(LAMPORTS_PER_SOL) + BigInt(fracPadded);
}
const lamports = solToLamports('0.005');
console.log('lamports:', lamports.toString()); // 5000000
const balance = await connection.getBalance(account);
console.log('balance lamports:', balance);
console.log('balance SOL:', balance / LAMPORTS_PER_SOL);Rent-exempt reserves and account creation
Solana accounts must hold a minimum balance to remain open, called the rent-exempt reserve. The threshold is calculated in lamports based on the number of bytes the account stores. When you create a token account or a program data account, you fund it with enough lamports to meet that threshold. If an account is closed, its remaining lamports are returned to the designated recipient.
The exact reserve depends on account size and current parameters. Do not hardcode a single number for all account types. Instead, query the minimum balance for rent exemption for the specific data length using getMinimumBalanceForRentExemption, which returns lamports. This is the correct way to size funding for a new account.
A common failure mode is funding an account with slightly less than the rent-exempt minimum because of a rounding error in SOL-to-lamport conversion. The account creation then fails or the account is subject to rent collection. Always compute the reserve in lamports and compare integers.
curl -s RPC_URL -H 'Content-Type: application/json' -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getMinimumBalanceForRentExemption",
"params": [165, {"commitment": "confirmed"}]
}'A diagnostic procedure for lamport mismatches
When a transfer fails with an insufficient funds error, or when an account unexpectedly closes, work through the lamport values in order. This procedure isolates whether the problem is a balance shortfall, a fee miscalculation, or a rent-exempt threshold issue.
First, query the sender balance with getBalance and record the integer. Second, query the recipient account with getAccountInfo to see whether it exists and what its lamports and data length are. Third, query getMinimumBalanceForRentExemption for the recipient's data length if you are creating it. Fourth, inspect the failed transaction's meta.fee and logs if a signature is available. Compare the sum of transfer amount plus fee plus any rent funding against the sender balance as integers.
The Python example below performs the first three checks. It uses the standard library and a JSON-RPC call, so it has no SDK dependency. Replace RPC_URL and the public keys with your own values.
import json, urllib.request
RPC_URL = 'RPC_URL'
def rpc(method, params):
body = json.dumps({'jsonrpc': '2.0', 'id': 1, 'method': method, 'params': params}).encode()
req = urllib.request.Request(RPC_URL, data=body, headers={'Content-Type': 'application/json'})
with urllib.request.urlopen(req) as resp:
return json.loads(resp.read())
sender = 'SENDER_PUBKEY'
recipient = 'RECIPIENT_PUBKEY'
balance = rpc('getBalance', [sender, {'commitment': 'confirmed'}])['result']['value']
print('sender lamports:', balance)
info = rpc('getAccountInfo', [recipient, {'encoding': 'base64', 'commitment': 'confirmed'}])['result']['value']
if info is None:
print('recipient does not exist; rent funding required')
else:
data_len = len(info['data'][0]) if isinstance(info['data'], list) else 0
print('recipient lamports:', info['lamports'], 'data bytes:', data_len)
reserve = rpc('getMinimumBalanceForRentExemption', [data_len, {'commitment': 'confirmed'}])['result']
print('rent-exempt minimum lamports:', reserve)Troubleshooting common lamport errors
Several failure patterns recur when teams first work with lamports. Recognizing them shortens debugging.
Rounding drift: converting SOL to lamports with floating point and truncating can produce a value one lamport short. Use string or decimal parsing and integer arithmetic. Insufficient rent: creating an account with less than the rent-exempt minimum for its data length causes failure or rent collection. Query the minimum for the exact byte length. Fee underestimation: assuming only the base fee when priority fees are set leads to rejected transactions. Read meta.fee from a confirmed transaction to see the actual charge. Wrong commitment: reading a balance at processed commitment can show a state that is later rolled back. Use confirmed or finalized for decisions that move funds.
If you are testing against a non-mainnet cluster, confirm that your endpoint serves the cluster you expect. The guide to Solana devnet covers cluster selection and faucet workflows. For production reads and writes, endpoint reliability and rate limits matter; the comparison of Solana RPC providers and the RPC pricing page help you size that choice.
- Use integer or decimal parsing, never binary floats, for SOL-to-lamport conversion.
- Query getMinimumBalanceForRentExemption for the exact account data length.
- Reconcile against meta.fee, not an assumed base fee.
- Use confirmed or finalized commitment for balance-sensitive decisions.
Limitations and tradeoffs
Working in lamports is exact but verbose. User interfaces must format large integers into SOL strings, and JavaScript's Number type is only safe up to 2^53, which is about 9 million SOL in lamports. For balances or totals that may exceed that, use BigInt or a decimal library. This is a real constraint for treasury and program-owned accounts.
Rent-exempt thresholds and fee parameters are network parameters that can change. Hardcoding them into long-lived services creates maintenance risk. Prefer querying the chain for the values you need at the time you need them, and cache with a short time-to-live.
Finally, lamports are not a token you can trade independently; they are the accounting unit of SOL. Tools that display a separate 'lamport' price or market are not describing the Solana unit. Treat any such listing as unrelated to the protocol unit described here.
Next steps for integration and operations
Once your conversion and balance checks are integer-safe, the next step is to make your RPC access reliable enough for the read and write volume you need. For a concrete endpoint choice, use the RPC Assistant recommendation for the best Solana RPC provider. For network coverage and cluster details, see the supported networks page. For dedicated throughput and isolation, review dedicated node options, and for cost modeling, the RPC pricing page.
If you are building a broader integration, the multi-chain RPC endpoints guide and the Solana devnet guide provide context for testing across clusters. Keep your lamport handling in one shared utility module so every service converts and compares amounts the same way.
- Centralize SOL-to-lamport and lamport-to-SOL conversion in one tested utility.
- Use BigInt or decimal types wherever totals can exceed 2^53 lamports.
- Query rent-exempt minimums at runtime rather than hardcoding them.
- Choose an endpoint through RPC Assistant guidance, then verify with your own balance and fee measurements.