Solana slots got faster. Slot-based vesting did not.

A deadline counted in slots was calibrated for a 400 ms slot, and that slot now finishes early on the wall clock.

Vesting cliffs, unlock delays, and per-slot fees were written when a Solana slot lasted about 400 ms. The slot is shorter now. Code that still multiplies by the old length does not fail: the arithmetic succeeds, and the wall-clock deadline is early. This page is that warning. The checker below reads an account at the current sample. The tables stay on one measurement, mainnet on 23 October 2026.

In short

  • Slot time stepped from 400 ms down to 200 ms, reaching that target on 2026-10-09 at slot 454,896,000. A mainnet sample on 23 October measured 211.4 ms per slot.
  • In that sample, slots elapsed about 1.9 times faster, so a duration stored in slots finishes early.
  • Check every slot count, slot delay, and per-slot rate. The checker on this page is the way to read an account. It is a starting point, not an audit.

Check an account

Paste an address. The checker classifies integer fields by name and compares a 400 ms reading with the speed from getRecentPerformanceSamples. That speed is live. It is not the 23 October table below. Source and forecast script: Flow-Biboux/solana-clock-slot.

Loading the checker…

What changed

Two upgrades landed in autumn 2026. They move on-chain time in different ways. Shorter slots change how long a slot count takes on the wall clock. Alpenglow changes who writes Clock.unix_timestamp.

Shorter slots, SIMD-0525. A slot is a leader's turn to produce a block. For years that turn was about 400 ms. SIMD-0525 cut it in four steps:

  • 2026-08-21, slot 440,640,000: 350 ms
  • 2026-08-28, slot 442,368,000: 300 ms
  • 2026-09-18, slot 447,984,000: 250 ms
  • 2026-10-09, slot 454,896,000: 200 ms

The SDK constant stayed put. SIMD-0525 says the solana-sdk constant remains unchanged initially, so DEFAULT_TICKS_PER_SECOND and DEFAULT_TICKS_PER_SLOT still describe a 400 ms slot. The SDK still multiplies as if a slot were 400 ms, so the arithmetic succeeds and the wall-clock result is wrong.

The archived SPL token-lending program turns a yearly rate into a per-slot rate with a fixed SLOTS_PER_YEAR, built from DEFAULT_TICKS_PER_SECOND / DEFAULT_TICKS_PER_SLOT. Integer division in that expression does not produce 78,840,000, which is the 400 ms slots-per-year figure worth searching for. Either constant is frozen to the old tick model, so interest denominated in those slots accrues on the faster clock. This article does not report a measured APY for any deployment of that program.

An epoch is a fixed slot count, 432,000 slots, so epochs now finish in less wall-clock time. Any liquid-staking token or reward calculation that assumed a 400 ms slot inherits the same early-unlock problem. No protocol-by-protocol LST review is published here.

A new writer for the timestamp, Alpenglow. It went live on 2026-10-21 at slot 459,653,000. Before that, Clock.unix_timestamp was a stake-weighted median of validator vote timestamps. The leader now writes unix_timestamp inside a bounded window. Programs should not treat that value as an exact real-world instant. The bound is the one described on the Alpenglow page. This article does not add a tolerance number that page does not state. Slot time and that timestamp bound are separate upgrades.

Where does time hide in a program?

Time shows up in four kinds, and three of them changed.

The "Now" column is the 23 October mainnet sample, 211.4 ms per slot, about 1.9× the old 400 ms assumption. The timestamp row does not use that sample.

KindExampleMeant (400 ms)Now (23 Oct, 211.4 ms)
Absolute slotcliff_slot = start + 150010 min5 min 17 s. The stored slot arrives about twice early.
Duration in slotsdelay_slots = 216,00024 h12 h 41 min. A one-day delay stored as a slot count is shorter on the wall clock.
Rate per slotfee_per_slot = 357.56 M per dayAbout 14.3 M per day (1.9×). The same per-slot fee posts more often per calendar day.
Timestampcliff_ts = start_ts + 60010 min10 min. Unchanged. The deadline is a unix timestamp, not a slot count.

One schedule, two clocks

legacy_secs_to_slots converts a duration in seconds into slots by dividing by 0.4: slots = seconds / 0.4. Six hundred seconds, ten minutes, becomes 1,500 slots. The seconds-based cliff stores the same ten minutes as start_ts + 600 and reads Clock.unix_timestamp. That path does not move when the slot gets shorter.

/// slots = seconds / 0.4
fn legacy_secs_to_slots(seconds: u64) -> u64 {
    seconds * 1_000 / 400
}

