shadow_drive_user_staking/instructions/
request_delete_account.rs

1use crate::constants::*;
2use crate::errors::ErrorCodes;
3use crate::instructions::{initialize_account::{ShadowDriveStorageAccount, StorageAccount, StorageAccountV2}, initialize_config::StorageConfig};
4use anchor_lang::prelude::*;
5use anchor_spl::token::Mint;
6use std::convert::TryInto;
7
8/// This is the function that handles the `request_delete_account` ix
9pub fn handler(mut ctx: impl RequestDeleteAccount) -> Result<()> {
10    // Cannot request to delete storage account if immutable
11    require!(
12        !ctx.check_immutable(),
13        ErrorCodes::StorageAccountMarkedImmutable
14    );
15
16    // Cannot flag for deletion when already flagged for deletion
17    require!(
18        !ctx.check_delete_flag(),
19        ErrorCodes::AlreadyMarkedForDeletion
20    );
21
22    msg!(
23        "Requesting to delete StorageAccount account: {}",
24        ctx.get_identifier()
25    );
26    ctx.mark_delete();
27
28    Ok(())
29}
30
31#[derive(Accounts)]
32/// This `RequestDeleteAccount` context is used in the instruction which allows users to
33/// mark an account for future deletion (by an admin).
34pub struct RequestDeleteAccountV1<'info> {
35    /// This is the `StorageConfig` accounts that holds all of the admin, uploader keys.
36    #[account(
37        seeds = [
38            "storage-config".as_bytes()
39        ],
40        bump,
41    )]
42    pub storage_config: Box<Account<'info, StorageConfig>>,
43
44    /// Parent storage account.
45    #[account(
46        mut,
47        seeds = [
48            "storage-account".as_bytes(),
49            &storage_account.owner_1.key().to_bytes(),
50            &storage_account.account_counter_seed.to_le_bytes()
51        ],
52        bump,
53    )]
54    pub storage_account: Box<Account<'info, StorageAccount>>,
55
56    /// File owner, user, fee-payer
57    /// Requires mutability since owner/user is fee payer.
58    #[account(mut, constraint=storage_account.is_owner(owner.key()))]
59    pub owner: Signer<'info>,
60
61    /// Token mint account
62    #[account(address = shdw::ID)]
63    pub token_mint: Account<'info, Mint>,
64
65    /// System Program
66    pub system_program: Program<'info, System>,
67}
68
69#[derive(Accounts)]
70/// This `RequestDeleteAccount` context is used in the instruction which allows users to
71/// mark an account for future deletion (by an admin).
72pub struct RequestDeleteAccountV2<'info> {
73    /// This is the `StorageConfig` accounts that holds all of the admin, uploader keys.
74    #[account(
75        seeds = [
76            "storage-config".as_bytes()
77        ],
78        bump,
79    )]
80    pub storage_config: Box<Account<'info, StorageConfig>>,
81
82    /// Parent storage account.
83    #[account(
84        mut,
85        seeds = [
86            "storage-account".as_bytes(),
87            &storage_account.owner_1.key().to_bytes(),
88            &storage_account.account_counter_seed.to_le_bytes()
89        ],
90        bump,
91    )]
92    pub storage_account: Box<Account<'info, StorageAccountV2>>,
93
94    /// File owner, user, fee-payer
95    /// Requires mutability since owner/user is fee payer.
96    #[account(mut, constraint=storage_account.is_owner(owner.key()))]
97    pub owner: Signer<'info>,
98
99    /// Token mint account
100    #[account(address = shdw::ID)]
101    pub token_mint: Account<'info, Mint>,
102
103    /// System Program
104    pub system_program: Program<'info, System>,
105}
106
107pub trait RequestDeleteAccount {
108    fn check_immutable(&self) -> bool;
109    fn check_delete_flag(&self) -> bool;
110    fn get_identifier(&self) -> String;
111    fn mark_delete(&mut self);
112}
113
114impl RequestDeleteAccount for Context<'_,'_,'_,'_, RequestDeleteAccountV1<'_>> {
115    fn check_immutable(&self) -> bool {
116        self.accounts.storage_account.check_immutable()
117    }
118    fn check_delete_flag(&self) -> bool {
119        self.accounts.storage_account.to_be_deleted
120    }
121    fn get_identifier(&self) -> String {
122        self.accounts.storage_account.get_identifier()
123    }
124    fn mark_delete(&mut self) {
125        let storage_account = &mut self.accounts.storage_account;
126
127        // Update deletion flag and record request time
128        storage_account.to_be_deleted = true;
129        storage_account.delete_request_epoch = Clock::get().unwrap().epoch.try_into().unwrap();
130    }
131}
132
133
134impl RequestDeleteAccount for Context<'_,'_,'_,'_, RequestDeleteAccountV2<'_>> {
135    fn check_immutable(&self) -> bool {
136        self.accounts.storage_account.check_immutable()
137    }
138    fn check_delete_flag(&self) -> bool {
139        self.accounts.storage_account.to_be_deleted
140    }
141    fn get_identifier(&self) -> String {
142        self.accounts.storage_account.get_identifier()
143    }
144    fn mark_delete(&mut self) {
145        let storage_account = &mut self.accounts.storage_account;
146
147        // Update deletion flag and record request time
148        storage_account.to_be_deleted = true;
149        storage_account.delete_request_epoch = Clock::get().unwrap().epoch.try_into().unwrap();
150    }
151}