Skip to main content

dlp_api/state/
delegation_metadata.rs

1use std::ptr;
2
3use borsh::{BorshDeserialize, BorshSerialize};
4use pinocchio::{account::RefMut, error::ProgramError, AccountView};
5use solana_program::pubkey::Pubkey;
6
7use super::discriminator::{AccountDiscriminator, AccountWithDiscriminator};
8use crate::{
9    impl_to_bytes_with_discriminator_borsh,
10    impl_try_from_bytes_with_discriminator_borsh, require_ge,
11};
12
13/// The Delegated Metadata includes Account Seeds, max delegation time, seeds
14/// and other meta information about the delegated account.
15/// * Everything necessary at cloning time is instead stored in the delegation record.
16#[derive(BorshSerialize, BorshDeserialize, Debug, PartialEq)]
17pub struct DelegationMetadata {
18    /// The last nonce account had during delegation update
19    /// Deprecated: The last slot at which the delegation was updated
20    pub last_update_nonce: u64,
21    /// Whether the account can be undelegated or not
22    pub is_undelegatable: bool,
23    /// The seeds of the account, used to reopen it on undelegation
24    pub seeds: Vec<Vec<u8>>,
25    /// The account that paid the rent for the delegation PDAs
26    pub rent_payer: Pubkey,
27}
28
29pub struct DelegationMetadataFast<'a> {
30    data: RefMut<'a, [u8]>,
31}
32
33impl<'a> DelegationMetadataFast<'a> {
34    pub fn from_account(
35        account: &'a AccountView,
36    ) -> Result<Self, ProgramError> {
37        require_ge!(
38            account.data_len(),
39            AccountDiscriminator::SPACE
40            + 8  // last_update_nonce
41            + 1  // is_undelegatable
42            + 32 // rent_payer
43            + 4, // seeds (at least 4)
44            ProgramError::InvalidAccountData
45        );
46
47        Ok(Self {
48            data: account.try_borrow_mut()?,
49        })
50    }
51
52    pub fn last_update_nonce(&self) -> u64 {
53        unsafe {
54            ptr::read(self.data.as_ptr().add(AccountDiscriminator::SPACE)
55                as *const u64)
56        }
57    }
58
59    pub fn set_last_update_nonce(&mut self, val: u64) {
60        unsafe {
61            ptr::write(
62                self.data.as_mut_ptr().add(AccountDiscriminator::SPACE)
63                    as *mut u64,
64                val,
65            )
66        }
67    }
68
69    pub fn replace_last_update_nonce(&mut self, val: u64) -> u64 {
70        unsafe {
71            ptr::replace(
72                self.data.as_mut_ptr().add(AccountDiscriminator::SPACE)
73                    as *mut u64,
74                val,
75            )
76        }
77    }
78
79    pub fn set_is_undelegatable(&mut self, val: bool) {
80        unsafe {
81            ptr::write(
82                self.data.as_mut_ptr().add(AccountDiscriminator::SPACE + 8)
83                    as *mut bool,
84                val,
85            )
86        }
87    }
88
89    pub fn replace_is_undelegatable(&mut self, val: bool) -> bool {
90        unsafe {
91            ptr::replace(
92                self.data.as_mut_ptr().add(AccountDiscriminator::SPACE + 8)
93                    as *mut bool,
94                val,
95            )
96        }
97    }
98}
99
100impl AccountWithDiscriminator for DelegationMetadata {
101    fn discriminator() -> AccountDiscriminator {
102        AccountDiscriminator::DelegationMetadata
103    }
104}
105
106impl DelegationMetadata {
107    pub fn serialized_size(&self) -> usize {
108        AccountDiscriminator::SPACE
109        + 8 // last_update_nonce (u64) 
110        + 1 // is_undelegatable (bool)
111        + 32 // rent_payer (Pubkey)
112        + (4 + self.seeds.iter().map(|s| 4 + s.len()).sum::<usize>()) // seeds (Vec<Vec<u8>>)
113    }
114}
115
116impl_to_bytes_with_discriminator_borsh!(DelegationMetadata);
117impl_try_from_bytes_with_discriminator_borsh!(DelegationMetadata);
118
119#[cfg(test)]
120mod tests {
121    use borsh::to_vec;
122
123    use super::*;
124
125    #[test]
126    fn test_serialization_without_discriminator() {
127        let original = DelegationMetadata {
128            seeds: vec![
129                vec![],
130                vec![
131                    215, 233, 74, 188, 162, 203, 12, 212, 106, 87, 189, 226,
132                    48, 38, 129, 7, 34, 82, 254, 106, 161, 35, 74, 146, 30,
133                    211, 164, 97, 139, 136, 136, 77,
134                ],
135            ],
136            is_undelegatable: false,
137            last_update_nonce: 0,
138            rent_payer: Pubkey::default(),
139        };
140
141        // Serialize
142        let serialized = to_vec(&original).expect("Serialization failed");
143
144        // Deserialize
145        let deserialized: DelegationMetadata =
146            DelegationMetadata::try_from_slice(&serialized)
147                .expect("Deserialization failed");
148
149        assert_eq!(deserialized, original);
150    }
151}