use marsh_api::{consts::*, error::MarshError, instruction::Stake, loaders::*, state::Config};
use marsh_utils::*;
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError,
program_pack::Pack,
};
use spl_token::state::Mint;
pub fn process_upgrade(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult {
let args = Stake::try_from_bytes(data)?;
let amount = u64::from_le_bytes(args.amount);
let [signer, beneficiary_info, mint_info, mint_v1_info, sender_info, treasury_info, token_program, config_info] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};
load_signer(signer)?;
load_token_account(beneficiary_info, Some(&signer.key), &MINT_ADDRESS, true)?;
load_mint(mint_info, MINT_ADDRESS, true)?;
load_mint(mint_v1_info, MINT_V1_ADDRESS, true)?;
load_token_account(sender_info, Some(signer.key), &MINT_V1_ADDRESS, true)?;
load_program(token_program, spl_token::id())?;
load_config(config_info, false)?;
let config_data = config_info.data.borrow();
let config = Config::try_from_bytes(&config_data)?;
if config.evolvable.eq(&0) {
return Err(MarshError::NotEvolvable.into());
}
solana_program::program::invoke(
&spl_token::instruction::burn(
&spl_token::id(),
sender_info.key,
mint_v1_info.key,
signer.key,
&[signer.key],
amount,
)?,
&[
token_program.clone(),
sender_info.clone(),
mint_v1_info.clone(),
signer.clone(),
],
)?;
let amount_to_mint = amount.saturating_mul(10);
let mint_data = mint_info.data.borrow();
let mint = Mint::unpack(&mint_data)?;
if mint.supply.saturating_add(amount_to_mint).gt(&MAX_SUPPLY) {
return Err(MarshError::MaxSupply.into());
}
drop(mint_data);
mint_to_signed(
mint_info,
beneficiary_info,
treasury_info,
token_program,
amount_to_mint,
&[&[TREASURY, &[TREASURY_BUMP]]],
)?;
Ok(())
}