8

I have tried the secure approach to prevent sea-level attacks to close my PDA account:

use anchor_lang::__private::CLOSED_ACCOUNT_DISCRIMINATOR;
use anchor_lang::prelude::*;
use std::io::{Cursor, Write};
use std::ops::DerefMut;

declare_id!("MY_PROGAM_ID");

#[program]
pub mod closing_accounts_secure {
    use super::*;

    pub fn close(ctx: Context<Close>) -> ProgramResult {
        let dest_starting_lamports = ctx.accounts.destination.lamports();

        let account = ctx.accounts.account.to_account_info();
        **ctx.accounts.destination.lamports.borrow_mut() = dest_starting_lamports
            .checked_add(account.lamports())
            .unwrap();
        **account.lamports.borrow_mut() = 0;

        let mut data = account.try_borrow_mut_data()?;
        for byte in data.deref_mut().iter_mut() {
            *byte = 0;
        }

        let dst: &mut [u8] = &mut data;
        let mut cursor = Cursor::new(dst);
        cursor.write_all(&CLOSED_ACCOUNT_DISCRIMINATOR).unwrap();

        Ok(())
    }
}

#[derive(Accounts)]
pub struct Close<'info> {
    #[account(mut, constraint= account.key() == MY_SPECIFIC_PUBKEY)]
    account: UncheckedAccount<'info>,
    destination: AccountInfo<'info>,
}

The SOL balance of the PDA account was actually reduced to 0, but I was unable to initialize again the PDA account after this. Is it because the account discriminator has changed? How can I reset the account discriminator so the account can be initialized again?

4
  • I have faced the same problem that once the account is closed you cannot initialize until epoch ends.
    – Void
    Commented Oct 18, 2022 at 20:05
  • The epoch is already over @Void: explorer.solana.com/address/… but the account doesn't seem to be deleted (even having 0 balance and 0 bytes) therefore I am still unable to initialize the account. Is there a way to set the Account discriminator to 0? Commented Oct 21, 2022 at 5:15
  • I've never run into this issue before, and curious how this resolves. What was the error message you got when you tried to reinitialize the PDA? Was there a reason you avoided using the close constraint? Using that has always worked for me, and I've been able to close and reopen PDAs in the same epoch. docs.rs/anchor-lang/latest/anchor_lang/…
    – HelmetFace
    Commented Dec 10, 2022 at 18:35
  • Still I have no clue @HelmetFace the address 7oSM.. seems to have no balance and when I search for all accounts related to the program it doesn't appear anymore. So I assume it was correctly reset, but nonetheless it throws custom program error: 0x0 whenever I try to initiate the account. Maybe is because account was resized? Would it matter if an account was deleted with a different account size? Commented Dec 16, 2022 at 8:50

1 Answer 1

1

Once the SOL balance is 0, the account is deleted at the end of the transaction. You can see this from the "Account does not exist" row on the explorer. The custom program error: 0x0 is probably due to something else. Need more info to debug this. Do you have a transaction you can simulate with https://explorer.solana.com/tx/inspector?cluster=devnet ?

Btw that sealevel-attacks closing accounts example is a little outdated. The preferred way after 1.10 is to realloc() the account data length to 0 instead of writing a closed discriminator. I believe this is what anchor's close constraint does now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.