From 4bf9fa8d7215d48b0cb7726ac0529873ba68088f Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Mon, 29 Sep 2025 09:43:02 -0700 Subject: [PATCH] stake --- Cargo.lock | 1 + api/Cargo.toml | 1 + api/src/instruction.rs | 6 --- api/src/sdk.rs | 25 ++++------- cli/src/main.rs | 81 +++++++++++++++++++++++++++--------- program/src/claim_yield.rs | 7 ---- program/src/deposit.rs | 3 ++ program/src/lib.rs | 3 -- program/src/migrate_miner.rs | 26 ------------ program/src/whitelist.rs | 7 +++- 10 files changed, 80 insertions(+), 80 deletions(-) delete mode 100644 program/src/migrate_miner.rs diff --git a/Cargo.lock b/Cargo.lock index 4808255..b7b18ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2445,6 +2445,7 @@ dependencies = [ "solana-program", "spl-associated-token-account", "spl-token 4.0.2", + "spl-token-2022 7.0.0", "steel", "thiserror 1.0.69", ] diff --git a/api/Cargo.toml b/api/Cargo.toml index e50c4a4..9747183 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -20,6 +20,7 @@ num_enum.workspace = true serde.workspace = true solana-program.workspace = true spl-token.workspace = true +spl-token-2022.workspace = true spl-associated-token-account.workspace = true steel.workspace = true thiserror.workspace = true diff --git a/api/src/instruction.rs b/api/src/instruction.rs index 604f22a..06a6cb4 100644 --- a/api/src/instruction.rs +++ b/api/src/instruction.rs @@ -26,7 +26,6 @@ pub enum OreInstruction { // Seeker ClaimSeeker = 15, - MigrateMiner = 16, } #[repr(C)] @@ -145,10 +144,6 @@ pub struct ClaimYield { #[derive(Clone, Copy, Debug, Pod, Zeroable)] pub struct ClaimSeeker {} -#[repr(C)] -#[derive(Clone, Copy, Debug, Pod, Zeroable)] -pub struct MigrateMiner {} - instruction!(OreInstruction, Automate); instruction!(OreInstruction, Boost); instruction!(OreInstruction, ClaimSOL); @@ -165,4 +160,3 @@ instruction!(OreInstruction, Deposit); instruction!(OreInstruction, Withdraw); instruction!(OreInstruction, ClaimYield); instruction!(OreInstruction, ClaimSeeker); -instruction!(OreInstruction, MigrateMiner); diff --git a/api/src/sdk.rs b/api/src/sdk.rs index e981963..b863f13 100644 --- a/api/src/sdk.rs +++ b/api/src/sdk.rs @@ -1,6 +1,8 @@ use solana_program::pubkey; use solana_program::pubkey::Pubkey; -use spl_associated_token_account::get_associated_token_address; +use spl_associated_token_account::{ + get_associated_token_address, get_associated_token_address_with_program_id, +}; use steel::*; use crate::{ @@ -344,32 +346,23 @@ pub fn set_fee_collector(signer: Pubkey, fee_collector: Pubkey) -> Instruction { } } +// let [signer_info, mint_info, seeker_info, stake_info, token_account_info, system_program] = + pub fn claim_seeker(signer: Pubkey, mint: Pubkey) -> Instruction { let seeker_address = seeker_pda(mint).0; - let token_account_address = get_associated_token_address(&signer, &mint); + let stake_address = stake_pda(signer).0; + let token_account_address = + get_associated_token_address_with_program_id(&signer, &mint, &spl_token_2022::ID); Instruction { program_id: crate::ID, accounts: vec![ AccountMeta::new(signer, true), AccountMeta::new_readonly(mint, false), AccountMeta::new(seeker_address, false), + AccountMeta::new(stake_address, false), AccountMeta::new(token_account_address, false), AccountMeta::new_readonly(system_program::ID, false), ], data: ClaimSeeker {}.to_bytes(), } } - -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(), - } -} diff --git a/cli/src/main.rs b/cli/src/main.rs index a5d1e39..2f3e290 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -74,14 +74,17 @@ async fn main() { "deploy" => { deploy(&rpc, &payer).await.unwrap(); } + "stake" => { + log_stake(&rpc, &payer).await.unwrap(); + } "deploy_all" => { deploy_all(&rpc, &payer).await.unwrap(); } "square" => { log_square(&rpc).await.unwrap(); } - "migrate_miners" => { - migrate_miners(&rpc, &payer).await.unwrap(); + "seeker" => { + log_seeker(&rpc).await.unwrap(); } "test_kick" => { test_kick(&rpc).await.unwrap(); @@ -105,24 +108,6 @@ async fn main() { }; } -async fn migrate_miners( - rpc: &RpcClient, - payer: &solana_sdk::signer::keypair::Keypair, -) -> Result<(), anyhow::Error> { - let miners = get_miners(rpc).await?; - for (i, (address, miner)) in miners.iter().enumerate() { - println!( - "[{}/{}] Migrating miner {}", - i + 1, - miners.len(), - miner.authority - ); - let ix = ore_api::sdk::migrate_miner(payer.pubkey(), *address); - submit_transaction(rpc, payer, &[ix]).await?; - } - Ok(()) -} - // Dmy2fqxpkUocwvkALMDwfCRFeYfkdGqgB5PLfmZW5ASR // Az9Xia5f6EXU9MGHuuMCKyHMy3MfNnsoyTbh7HTuFw5G // 5muLAbcjsAMcP8438KPfo2Jqw2vgAtuSDvMFNWb6Bexi @@ -175,6 +160,32 @@ async fn test_kick(rpc: &RpcClient) -> Result<(), anyhow::Error> { Ok(()) } +async fn log_stake( + rpc: &RpcClient, + payer: &solana_sdk::signer::keypair::Keypair, +) -> Result<(), anyhow::Error> { + let authority = std::env::var("AUTHORITY").unwrap_or(payer.pubkey().to_string()); + let authority = Pubkey::from_str(&authority).expect("Invalid AUTHORITY"); + let staker_address = ore_api::state::stake_pda(authority).0; + let stake = get_stake(rpc, authority).await?; + println!("Stake"); + println!(" address: {}", staker_address); + println!(" authority: {}", authority); + println!(" balance: {}", stake.balance); + println!(" last_claim_at: {}", stake.last_claim_at); + println!(" last_deposit_at: {}", stake.last_deposit_at); + println!(" last_withdraw_at: {}", stake.last_withdraw_at); + println!( + " rewards_factor: {}", + stake.rewards_factor.to_i80f48().to_string() + ); + println!(" rewards: {}", stake.rewards); + println!(" lifetime_rewards: {}", stake.lifetime_rewards); + println!(" is_seeker: {}", stake.is_seeker); + + Ok(()) +} + async fn ata( rpc: &RpcClient, payer: &solana_sdk::signer::keypair::Keypair, @@ -397,6 +408,11 @@ async fn log_treasury(rpc: &RpcClient) -> Result<(), anyhow::Error> { " motherlode: {} ORE", amount_to_ui_amount(treasury.motherlode, TOKEN_DECIMALS) ); + println!( + " rewards_factor: {}", + treasury.rewards_factor.to_i80f48().to_string() + ); + println!(" total_staked: {}", treasury.total_staked); Ok(()) } @@ -432,6 +448,17 @@ async fn log_miner( Ok(()) } +async fn log_seeker(rpc: &RpcClient) -> Result<(), anyhow::Error> { + let mint = std::env::var("MINT").unwrap(); + let mint = Pubkey::from_str(&mint).expect("Invalid MINT"); + let seeker = get_seeker(&rpc, mint).await?; + let seeker_address = ore_api::state::seeker_pda(mint).0; + println!("Seeker"); + println!(" address: {}", seeker_address); + println!(" mint: {}", seeker.mint); + Ok(()) +} + async fn log_clock(rpc: &RpcClient) -> Result<(), anyhow::Error> { let clock = get_clock(&rpc).await?; println!("Clock"); @@ -551,6 +578,20 @@ async fn get_clock(rpc: &RpcClient) -> Result { Ok(clock) } +async fn get_seeker(rpc: &RpcClient, mint: Pubkey) -> Result { + let seeker_pda = ore_api::state::seeker_pda(mint); + let account = rpc.get_account(&seeker_pda.0).await?; + let seeker = Seeker::try_from_bytes(&account.data)?; + Ok(*seeker) +} + +async fn get_stake(rpc: &RpcClient, authority: Pubkey) -> Result { + let stake_pda = ore_api::state::stake_pda(authority); + let account = rpc.get_account(&stake_pda.0).await?; + let stake = Stake::try_from_bytes(&account.data)?; + Ok(*stake) +} + #[allow(dead_code)] async fn get_miners(rpc: &RpcClient) -> Result, anyhow::Error> { let miners = get_program_accounts::(rpc, ore_api::ID, vec![]).await?; diff --git a/program/src/claim_yield.rs b/program/src/claim_yield.rs index 0ebf805..2b1a3a0 100644 --- a/program/src/claim_yield.rs +++ b/program/src/claim_yield.rs @@ -3,8 +3,6 @@ use solana_program::log::sol_log; use spl_token::amount_to_ui_amount; use steel::*; -use crate::AUTHORIZED_ACCOUNTS; - /// Claims yield from the staking contract. pub fn process_claim_yield(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { // Parse data. @@ -34,11 +32,6 @@ pub fn process_claim_yield(accounts: &[AccountInfo<'_>], data: &[u8]) -> Program token_program.is_program(&spl_token::ID)?; associated_token_program.is_program(&spl_associated_token_account::ID)?; - // Check whitelist - if !AUTHORIZED_ACCOUNTS.contains(&signer_info.key) { - return Err(trace("Not authorized", OreError::NotAuthorized.into())); - } - // Open recipient token account. if recipient_info.data_is_empty() { create_associated_token_account( diff --git a/program/src/deposit.rs b/program/src/deposit.rs index 1cc8e5e..c7cfb25 100644 --- a/program/src/deposit.rs +++ b/program/src/deposit.rs @@ -61,6 +61,9 @@ pub fn process_deposit(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResu .assert_mut(|s| s.authority == *signer_info.key)? }; + // Only allow deposits from seekers. + assert!(stake.is_seeker == 1, "Only seekers can deposit stake"); + // Deposit into stake account. let amount = stake.deposit(amount, &clock, treasury, &sender); diff --git a/program/src/lib.rs b/program/src/lib.rs index a7b6557..6db5e22 100644 --- a/program/src/lib.rs +++ b/program/src/lib.rs @@ -9,7 +9,6 @@ mod deploy; mod deposit; mod initialize; mod log; -mod migrate_miner; mod reset; mod set_admin; mod set_fee_collector; @@ -28,7 +27,6 @@ use deploy::*; use deposit::*; use initialize::*; use log::*; -use migrate_miner::*; use reset::*; use set_admin::*; use set_fee_collector::*; @@ -70,7 +68,6 @@ pub fn process_instruction( // Seeker OreInstruction::ClaimSeeker => process_claim_seeker(accounts, data)?, - OreInstruction::MigrateMiner => process_migrate_miner(accounts, data)?, } Ok(()) diff --git a/program/src/migrate_miner.rs b/program/src/migrate_miner.rs deleted file mode 100644 index 58e6b72..0000000 --- a/program/src/migrate_miner.rs +++ /dev/null @@ -1,26 +0,0 @@ -use ore_api::prelude::*; -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 miner = miner_info.as_account_mut::(&ore_api::ID)?; - let config = config_info - .as_account_mut::(&ore_api::ID)? - .assert_mut_err( - |c| c.admin == *signer_info.key, - OreError::NotAuthorized.into(), - )?; - system_program.is_program(&system_program::ID)?; - - // Set seeker activation flag. - config.is_seeker_activation_enabled = 0; - - // No op - - Ok(()) -} diff --git a/program/src/whitelist.rs b/program/src/whitelist.rs index 9a6b2f9..1b0893c 100644 --- a/program/src/whitelist.rs +++ b/program/src/whitelist.rs @@ -1,5 +1,8 @@ use solana_program::pubkey; use steel::*; -pub const AUTHORIZED_ACCOUNTS: [Pubkey; 1] = - [pubkey!("pqspJ298ryBjazPAr95J9sULCVpZe3HbZTWkbC1zrkS")]; +pub const AUTHORIZED_ACCOUNTS: [Pubkey; 3] = [ + pubkey!("pqspJ298ryBjazPAr95J9sULCVpZe3HbZTWkbC1zrkS"), + pubkey!("By5JFFueXCqeqLk5MzR8ZSwFxASz3SKWX2TVfT1LTFbX"), + pubkey!("5Nb2ibzu4bWrwis2vNVD4mJprt6KTchzW6wgbVWM2PkY"), +];