From 44f40218340659b802a2fd781dfeb09f68255375 Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Wed, 8 Oct 2025 16:34:53 -0700 Subject: [PATCH] refined --- api/src/instruction.rs | 20 +++++-- api/src/sdk.rs | 43 +++++++++++---- api/src/state/miner.rs | 96 +++++++++++++++++++++++++++++--- api/src/state/mod.rs | 7 +++ api/src/state/stake.rs | 6 +- api/src/state/treasury.rs | 33 ++++++++++- cli/src/main.rs | 97 +++++++++++++++++++++++++++++++-- program/src/bury.rs | 3 +- program/src/claim_ore.rs | 9 +-- program/src/claim_sol.rs | 9 +-- program/src/deploy.rs | 3 +- program/src/deposit.rs | 2 +- program/src/lib.rs | 6 ++ program/src/migrate_miner.rs | 60 ++++++++++++++++++++ program/src/migrate_treasury.rs | 48 ++++++++++++++++ 15 files changed, 393 insertions(+), 49 deletions(-) create mode 100644 program/src/migrate_miner.rs create mode 100644 program/src/migrate_treasury.rs diff --git a/api/src/instruction.rs b/api/src/instruction.rs index b075952..f4157a7 100644 --- a/api/src/instruction.rs +++ b/api/src/instruction.rs @@ -28,6 +28,8 @@ pub enum OreInstruction { // Seeker ClaimSeeker = 17, + MigrateTreasury = 18, + MigrateMiner = 19, } #[repr(C)] @@ -46,15 +48,11 @@ pub struct Boost {} #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] -pub struct ClaimSOL { - pub amount: [u8; 8], -} +pub struct ClaimSOL {} #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] -pub struct ClaimORE { - pub amount: [u8; 8], -} +pub struct ClaimORE {} #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] @@ -154,6 +152,14 @@ pub struct Checkpoint {} #[derive(Clone, Copy, Debug, Pod, Zeroable)] pub struct Close {} +#[repr(C)] +#[derive(Clone, Copy, Debug, Pod, Zeroable)] +pub struct MigrateTreasury {} + +#[repr(C)] +#[derive(Clone, Copy, Debug, Pod, Zeroable)] +pub struct MigrateMiner {} + instruction!(OreInstruction, Automate); instruction!(OreInstruction, Boost); instruction!(OreInstruction, Close); @@ -172,3 +178,5 @@ instruction!(OreInstruction, Deposit); instruction!(OreInstruction, Withdraw); instruction!(OreInstruction, ClaimYield); instruction!(OreInstruction, ClaimSeeker); +instruction!(OreInstruction, MigrateTreasury); +instruction!(OreInstruction, MigrateMiner); diff --git a/api/src/sdk.rs b/api/src/sdk.rs index e9df587..8da36fd 100644 --- a/api/src/sdk.rs +++ b/api/src/sdk.rs @@ -105,7 +105,7 @@ pub fn initialize(signer: Pubkey) -> Instruction { } } -pub fn claim_sol(signer: Pubkey, amount: u64) -> Instruction { +pub fn claim_sol(signer: Pubkey) -> Instruction { let miner_address = miner_pda(signer).0; Instruction { program_id: crate::ID, @@ -114,16 +114,13 @@ pub fn claim_sol(signer: Pubkey, amount: u64) -> Instruction { AccountMeta::new(miner_address, false), AccountMeta::new_readonly(system_program::ID, false), ], - data: ClaimSOL { - amount: amount.to_le_bytes(), - } - .to_bytes(), + data: ClaimSOL {}.to_bytes(), } } // let [signer_info, miner_info, mint_info, recipient_info, treasury_info, treasury_tokens_info, system_program, token_program, associated_token_program] = -pub fn claim_ore(signer: Pubkey, amount: u64) -> Instruction { +pub fn claim_ore(signer: Pubkey) -> Instruction { let miner_address = miner_pda(signer).0; let treasury_address = treasury_pda().0; let treasury_tokens_address = get_associated_token_address(&treasury_address, &MINT_ADDRESS); @@ -141,10 +138,7 @@ pub fn claim_ore(signer: Pubkey, amount: u64) -> Instruction { AccountMeta::new_readonly(spl_token::ID, false), AccountMeta::new_readonly(spl_associated_token_account::ID, false), ], - data: ClaimORE { - amount: amount.to_le_bytes(), - } - .to_bytes(), + data: ClaimORE {}.to_bytes(), } } @@ -190,6 +184,35 @@ pub fn deploy( } } +pub fn migrate_miner(signer: Pubkey, address: Pubkey) -> Instruction { + let config_address = config_pda().0; + Instruction { + program_id: crate::ID, + accounts: vec![ + AccountMeta::new(signer, true), + AccountMeta::new(config_address, false), + AccountMeta::new(address, false), + AccountMeta::new_readonly(system_program::ID, false), + ], + data: MigrateMiner {}.to_bytes(), + } +} + +pub fn migrate_treasury(signer: Pubkey) -> Instruction { + let config_address = config_pda().0; + let treasury_address = treasury_pda().0; + Instruction { + program_id: crate::ID, + accounts: vec![ + AccountMeta::new(signer, true), + AccountMeta::new(config_address, false), + AccountMeta::new(treasury_address, false), + AccountMeta::new_readonly(system_program::ID, false), + ], + data: MigrateTreasury {}.to_bytes(), + } +} + const POOL_ADDRESS: Pubkey = pubkey!("GgaDTFbqdgjoZz3FP7zrtofGwnRS4E6MCzmmD5Ni1Mxj"); const TOKEN_A_MINT: Pubkey = MINT_ADDRESS; // pubkey!("oreoU2P8bN6jkk3jbaiVxYnG1dCXcYxwhwyK9jSybcp"); const TOKEN_B_MINT: Pubkey = SOL_MINT; //pubkey!("So11111111111111111111111111111111111111112"); diff --git a/api/src/state/miner.rs b/api/src/state/miner.rs index 1c3a587..2489d87 100644 --- a/api/src/state/miner.rs +++ b/api/src/state/miner.rs @@ -1,6 +1,6 @@ use steel::*; -use crate::state::{miner_pda, Treasury}; +use crate::state::{miner_pda, OreAccountOLD, Treasury}; use super::OreAccount; @@ -22,6 +22,52 @@ pub struct Miner { /// The last round that this miner checkpointed. pub checkpoint_id: u64, + /// The last time this miner claimed ORE rewards. + pub last_claim_ore_at: i64, + + /// The last time this miner claimed SOL rewards. + pub last_claim_sol_at: i64, + + /// The rewards factor last time rewards were updated on this miner account. + pub rewards_factor: Numeric, + + /// The amount of SOL this miner can claim. + pub rewards_sol: u64, + + /// The amount of ORE this miner can claim. + pub rewards_ore: u64, + + /// The amount of ORE this miner has earned from claim fees. + pub refined_ore: u64, + + /// The ID of the round this miner last played in. + pub round_id: u64, + + /// The total amount of SOL this miner has mined across all blocks. + pub lifetime_rewards_sol: u64, + + /// The total amount of ORE this miner has mined across all blocks. + pub lifetime_rewards_ore: u64, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] +pub struct MinerOLD { + /// The authority of this miner account. + pub authority: Pubkey, + + /// The miner's prospects in the current round. + pub deployed: [u64; 25], + + /// The cumulative amount of SOL deployed on each square prior to this miner's move. + pub cumulative: [u64; 25], + + /// SOL witheld in reserve to pay for checkpointing. + pub checkpoint_fee: u64, + + /// The last round that this miner checkpointed. + pub checkpoint_id: u64, + /// The amount of SOL this miner can claim. pub rewards_sol: u64, @@ -43,18 +89,52 @@ impl Miner { miner_pda(self.authority) } - pub fn claim_ore(&mut self, amount: u64, treasury: &mut Treasury) -> u64 { - let amount = self.rewards_ore.min(amount); - self.rewards_ore -= amount; - treasury.total_unclaimed -= amount; + pub fn claim_ore(&mut self, clock: &Clock, treasury: &mut Treasury) -> u64 { + self.update_rewards(treasury); + let refined_ore = self.refined_ore; + let rewards_ore = self.rewards_ore; + let mut amount = refined_ore + rewards_ore; + self.refined_ore = 0; + self.rewards_ore = 0; + treasury.total_unclaimed -= rewards_ore; + treasury.total_refined -= refined_ore; + self.last_claim_ore_at = clock.unix_timestamp; + + // Charge a 10% fee and share with miners who haven't claimed yet. + if treasury.total_unclaimed > 0 { + let fee = rewards_ore / 10; + amount -= fee; + treasury.miner_rewards_factor += Numeric::from_fraction(fee, treasury.total_unclaimed); + treasury.total_refined += fee; + self.lifetime_rewards_ore -= fee; + } + amount } - pub fn claim_sol(&mut self, amount: u64) -> u64 { - let amount = self.rewards_sol.min(amount); - self.rewards_sol -= amount; + pub fn claim_sol(&mut self, clock: &Clock) -> u64 { + let amount = self.rewards_sol; + self.rewards_sol = 0; + self.last_claim_sol_at = clock.unix_timestamp; amount } + + pub fn update_rewards(&mut self, treasury: &Treasury) { + // Accumulate rewards, weighted by stake balance. + if treasury.miner_rewards_factor > self.rewards_factor { + let accumulated_rewards = treasury.miner_rewards_factor - self.rewards_factor; + if accumulated_rewards < Numeric::ZERO { + panic!("Accumulated rewards is negative"); + } + let personal_rewards = accumulated_rewards * Numeric::from_u64(self.rewards_ore); + self.refined_ore += personal_rewards.to_u64(); + self.lifetime_rewards_ore += personal_rewards.to_u64(); + } + + // Update this miner account's last seen rewards factor. + self.rewards_factor = treasury.miner_rewards_factor; + } } account!(OreAccount, Miner); +account!(OreAccountOLD, MinerOLD); diff --git a/api/src/state/mod.rs b/api/src/state/mod.rs index d8326c3..6693929 100644 --- a/api/src/state/mod.rs +++ b/api/src/state/mod.rs @@ -35,6 +35,13 @@ pub enum OreAccount { Round = 109, } +#[repr(u8)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)] +pub enum OreAccountOLD { + MinerOLD = 103, + TreasuryOLD = 104, +} + pub fn automation_pda(authority: Pubkey) -> (Pubkey, u8) { Pubkey::find_program_address(&[AUTOMATION, &authority.to_bytes()], &crate::ID) } diff --git a/api/src/state/stake.rs b/api/src/state/stake.rs index f95689f..6704ab7 100644 --- a/api/src/state/stake.rs +++ b/api/src/state/stake.rs @@ -74,8 +74,8 @@ impl Stake { pub fn update_rewards(&mut self, treasury: &Treasury) { // Accumulate rewards, weighted by stake balance. - if treasury.rewards_factor > self.rewards_factor { - let accumulated_rewards = treasury.rewards_factor - self.rewards_factor; + if treasury.stake_rewards_factor > self.rewards_factor { + let accumulated_rewards = treasury.stake_rewards_factor - self.rewards_factor; if accumulated_rewards < Numeric::ZERO { panic!("Accumulated rewards is negative"); } @@ -85,7 +85,7 @@ impl Stake { } // Update this stake account's last seen rewards factor. - self.rewards_factor = treasury.rewards_factor; + self.rewards_factor = treasury.stake_rewards_factor; } } diff --git a/api/src/state/treasury.rs b/api/src/state/treasury.rs index 661a144..3e7eafc 100644 --- a/api/src/state/treasury.rs +++ b/api/src/state/treasury.rs @@ -1,5 +1,7 @@ use steel::*; +use crate::state::OreAccountOLD; + use super::OreAccount; /// Treasury is a singleton account which is the mint authority for the ORE token and the authority of @@ -13,8 +15,36 @@ pub struct Treasury { /// The amount of ORE in the motherlode rewards pool. pub motherlode: u64, + /// The cumulative ORE distributed to miners, divided by the total unclaimed ORE at the time of distribution. + pub miner_rewards_factor: Numeric, + /// The cumulative ORE distributed to stakers, divided by the total stake at the time of distribution. - pub rewards_factor: Numeric, + pub stake_rewards_factor: Numeric, + + /// The current total amount of ORE staking deposits. + pub total_staked: u64, + + /// The current total amount of unclaimed ORE mining rewards. + pub total_unclaimed: u64, + + /// The current total amount of refined ORE mining rewards. + pub total_refined: u64, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] +pub struct TreasuryOLD { + // The amount of SOL collected for buy-bury operations. + pub balance: u64, + + /// The amount of ORE in the motherlode rewards pool. + pub motherlode: u64, + + /// The cumulative ORE distributed to miners, divided by the total unclaimed ORE at the time of distribution. + pub miner_rewards_factor: Numeric, + + /// The cumulative ORE distributed to stakers, divided by the total stake at the time of distribution. + pub stake_rewards_factor: Numeric, /// The current total amount of ORE staking deposits. pub total_staked: u64, @@ -24,3 +54,4 @@ pub struct Treasury { } account!(OreAccount, Treasury); +account!(OreAccountOLD, TreasuryOLD); diff --git a/cli/src/main.rs b/cli/src/main.rs index 120f157..8f57988 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -107,6 +107,12 @@ async fn main() { "participating_miners" => { participating_miners(&rpc).await.unwrap(); } + "migrate_miners" => { + migrate_miners(&rpc, &payer).await.unwrap(); + } + "migrate_treasury" => { + migrate_treasury(&rpc, &payer).await.unwrap(); + } "keys" => { keys().await.unwrap(); } @@ -114,6 +120,45 @@ async fn main() { }; } +async fn migrate_miners( + rpc: &RpcClient, + payer: &solana_sdk::signer::keypair::Keypair, +) -> Result<(), anyhow::Error> { + let miners = get_miners_old(rpc).await?; + let mut ixs = vec![]; + for (i, (address, miner)) in miners.iter().enumerate() { + println!( + "[{}/{}] Migrate miner: {}", + i + 1, + miners.len(), + miner.authority + ); + ixs.push(ore_api::sdk::migrate_miner(payer.pubkey(), *address)); + } + // submit_transaction(rpc, payer, &ixs).await?; + // let ix = ore_api::sdk::migrate_miner(payer.pubkey()); + // submit_transaction(rpc, payer, &[ix]).await?; + + // simulate_transaction_batches(rpc, payer, ixs, 10).await?; + submit_transaction_batches(rpc, payer, ixs, 10).await?; + + Ok(()) +} + +async fn get_miners_old(rpc: &RpcClient) -> Result, anyhow::Error> { + let miners = get_program_accounts(rpc, ore_api::ID, vec![]).await?; + Ok(miners) +} + +async fn migrate_treasury( + rpc: &RpcClient, + payer: &solana_sdk::signer::keypair::Keypair, +) -> Result<(), anyhow::Error> { + let ix = ore_api::sdk::migrate_treasury(payer.pubkey()); + submit_transaction(rpc, payer, &[ix]).await?; + Ok(()) +} + async fn participating_miners(rpc: &RpcClient) -> Result<(), anyhow::Error> { let round_id = std::env::var("ID").expect("Missing ID env var"); let round_id = u64::from_str(&round_id).expect("Invalid ID"); @@ -206,8 +251,8 @@ async fn claim( rpc: &RpcClient, payer: &solana_sdk::signer::keypair::Keypair, ) -> Result<(), anyhow::Error> { - let ix_sol = ore_api::sdk::claim_sol(payer.pubkey(), u64::MAX); - let ix_ore = ore_api::sdk::claim_ore(payer.pubkey(), u64::MAX); + let ix_sol = ore_api::sdk::claim_sol(payer.pubkey()); + let ix_ore = ore_api::sdk::claim_ore(payer.pubkey()); submit_transaction(rpc, payer, &[ix_sol, ix_ore]).await?; Ok(()) } @@ -221,8 +266,8 @@ async fn bury( let amount_u64 = ui_amount_to_amount(amount_f64, TOKEN_DECIMALS); let wrap_ix = ore_api::sdk::wrap(payer.pubkey()); let bury_ix = ore_api::sdk::bury(payer.pubkey(), amount_u64); - submit_transaction(rpc, payer, &[wrap_ix, bury_ix]).await?; - // simulate_transaction(rpc, payer, &[wrap_ix, bury_ix]).await; + // submit_transaction(rpc, payer, &[wrap_ix, bury_ix]).await?; + simulate_transaction(rpc, payer, &[wrap_ix, bury_ix]).await; Ok(()) } @@ -469,8 +514,12 @@ async fn log_treasury(rpc: &RpcClient) -> Result<(), anyhow::Error> { amount_to_ui_amount(treasury.motherlode, TOKEN_DECIMALS) ); println!( - " rewards_factor: {}", - treasury.rewards_factor.to_i80f48().to_string() + " miner_rewards_factor: {}", + treasury.miner_rewards_factor.to_i80f48().to_string() + ); + println!( + " stake_rewards_factor: {}", + treasury.stake_rewards_factor.to_i80f48().to_string() ); println!( " total_staked: {} ORE", @@ -480,6 +529,10 @@ async fn log_treasury(rpc: &RpcClient) -> Result<(), anyhow::Error> { " total_unclaimed: {} ORE", amount_to_ui_amount(treasury.total_unclaimed, TOKEN_DECIMALS) ); + println!( + " total_refined: {} ORE", + amount_to_ui_amount(treasury.total_refined, TOKEN_DECIMALS) + ); Ok(()) } @@ -719,6 +772,38 @@ async fn simulate_transaction( println!("Simulation result: {:?}", x); } +async fn submit_transaction_batches( + rpc: &RpcClient, + payer: &solana_sdk::signer::keypair::Keypair, + mut ixs: Vec, + batch_size: usize, +) -> Result<(), anyhow::Error> { + // Batch and submit the instructions. + while !ixs.is_empty() { + let batch = ixs + .drain(..std::cmp::min(batch_size, ixs.len())) + .collect::>(); + submit_transaction_no_confirm(rpc, payer, &batch).await?; + } + Ok(()) +} + +async fn simulate_transaction_batches( + rpc: &RpcClient, + payer: &solana_sdk::signer::keypair::Keypair, + mut ixs: Vec, + batch_size: usize, +) -> Result<(), anyhow::Error> { + // Batch and submit the instructions. + while !ixs.is_empty() { + let batch = ixs + .drain(..std::cmp::min(batch_size, ixs.len())) + .collect::>(); + simulate_transaction(rpc, payer, &batch).await; + } + Ok(()) +} + async fn submit_transaction( rpc: &RpcClient, payer: &solana_sdk::signer::keypair::Keypair, diff --git a/program/src/bury.rs b/program/src/bury.rs index 6a9d8b2..517e9c2 100644 --- a/program/src/bury.rs +++ b/program/src/bury.rs @@ -96,7 +96,8 @@ pub fn process_bury(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult let mut shared_amount = 0; if treasury.total_staked > 0 { shared_amount = ONE_ORE / 10_000; // TODO: calculate shared amount - treasury.rewards_factor += Numeric::from_fraction(shared_amount, treasury.total_staked); + treasury.stake_rewards_factor += + Numeric::from_fraction(shared_amount, treasury.total_staked); } sol_log(&format!( diff --git a/program/src/claim_ore.rs b/program/src/claim_ore.rs index e9f15e5..862b98f 100644 --- a/program/src/claim_ore.rs +++ b/program/src/claim_ore.rs @@ -4,12 +4,9 @@ use spl_token::amount_to_ui_amount; use steel::*; /// Claims a block reward. -pub fn process_claim_ore(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { - // Parse data. - let args = ClaimORE::try_from_bytes(data)?; - let amount = u64::from_le_bytes(args.amount); - +pub fn process_claim_ore(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult { // Load accounts. + let clock = Clock::get()?; let [signer_info, miner_info, mint_info, recipient_info, treasury_info, treasury_tokens_info, system_program, token_program, associated_token_program] = accounts else { @@ -43,7 +40,7 @@ pub fn process_claim_ore(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramRe } // Normalize amount. - let amount = miner.claim_ore(amount, treasury); + let amount = miner.claim_ore(&clock, treasury); sol_log( &format!( diff --git a/program/src/claim_sol.rs b/program/src/claim_sol.rs index 2076a66..a39b63b 100644 --- a/program/src/claim_sol.rs +++ b/program/src/claim_sol.rs @@ -3,12 +3,9 @@ use solana_program::{log::sol_log, native_token::lamports_to_sol}; use steel::*; /// Claims a block reward. -pub fn process_claim_sol(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { - // Parse data. - let args = ClaimSOL::try_from_bytes(data)?; - let amount = u64::from_le_bytes(args.amount); - +pub fn process_claim_sol(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult { // Load accounts. + let clock = Clock::get()?; let [signer_info, miner_info, system_program] = accounts else { return Err(ProgramError::NotEnoughAccountKeys); }; @@ -19,7 +16,7 @@ pub fn process_claim_sol(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramRe system_program.is_program(&system_program::ID)?; // Normalize amount. - let amount = miner.claim_sol(amount); + let amount = miner.claim_sol(&clock); sol_log(&format!("Claiming {} SOL", lamports_to_sol(amount)).as_str()); diff --git a/program/src/deploy.rs b/program/src/deploy.rs index d813b3b..08ff1bb 100644 --- a/program/src/deploy.rs +++ b/program/src/deploy.rs @@ -23,7 +23,8 @@ pub fn process_deploy(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResul .has_seeds(&[AUTOMATION, &authority_info.key.to_bytes()], &ore_api::ID)?; let board = board_info .as_account_mut::(&ore_api::ID)? - .assert_mut(|b| clock.slot >= b.start_slot && clock.slot < b.end_slot)?; + .assert_mut(|b| clock.slot >= b.start_slot && clock.slot < b.end_slot)? + .assert_mut(|b| b.round_id < 15115)?; let round = round_info .as_account_mut::(&ore_api::ID)? .assert_mut(|r| r.id == board.round_id)?; diff --git a/program/src/deposit.rs b/program/src/deposit.rs index 94012c9..b80fbb3 100644 --- a/program/src/deposit.rs +++ b/program/src/deposit.rs @@ -51,7 +51,7 @@ pub fn process_deposit(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResu stake.last_deposit_at = 0; stake.last_withdraw_at = 0; stake.is_seeker = 0; - stake.rewards_factor = treasury.rewards_factor; + stake.rewards_factor = treasury.stake_rewards_factor; stake.rewards = 0; stake.lifetime_rewards = 0; stake diff --git a/program/src/lib.rs b/program/src/lib.rs index e021fab..b0f7872 100644 --- a/program/src/lib.rs +++ b/program/src/lib.rs @@ -10,6 +10,8 @@ mod close; mod deploy; mod deposit; mod log; +mod migrate_miner; +mod migrate_treasury; mod reset; mod set_admin; mod set_fee_collector; @@ -29,6 +31,8 @@ use close::*; use deploy::*; use deposit::*; use log::*; +use migrate_miner::*; +use migrate_treasury::*; use reset::*; use set_admin::*; use set_fee_collector::*; @@ -71,6 +75,8 @@ pub fn process_instruction( // Seeker OreInstruction::ClaimSeeker => process_claim_seeker(accounts, data)?, + OreInstruction::MigrateTreasury => process_migrate_treasury(accounts, data)?, + OreInstruction::MigrateMiner => process_migrate_miner(accounts, data)?, _ => return Err(ProgramError::InvalidInstructionData), } diff --git a/program/src/migrate_miner.rs b/program/src/migrate_miner.rs new file mode 100644 index 0000000..8d7f48a --- /dev/null +++ b/program/src/migrate_miner.rs @@ -0,0 +1,60 @@ +use ore_api::prelude::*; +use solana_program::rent::Rent; +use steel::*; + +/// Sets the admin. +pub fn process_migrate_miner(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { + // Load accounts. + let [signer_info, config_info, miner_info, system_program] = accounts else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + signer_info.is_signer()?; + let config = config_info + .as_account_mut::(&ore_api::ID)? + .assert_mut_err( + |c| c.admin == *signer_info.key, + OreError::NotAuthorized.into(), + )?; + let miner = miner_info.as_account_mut::(&ore_api::ID)?; + system_program.is_program(&system_program::ID)?; + + // Record old values. + let authority = miner.authority; + let deployed = miner.deployed; + let cumulative = miner.cumulative; + let checkpoint_fee = miner.checkpoint_fee; + let checkpoint_id = miner.checkpoint_id; + let rewards_sol = miner.rewards_sol; + let rewards_ore = miner.rewards_ore; + let round_id = miner.round_id; + let lifetime_rewards_sol = miner.lifetime_rewards_sol; + let lifetime_rewards_ore = miner.lifetime_rewards_ore; + + // Realloc miner. + let new_size = 8 + std::mem::size_of::(); + let old_size = 8 + std::mem::size_of::(); + let new_rent = Rent::get()?.minimum_balance(new_size); + let old_rent = Rent::get()?.minimum_balance(old_size); + let additional_rent = new_rent - old_rent; + miner_info.realloc(new_size, false)?; + miner_info.collect(additional_rent, &signer_info)?; + + // Update miner. + let miner = miner_info.as_account_mut::(&ore_api::ID)?; + miner.authority = authority; + miner.deployed = deployed; + miner.cumulative = cumulative; + miner.checkpoint_fee = checkpoint_fee; + miner.checkpoint_id = checkpoint_id; + miner.rewards_sol = rewards_sol; + miner.rewards_ore = rewards_ore; + miner.round_id = round_id; + miner.lifetime_rewards_sol = lifetime_rewards_sol; + miner.lifetime_rewards_ore = lifetime_rewards_ore; + miner.last_claim_ore_at = 0; + miner.last_claim_sol_at = 0; + miner.rewards_factor = Numeric::ZERO; + miner.refined_ore = 0; + + Ok(()) +} diff --git a/program/src/migrate_treasury.rs b/program/src/migrate_treasury.rs new file mode 100644 index 0000000..ef9a2ee --- /dev/null +++ b/program/src/migrate_treasury.rs @@ -0,0 +1,48 @@ +use ore_api::prelude::*; +use solana_program::rent::Rent; +use steel::*; + +/// Sets the admin. +pub fn process_migrate_treasury(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { + // Load accounts. + let [signer_info, config_info, treasury_info, system_program] = accounts else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + signer_info.is_signer()?; + let config = config_info + .as_account_mut::(&ore_api::ID)? + .assert_mut_err( + |c| c.admin == *signer_info.key, + OreError::NotAuthorized.into(), + )?; + let treasury = treasury_info.as_account_mut::(&ore_api::ID)?; + system_program.is_program(&system_program::ID)?; + + // Record old values. + let balance = treasury.balance; + let motherlode = treasury.motherlode; + let stake_rewards_factor = treasury.stake_rewards_factor; + let total_staked = treasury.total_staked; + let total_unclaimed = treasury.total_unclaimed; + let miner_rewards_factor = treasury.miner_rewards_factor; + + // Realloc treasury. + let new_size = 8 + std::mem::size_of::(); + let old_size = 8 + std::mem::size_of::(); + let new_rent = Rent::get()?.minimum_balance(new_size); + let old_rent = Rent::get()?.minimum_balance(old_size); + let additional_rent = new_rent - old_rent; + treasury_info.realloc(new_size, false)?; + treasury_info.collect(additional_rent, &signer_info)?; + + // Update treasury. + let treasury = treasury_info.as_account_mut::(&ore_api::ID)?; + treasury.balance = balance; + treasury.motherlode = motherlode; + treasury.stake_rewards_factor = stake_rewards_factor; + treasury.total_staked = total_staked; + treasury.total_unclaimed = total_unclaimed; + treasury.miner_rewards_factor = miner_rewards_factor; + + Ok(()) +}