From c80e3ac5b3e9aeefc3a4602bf29b3f2920ec1313 Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Sat, 27 Apr 2024 18:27:28 +0000 Subject: [PATCH] scaffold upgrade --- src/consts.rs | 3 ++ src/instruction.rs | 18 +++++++++ src/lib.rs | 1 + src/loaders.rs | 5 ++- src/processor/mod.rs | 2 + src/processor/upgrade.rs | 81 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 src/processor/upgrade.rs diff --git a/src/consts.rs b/src/consts.rs index 7950180..6680cb3 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -102,5 +102,8 @@ pub const NOISE_ADDRESS: Pubkey = pubkey!("2nXZSxfjELuRatcoY64yHdFLZFi3mtesxobHm /// The address of the mint account. pub const MINT_ADDRESS: Pubkey = pubkey!("oreoN2tQbHXVaZsr3pf66A48miqcBXCDJozganhEJgz"); +/// The address of the mint account. +pub const MINT_V1_ADDRESS: Pubkey = pubkey!("oreoN2tQbHXVaZsr3pf66A48miqcBXCDJozganhEJgz"); + /// The address of the treasury account. pub const TREASURY_ADDRESS: Pubkey = pubkey!("FTap9fv2GPpWGqrLj3o4c9nHH7p36ih7NbSWHnrkQYqa"); diff --git a/src/instruction.rs b/src/instruction.rs index c7d9bc8..5e49e49 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -63,6 +63,16 @@ pub enum OreInstruction { #[account(5, name = "token_program", desc = "SPL token program")] Stake = 4, + #[account(0, name = "ore_program", desc = "Ore program")] + #[account(1, name = "signer", desc = "Signer", signer)] + #[account(2, name = "beneficiary", desc = "Beneficiary token account", writable)] + #[account(3, name = "sender", desc = "Signer token account", writable)] + #[account(4, name = "treasury", desc = "Ore treasury account", writable)] + #[account(5, name = "mint", desc = "Ore token mint account", writable)] + #[account(6, name = "mint_v1", desc = "Ore v1 token mint account", writable)] + #[account(7, name = "token_program", desc = "SPL token program")] + Upgrade = 5, + #[account(0, name = "ore_program", desc = "Ore program")] #[account(1, name = "signer", desc = "Admin signer", signer)] #[account(2, name = "bus_0", desc = "Ore bus account 0", writable)] @@ -137,6 +147,12 @@ pub struct StakeArgs { pub amount: [u8; 8], } +#[repr(C)] +#[derive(Clone, Copy, Debug, Pod, Zeroable)] +pub struct UpgradeArgs { + pub amount: [u8; 8], +} + #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] pub struct UpdateAdminArgs { @@ -148,6 +164,7 @@ impl_to_bytes!(RegisterArgs); impl_to_bytes!(MineArgs); impl_to_bytes!(ClaimArgs); impl_to_bytes!(StakeArgs); +impl_to_bytes!(UpgradeArgs); impl_to_bytes!(UpdateAdminArgs); impl_instruction_from_bytes!(InitializeArgs); @@ -155,6 +172,7 @@ impl_instruction_from_bytes!(RegisterArgs); impl_instruction_from_bytes!(MineArgs); impl_instruction_from_bytes!(ClaimArgs); impl_instruction_from_bytes!(StakeArgs); +impl_instruction_from_bytes!(UpgradeArgs); impl_instruction_from_bytes!(UpdateAdminArgs); /// Builds a reset instruction. diff --git a/src/lib.rs b/src/lib.rs index aced536..c31df80 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,6 +41,7 @@ pub fn process_instruction( OreInstruction::Mine => process_mine(program_id, accounts, data)?, OreInstruction::Claim => process_claim(program_id, accounts, data)?, OreInstruction::Stake => process_stake(program_id, accounts, data)?, + OreInstruction::Upgrade => process_upgrade(program_id, accounts, data)?, OreInstruction::Initialize => process_initialize(program_id, accounts, data)?, OreInstruction::UpdateAdmin => process_update_admin(program_id, accounts, data)?, } diff --git a/src/loaders.rs b/src/loaders.rs index cbf034e..71c7ba3 100644 --- a/src/loaders.rs +++ b/src/loaders.rs @@ -7,7 +7,7 @@ use spl_token::state::Mint; use crate::{ state::{Bus, Config, Proof, Treasury}, utils::AccountDeserialize, - BUS_ADDRESSES, BUS_COUNT, CONFIG_ADDRESS, MINT_ADDRESS, NOISE_ADDRESS, TREASURY_ADDRESS, + BUS_ADDRESSES, BUS_COUNT, CONFIG_ADDRESS, NOISE_ADDRESS, TREASURY_ADDRESS, }; // TODO Account checks don't need to deserialize the whole byte array. They can just check the type byte @@ -226,13 +226,14 @@ pub fn load_treasury<'a, 'info>( /// - Expected to be writable, but is not. pub fn load_mint<'a, 'info>( info: &'a AccountInfo<'info>, + address: Pubkey, is_writable: bool, ) -> Result<(), ProgramError> { if info.owner.ne(&spl_token::id()) { return Err(ProgramError::InvalidAccountOwner); } - if info.key.ne(&MINT_ADDRESS) { + if info.key.ne(&address) { return Err(ProgramError::InvalidSeeds); } diff --git a/src/processor/mod.rs b/src/processor/mod.rs index 2410f76..23535f5 100644 --- a/src/processor/mod.rs +++ b/src/processor/mod.rs @@ -5,6 +5,7 @@ mod register; mod reset; mod stake; mod update_admin; +mod upgrade; pub use claim::*; pub use initialize::*; @@ -13,3 +14,4 @@ pub use register::*; pub use reset::*; pub use stake::*; pub use update_admin::*; +pub use upgrade::*; diff --git a/src/processor/upgrade.rs b/src/processor/upgrade.rs new file mode 100644 index 0000000..4788c17 --- /dev/null +++ b/src/processor/upgrade.rs @@ -0,0 +1,81 @@ +use solana_program::{ + account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError, + pubkey::Pubkey, +}; + +use crate::{ + instruction::StakeArgs, loaders::*, state::Treasury, utils::AccountDeserialize, MINT_ADDRESS, + MINT_V1_ADDRESS, TREASURY, +}; + +pub fn process_upgrade<'a, 'info>( + _program_id: &Pubkey, + accounts: &'a [AccountInfo<'info>], + data: &[u8], +) -> ProgramResult { + // Parse args + let args = StakeArgs::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); + }; + load_signer(signer_info)?; + load_token_account( + beneficiary_info, + Some(&signer_info.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_info.key), &MINT_V1_ADDRESS, true)?; + load_program(token_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(), + ], + )?; + + // Mint to beneficiary account + // TODO Account for decimals! + let treasury_data = treasury_info.data.borrow(); + let treasury = Treasury::try_from_bytes(&treasury_data)?; + let treasury_bump = treasury.bump as u8; + drop(treasury_data); + solana_program::program::invoke_signed( + &spl_token::instruction::mint_to( + &spl_token::id(), + mint_info.key, + beneficiary_info.key, + treasury_info.key, + &[treasury_info.key], + amount, + )?, + &[ + token_program.clone(), + mint_info.clone(), + beneficiary_info.clone(), + treasury_info.clone(), + ], + &[&[TREASURY, &[treasury_bump]]], + )?; + + Ok(()) +}