Files
ore/program/src/upgrade.rs
2024-09-27 08:15:05 +00:00

77 lines
2.1 KiB
Rust

use ore_api::prelude::*;
use steel::*;
/// Upgrade allows a user to migrate a v1 token to a v2 token at a 1:1 exchange rate.
pub fn process_upgrade(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult {
// Parse args
let args = Stake::try_from_bytes(data)?;
let amount = u64::from_le_bytes(args.amount);
// Load accounts
let [signer_info, beneficiary_info, mint_info, mint_v1_info, sender_info, treasury_info, token_program] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};
signer_info.is_signer()?;
beneficiary_info
.is_writable()?
.to_token_account()?
.check(|t| t.owner == *signer_info.key)?
.check(|t| t.mint == MINT_ADDRESS)?;
let mint = mint_info
.is_writable()?
.has_address(&MINT_ADDRESS)?
.to_mint()?;
mint_v1_info
.is_writable()?
.has_address(&MINT_V1_ADDRESS)?
.to_mint()?;
sender_info
.is_writable()?
.to_token_account()?
.check(|t| t.owner == *signer_info.key)?
.check(|t| t.mint == MINT_V1_ADDRESS)?;
treasury_info.is_treasury()?;
token_program.is_program(&spl_token::ID)?;
// Burn v1 tokens
solana_program::program::invoke(
&spl_token::instruction::burn(
&spl_token::id(),
sender_info.key,
mint_v1_info.key,
signer_info.key,
&[signer_info.key],
amount,
)?,
&[
token_program.clone(),
sender_info.clone(),
mint_v1_info.clone(),
signer_info.clone(),
],
)?;
// Account for decimals change.
// v1 token has 9 decimals. v2 token has 11.
let amount_to_mint = amount.saturating_mul(100);
// Cap at max supply.
if mint.supply.saturating_add(amount_to_mint).gt(&MAX_SUPPLY) {
return Err(OreError::MaxSupply.into());
}
// Mint to the beneficiary account
mint_to_signed(
mint_info,
beneficiary_info,
treasury_info,
token_program,
amount_to_mint,
&[&[TREASURY, &[TREASURY_BUMP]]],
)?;
Ok(())
}