Skip to main content

spherenet_program_whitelist_interface/state/
whitelist_entry.rs

1use {
2    super::{EntryState, Initializable},
3    bytemuck::{Pod, Zeroable},
4    pinocchio::pubkey::Pubkey,
5    shank::ShankAccount,
6};
7
8/// Offset of the entry_address field in the account data
9pub const ENTRY_ADDRESS_OFFSET: usize = 0;
10/// Offset of the state field in the account data
11pub const STATE_OFFSET: usize = 32;
12
13#[repr(C)]
14#[derive(Copy, Clone, Pod, Zeroable, ShankAccount)]
15pub struct ProgramWhitelistEntry {
16    pub entry_address: Pubkey,
17    pub state: u8,
18}
19
20impl ProgramWhitelistEntry {
21    /// Mark the entry as approved (active on the whitelist)
22    #[inline(always)]
23    pub fn set_approved(&mut self) {
24        self.state = EntryState::Approved as u8;
25    }
26
27    /// Mark the entry as a pending request (awaiting authority approval)
28    #[inline(always)]
29    pub fn set_pending(&mut self) {
30        self.state = EntryState::Pending as u8;
31    }
32
33    /// Check if the deployer has been approved (state == Approved).
34    /// A `Pending` entry is initialized but NOT approved — the deploy gate
35    /// must check this, not just `is_initialized()`.
36    #[inline(always)]
37    pub fn is_approved(&self) -> bool {
38        self.state == EntryState::Approved as u8
39    }
40}
41
42impl Initializable for ProgramWhitelistEntry {
43    #[inline(always)]
44    fn is_initialized(&self) -> bool {
45        self.state != EntryState::Uninitialized as u8
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    /// The deploy gate checks `is_approved()`, NOT `is_initialized()`: a pending
54    /// request is initialized but must not pass the gate. Only an approved entry
55    /// deploys.
56    #[test]
57    fn pending_entry_does_not_pass_deploy_gate() {
58        let mut entry = ProgramWhitelistEntry {
59            entry_address: Pubkey::default(),
60            state: EntryState::Uninitialized as u8,
61        };
62
63        entry.set_pending();
64        assert!(entry.is_initialized());
65        assert!(!entry.is_approved(), "pending entry must not be deployable");
66
67        entry.set_approved();
68        assert!(entry.is_approved(), "approved entry must be deployable");
69    }
70}