2

Say we have the following definition for an instruction and we know that my_acc previously took up 200 bytes and is now being realloced to 100. How can we find out how many lamports will be paid to signer for this?

#[derive(Accounts)]
pub struct ReallocMyAcc<'info> {
    #[account(mut)]
    pub signer: Signer<'info>,
    #[account(
        mut,
        realloc = 100,
        realloc::payer = signer,
        realloc::zero = false,
        seeds = [123],
        bump
    )]
    pub my_acc: Account<'info, SomeAccount>,
    pub system_program: Program<'info, System>,
}

pub fn realloc_my_acc(ctx: Context<ReallocMyAcc>) -> Result<()>{
    let lamports_paid_back_to_signer = // How do I calculate this?
}

2 Answers 2

3

I found the answer by looking into the source code of minimum_balance:

/// Minimum balance due for rent-exemption of a given account data size.
pub fn minimum_balance(&self, data_len: usize) -> u64 {
    let bytes = data_len as u64;
    (((ACCOUNT_STORAGE_OVERHEAD + bytes) * self.lamports_per_byte_year) as f64
        * self.exemption_threshold) as u64
    }

Here we see that each account has an extra overhead of ACCOUNT_STORAGE_OVERHEAD (which is 128 bytes) to store it even if it has no data. Note that this is per account, meaning for the first 100 bytes we'll store we'll have to pay for the storage space of 128+100=228 bytes, but for the second 100 bytes we store in an account we only have to pay for those 100 extra bytes since the initial 128 bytes already exist.

Long story short, accounts.rent.minimum_balance from Jonas' answer only applies if we're reallocing an account that was previously nonexistent (not empty, as an empty account still has those 128 bytes already initialized). In all other cases we just do

let rent_var = solana_program::sysvar::rent::Rent::get()?;
let rent = rent.lamports_per_byte_year * bytes_that_we_are_reallocing_count;
1

Should be the rent for 100 bytes so 0.00158688 SOL

solana rent 100

In a program you would need to pass in the Rent sysvar probably and then use:

    let rent = accounts.rent.minimum_balance(100);

and pass it in the sysvar like this:

    pub rent: Sysvar<'info, Rent>,

Would result into this:

#[derive(Accounts)]
pub struct ReallocMyAcc<'info> {
    #[account(mut)]
    pub signer: Signer<'info>,
    #[account(
        mut,
        realloc = 100,
        realloc::payer = signer,
        realloc::zero = false,
        seeds = [123],
        bump
    )]
    pub my_acc: Account<'info, SomeAccount>,
    pub rent: Sysvar<'info, Rent>,
    pub system_program: Program<'info, System>,
}

pub fn realloc_my_acc(ctx: Context<ReallocMyAcc>) -> Result<()>{
    let rent = accounts.rent.minimum_balance(100);
}
```
1
  • 1
    Thank you for this answer, but I think it only applies for accounts that were previously nonexistent, not for realloc in general. I explain my thinking in my own answer, feel free to comment in case I misunderstood your answer :)
    – McBain
    Commented Apr 15 at 11:12

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.