let cliff_slots = legacy_secs_to_slots(600); // 1,500 slots
let cliff_ts = start_ts + 600;               // 600 seconds on Clock.unix_timestamp

Both lines mean "unlock in 10 minutes." Only the slot line moves.

ClockStored valueWall clock on 23 Oct
Seconds cliffcliff_ts = start_ts + 60010 min on mainnet and on devnet. Unchanged.
Slot clifflegacy_secs_to_slots(600) = 1,500 slotsMainnet at 211.4 ms: about 5 min 17 s, roughly 4 min 42 s early. Devnet in the same runs sat near 238.5 ms; a 10 minute forecast that still assumed 400 ms was off by about 1,015 slots, roughly 4 min 3 s.

If compared with a one-year slot schedule, the same lock expires after about 193 days. A token that should stay locked for a year can become claimable after about 193 days, using the 23 October mainnet sample of 211.4 ms (400 / 211.4 ≈ 1.9, and 365 / 1.9 ≈ 193).

How the slot time was measured

The forecast uses Helius RPC and two methods. getRecentPerformanceSamples returns about 60 seconds of finalized and skipped slots, which is enough to average the slot time. getBlockTime returns the timestamp of a past slot. The script predicts the slot ten minutes ahead, waits, and compares that prediction with the slot that lands.

npm run forecast -- --minutes 10 --verify

Mainnet on 23 October 2026. This block is that run, not the live sample in the checker:

Measured slot time 211.4 ms (range 206.9 – 219.8, last 30 min)
Forecast +10 min at measured speed: slot 460,458,670
Forecast +10 min at 400 ms:          slot 460,457,332
Actual slot                          460,458,667

Error at measured speed: 3 slots (~0.6 s)
Error at 400 ms:         1,335 slots (~4 min 42 s)

The measured-speed forecast was off by 3 slots, about 0.6 seconds. The 400 ms forecast was off by 1,335 slots, about 4 minutes 42 seconds. On devnet, two runs measured 238.6 ms and 238.5 ms, with the same pattern: 1 to 3 slots of error at the measured speed, and about 1,015 slots against the 400 ms assumption.

What to search for

Grepping a large repo for 400 or 0.4 is noisy. The useful constants are 216,000 and 216000, 432,000 and 432000, 78,840,000 and 78840000, SLOTS_PER, DEFAULT_TICKS_PER, _slots, and per_slot. Search on-chain programs and the clients that build their arguments.

A structured agent audit is a better pass than a raw grep. Helius used that approach for the Agave 4.2 checklist: run the agent audit. The same shape, pointed at the constants above, catches slot math that a single pattern misses.

Run it

The forecast script and the account checker live in solana-clock-slot. The same checker is on this page. It decodes an Anchor IDL, or a pasted IDL, and classifies fields by name. Forecasts use the current speed. It reads account data, not program logic, and not the instructions that rewrite a field at runtime. Starting point, not an audit.

One account from the author's own program, Raid Arena, a non-binary prediction competition: B3dmZyp5amBY6rYWpiWkRj8pV6xpfuGX5MTWXoJvK4D9. The PDA stores when a competition starts and ends. The slot fields are already deprecated. The program uses the timestamp. This is a demo of that deprecation, not a stranger's live bug.

FieldStored readingWall clock on that account
Start timestamp17:50:0017:50:00
End timestamp17:55:0017:55:00
Start slot456,529,18117:46:52
End slot456,529,93117:49:35

The timestamp window is five minutes. The slot window on the same account runs from 17:46:52 to 17:49:35, about 2.7 minutes. Those slot fields are not the schedule the program still enforces.

What to change

  1. Count deadlines in unix_timestamp. Store durations as differences between timestamps. Do not treat the leader's timestamp as exact: it is written inside the bounded window described on the Alpenglow page.
  2. Make slot_per_year updatable if the program must stay on slots. That requires an upgradeable program, so the parameter can follow the network instead of a compiled 400 ms constant.
  3. Search for 216_000, 432_000, 78_840_000, SLOTS_PER, DEFAULT_TICKS_PER, _slots, and per_slot. Skip a raw grep for 400 or 0.4 as the main pass.
  4. Run the checker on this page, and the forecast script in the repo, against accounts that still store slots. Starting point, not an audit.
  5. Migrate stored accounts whose slot fields are still live deadlines, whether the value sits in a PDA or is recomputed from a slot constant.
  6. Tell users when a vest, a fee, or an epoch now arrives earlier than the schedule they were shown.

Solana made the slot faster. A program still has to agree on which clock it is using.

Solana slots got faster. Slot-based vesting did not.