Skip to main content

antegen_fiber_program/instructions/
close.rs

1use crate::errors::AntegenFiberError;
2use crate::state::Fiber;
3use anchor_lang::prelude::*;
4
5/// Accounts required by the `close_fiber` instruction.
6/// Thread PDA is signer, receives rent back. Works for both legacy and V1
7/// fiber accounts — discriminator is read manually via `Fiber`.
8#[derive(Accounts)]
9pub struct Close<'info> {
10    /// Thread PDA - signer, receives rent back
11    #[account(mut)]
12    pub thread: Signer<'info>,
13
14    /// CHECK: shape-agnostic fiber account — validated manually below.
15    #[account(mut)]
16    pub fiber: UncheckedAccount<'info>,
17}
18
19pub fn close(ctx: Context<Close>) -> Result<()> {
20    let fiber_info = ctx.accounts.fiber.to_account_info();
21    let thread_info = ctx.accounts.thread.to_account_info();
22
23    let read = {
24        let data = fiber_info.try_borrow_data()?;
25        Fiber::try_deserialize(&mut &data[..])?
26    };
27    require!(
28        read.thread() == thread_info.key(),
29        AntegenFiberError::InvalidFiberPDA
30    );
31
32    sweep_fiber_lamports(&fiber_info, &thread_info)?;
33    Ok(())
34}
35
36/// Drains all lamports from `fiber` into `thread` and zeros the data buffer.
37/// Sets the discriminator bytes to Anchor's `CLOSED_ACCOUNT_DISCRIMINATOR`
38/// sentinel so future reads recognize the slot as closed.
39pub(crate) fn sweep_fiber_lamports<'info>(
40    fiber: &AccountInfo<'info>,
41    thread: &AccountInfo<'info>,
42) -> Result<()> {
43    let fiber_lamports = fiber.lamports();
44    **thread.try_borrow_mut_lamports()? = thread
45        .lamports()
46        .checked_add(fiber_lamports)
47        .ok_or(ProgramError::ArithmeticOverflow)?;
48    **fiber.try_borrow_mut_lamports()? = 0;
49
50    let mut data = fiber.try_borrow_mut_data()?;
51    for byte in data.iter_mut() {
52        *byte = 0;
53    }
54    // Anchor closed-account sentinel: [0xff; 8] in the first 8 bytes — tells
55    // downstream readers the slot is closed (cf. anchor's `close` constraint).
56    if data.len() >= 8 {
57        data[..8].copy_from_slice(&[0xff; 8]);
58    }
59    Ok(())
60}