Timestamp Dependency
Detects dangerous dependencies on block timestamps in security-critical logic including access control and randomness.
Timestamp Dependency
Overview
The timestamp dependency detector identifies Solana programs that use Clock sysvar values (timestamps, slots, epochs) in security-critical contexts such as access control decisions, direct equality comparisons, and randomness generation. Validators can manipulate timestamps within acceptable bounds, making them unreliable for strict security logic. For remediation steps, see the Timestamp Dependency Remediation.
Why This Is an Issue
Solana’s Clock sysvar timestamp is derived from validator vote timestamps and is not cryptographically guaranteed to be accurate. Validators have some flexibility in the timestamps they report, meaning:
- Exact equality checks are unreliable: A condition like
if timestamp == target_timemay never trigger or may be manipulable by validators who can nudge the timestamp. - Access control is bypassable: Using timestamps as the sole gate for privileged operations allows validators (or colluding parties) to execute transactions at manipulated times.
- Randomness is predictable: Timestamps, slots, and epochs are known to all participants before a block is finalized, making them unsuitable as entropy sources. Validators can choose which transactions to include based on favorable timestamp values.
The detector distinguishes three severity levels: direct equality checks on timestamps (high), timestamps in non-ordering branch conditions (medium), and timestamps used as entropy sources (high).
How to Resolve
// Before: Vulnerable -- exact timestamp check
pub fn process(accounts: &[AccountInfo]) -> ProgramResult {
let clock = Clock::get()?;
if clock.unix_timestamp == 1700000000 { // Exact match
execute_privileged_operation(accounts)?;
}
Ok(())
}
// After: Fixed -- range-based comparison with tolerance
pub fn process(accounts: &[AccountInfo]) -> ProgramResult {
let clock = Clock::get()?;
let target = 1700000000i64;
let tolerance = 60i64; // 1-minute window
if clock.unix_timestamp >= target && clock.unix_timestamp <= target + tolerance {
execute_privileged_operation(accounts)?;
}
Ok(())
}
Examples
Vulnerable Code: Timestamp as Randomness
pub fn pick_winner(accounts: &[AccountInfo]) -> ProgramResult {
let clock = Clock::get()?;
// VULNERABLE: validators know the timestamp before block finalization
let winner_index = (clock.unix_timestamp as u64) % num_participants;
distribute_prize(accounts, winner_index)?;
Ok(())
}
Fixed Code: Proper Randomness
pub fn pick_winner(accounts: &[AccountInfo]) -> ProgramResult {
// Use a verifiable random function or commit-reveal scheme
let recent_slothashes = &accounts[1];
let slothash_data = recent_slothashes.try_borrow_data()?;
// Combine multiple entropy sources
let seed = solana_program::hash::hash(&slothash_data[..32]);
let winner_index = u64::from_le_bytes(
seed.to_bytes()[..8].try_into().unwrap()
) % num_participants;
distribute_prize(accounts, winner_index)?;
Ok(())
}
Vulnerable Code: Exact Equality
pub fn unlock(accounts: &[AccountInfo]) -> ProgramResult {
let clock = Clock::get()?;
// VULNERABLE: exact match may never trigger or can be manipulated
if clock.unix_timestamp == lockup.release_time {
release_funds(accounts)?;
}
Ok(())
}
Example JSON Finding
{
"detector": "timestamp-dependency",
"severity": "high",
"confidence": 0.78,
"title": "Direct Equality Check on Timestamp",
"description": "Block timestamp is checked for exact equality. Validators can manipulate timestamps within bounds.",
"cwe_ids": [367]
}
Detection Methodology
- Timestamp variable collection: Identifies variables assigned from syscalls with names containing “clock”, “time”, “slot”, or “epoch”.
- Equality check detection: Scans branch conditions for
==comparisons involving timestamp variables (highest severity). - Access control pattern matching: Identifies timestamp variables used in non-ordering branch conditions that may gate privileged operations.
- Randomness pattern detection: Flags XOR or modulo operations combining timestamp variables with constants, which indicate use as an entropy source.
Limitations
False positives: Legitimate timelock and vesting patterns that use ordering comparisons (>=, <=) receive low severity since these represent standard DeFi patterns. Programs using timestamps purely for logging or display purposes may be flagged. False negatives: Timestamps passed through complex expression chains or stored in structs before use may lose tracking. Randomness patterns using multiplication or addition (rather than XOR/modulo) are not detected.
Related Detectors
- Clock Staleness — detects missing staleness bounds on clock usage
- Clock Account Spoofing — detects unvalidated clock account sources
- Weak Randomness — detects insecure random number generation