1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//! Time and deadline constraint checks for DeFi programs.
//!
//! Nearly every DeFi instruction involves time: order expiry, listing
//! deadlines, vesting schedules, cooldown periods, oracle staleness.
//! These checks compose with the sysvar clock reader to provide
//! one-line time validation.
use ;
/// Verify the current time has NOT passed a deadline.
///
/// Returns `Ok(())` if `current_timestamp <= deadline`.
/// Use this for orders, listings, bids, and any time-limited operation.
///
/// ```rust,ignore
/// let (_, now) = read_clock(clock_account)?;
/// check_not_expired(now, order.expiry_timestamp)?;
/// ```
/// Verify the current time HAS passed a deadline.
///
/// Returns `Ok(())` if `current_timestamp > deadline`.
/// Use this for claim-after-vesting, settlement after expiry, or
/// cancellation of expired orders.
///
/// ```rust,ignore
/// let (_, now) = read_clock(clock_account)?;
/// check_expired(now, vesting.unlock_timestamp)?;
/// ```
/// Verify the current time is within an inclusive window `[start, end]`.
///
/// Useful for auction periods, sale windows, or any operation that's only
/// valid during a specific time range.
///
/// ```rust,ignore
/// let (_, now) = read_clock(clock_account)?;
/// check_within_window(now, auction.start_time, auction.end_time)?;
/// ```
/// Verify enough time has passed since the last action (cooldown/rate-limit).
///
/// Returns `Ok(())` if `current_timestamp >= last_action + cooldown_seconds`.
/// Use this for rate-limiting operations like price oracle updates,
/// admin parameter changes, or withdrawal cooldowns.
///
/// ```rust,ignore
/// let (_, now) = read_clock(clock_account)?;
/// check_cooldown(pool.last_rebalance, 3600, now)?; // 1-hour cooldown
/// ```
/// Combined: read clock timestamp and verify not expired.
///
/// Reads the Clock sysvar account and checks that the current unix
/// timestamp has not passed the deadline.
///
/// ```rust,ignore
/// check_deadline(clock_account, order.expiry)?;
/// ```
/// Combined: read clock timestamp and verify expired.
///
/// Reads the Clock sysvar account and checks that the current unix
/// timestamp has passed the deadline. For claim-after-expiry patterns.
///
/// ```rust,ignore
/// check_after(clock_account, vesting.unlock_time)?;
/// ```
/// Verify an on-chain data feed (oracle, price feed, etc.) is not stale.
///
/// Compares the slot when the data was last updated against the current slot,
/// rejecting if the gap exceeds `max_age_slots`. Every program integrating
/// Pyth, Switchboard, or any on-chain oracle should call this before using
/// the price.
///
/// Typical staleness thresholds:
/// - Aggressive DeFi (liquidations): 5-25 slots (~2-10 seconds)
/// - Standard DeFi (swaps): 50-150 slots (~20-60 seconds)
/// - Relaxed (display/analytics): 300+ slots
///
/// ```rust,ignore
/// let (current_slot, _) = read_clock(clock)?;
/// let oracle_data = oracle_account.try_borrow()?;
/// let last_update_slot = u64::from_le_bytes(oracle_data[8..16].try_into().unwrap());
/// check_slot_staleness(last_update_slot, current_slot, 50)?; // max 50 slots old
/// ```