kvault_interface/state/
mod.rs1mod global_config;
9mod pod;
10mod reserve_whitelist;
11mod vault_allocation;
12mod vault_reward_info;
13mod vault_state;
14
15pub use global_config::*;
16pub use pod::PodU128;
17pub use reserve_whitelist::*;
18pub use spl_discriminator::{ArrayDiscriminator, SplDiscriminate};
19pub use vault_allocation::*;
20pub use vault_reward_info::*;
21pub use vault_state::*;
22
23pub const DISCRIMINATOR_SIZE: usize = ArrayDiscriminator::LENGTH;
25
26#[derive(Debug, Clone, PartialEq, Eq)]
28pub enum AccountDataError {
29 DataTooShort { expected: usize, actual: usize },
31 InvalidDiscriminator { expected: [u8; 8], actual: [u8; 8] },
33}
34
35impl core::fmt::Display for AccountDataError {
36 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
37 match self {
38 Self::DataTooShort { expected, actual } => {
39 write!(
40 f,
41 "account data too short: expected {expected}, got {actual}"
42 )
43 }
44 Self::InvalidDiscriminator { expected, actual } => {
45 write!(
46 f,
47 "invalid discriminator: expected {expected:?}, got {actual:?}"
48 )
49 }
50 }
51 }
52}
53
54impl std::error::Error for AccountDataError {}
55
56pub fn from_account_data<T: bytemuck::Pod + SplDiscriminate>(
60 data: &[u8],
61) -> Result<&T, AccountDataError> {
62 let expected_len = DISCRIMINATOR_SIZE + core::mem::size_of::<T>();
63 if data.len() < expected_len {
64 return Err(AccountDataError::DataTooShort {
65 expected: expected_len,
66 actual: data.len(),
67 });
68 }
69 let disc = &data[..DISCRIMINATOR_SIZE];
70 if disc != T::SPL_DISCRIMINATOR_SLICE {
71 let mut actual = [0u8; 8];
72 actual.copy_from_slice(disc);
73 let mut expected = [0u8; 8];
74 expected.copy_from_slice(T::SPL_DISCRIMINATOR_SLICE);
75 return Err(AccountDataError::InvalidDiscriminator { expected, actual });
76 }
77 Ok(bytemuck::from_bytes(
78 &data[DISCRIMINATOR_SIZE..expected_len],
79 ))
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn verify_account_sizes() {
88 assert_eq!(core::mem::size_of::<VaultState>(), 62544);
89 assert_eq!(core::mem::size_of::<VaultAllocation>(), 2160);
90 assert_eq!(core::mem::size_of::<GlobalConfig>(), 1024);
91 assert_eq!(core::mem::size_of::<ReserveWhitelistEntry>(), 128);
92 }
93
94 #[test]
95 fn verify_account_discriminators() {
96 use sha2::{Digest, Sha256};
97
98 macro_rules! check {
99 ($ty:ty, $name:expr) => {{
100 let mut h = Sha256::new();
101 h.update(concat!("account:", $name).as_bytes());
102 let hash = h.finalize();
103 let mut expected = [0u8; 8];
104 expected.copy_from_slice(&hash[..8]);
105 assert_eq!(
106 <$ty as SplDiscriminate>::SPL_DISCRIMINATOR_SLICE,
107 &expected,
108 concat!("Discriminator mismatch for ", $name),
109 );
110 }};
111 }
112
113 check!(VaultState, "VaultState");
114 check!(GlobalConfig, "GlobalConfig");
115 }
116}