From e942e7ae5bd5cd16d4ba7ffc2ec9af18af8f274b Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Fri, 23 May 2025 17:52:47 -0700 Subject: [PATCH] scaffold bury ix --- Cargo.lock | 13 ++++++++ Cargo.toml | 2 ++ README.md | 3 +- api/src/instruction.rs | 12 +++++-- api/src/sdk.rs | 34 ++++++++++++++++++- program/Cargo.toml | 1 + program/src/bet.rs | 2 +- program/src/bury.rs | 69 +++++++++++++++++++++++++++++++++++++++ program/src/initialize.rs | 15 +++++++-- program/src/lib.rs | 3 ++ program/src/reset.rs | 1 + 11 files changed, 146 insertions(+), 9 deletions(-) create mode 100644 program/src/bury.rs diff --git a/Cargo.lock b/Cargo.lock index c9e68d6..58d201f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1110,6 +1110,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "meteora-pools-sdk" +version = "0.1.1" +source = "git+https://github.com/regolith-labs/meteora-pools-sdk?branch=master#6f5a7eab4a460435591765a7d278f117a946b3bd" +dependencies = [ + "borsh 0.10.4", + "num-derive 0.4.2", + "num-traits", + "solana-program", + "thiserror 2.0.12", +] + [[package]] name = "mpl-token-metadata" version = "5.1.0" @@ -1306,6 +1318,7 @@ name = "ore-program" version = "3.7.0" dependencies = [ "drillx", + "meteora-pools-sdk", "mpl-token-metadata", "ore-api 3.7.0", "ore-boost-api", diff --git a/Cargo.toml b/Cargo.toml index 02bb5ab..ec902ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ bytemuck = "1.14.3" bytemuck_derive = "1.7.0" const-crypto = "0.1.0" drillx = { version = "2.2", features = ["solana"] } +meteora-pools-sdk = "0.1" mpl-token-metadata = "5.1" num_enum = "0.7.2" ore-api = { path = "api" } @@ -34,6 +35,7 @@ thiserror = "1.0.57" tokio = { version = "1.37.0", features = ["full"] } [patch.crates-io] +meteora-pools-sdk = { git = "https://github.com/regolith-labs/meteora-pools-sdk", branch = "master" } [profile.release] overflow-checks = true diff --git a/README.md b/README.md index 96274cd..4756a3c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # ORE -**ORE is a cryptocurrency everyone can mine.** - +**Digital gold, accelerated.** ## API - [`Consts`](api/src/consts.rs) – Program constants. diff --git a/api/src/instruction.rs b/api/src/instruction.rs index cf590b2..c150769 100644 --- a/api/src/instruction.rs +++ b/api/src/instruction.rs @@ -5,9 +5,10 @@ use steel::*; pub enum OreInstruction { // User Bet = 0, - Close = 1, - Payout = 2, - Reset = 3, + Bury = 1, + Close = 2, + Payout = 3, + Reset = 4, // Admin Initialize = 100, @@ -20,6 +21,10 @@ pub struct Bet { pub seed: [u8; 32], } +#[repr(C)] +#[derive(Clone, Copy, Debug, Pod, Zeroable)] +pub struct Bury {} + #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] pub struct Close {} @@ -37,6 +42,7 @@ pub struct Payout {} pub struct Initialize {} instruction!(OreInstruction, Bet); +instruction!(OreInstruction, Bury); instruction!(OreInstruction, Close); instruction!(OreInstruction, Payout); instruction!(OreInstruction, Reset); diff --git a/api/src/sdk.rs b/api/src/sdk.rs index b44e26a..c7d9694 100644 --- a/api/src/sdk.rs +++ b/api/src/sdk.rs @@ -1,3 +1,35 @@ use steel::*; -use crate::{consts::*, instruction::*, state::*}; +use crate::{instruction::*, state::*}; + +pub fn bet( + signer: Pubkey, + mint: Pubkey, + amount: u64, + id: u64, + round: u64, + seed: Option<[u8; 32]>, +) -> Instruction { + let sender = spl_associated_token_account::get_associated_token_address(&signer, &mint); + let block = block_pda().0; + let block_bets = spl_associated_token_account::get_associated_token_address(&signer, &mint); + let wager = wager_pda(round, id).0; + Instruction { + program_id: crate::ID, + accounts: vec![ + AccountMeta::new(signer, true), + AccountMeta::new(block, false), + AccountMeta::new(block_bets, false), + AccountMeta::new(sender, false), + AccountMeta::new(wager, false), + AccountMeta::new_readonly(spl_token::ID, false), + AccountMeta::new_readonly(spl_associated_token_account::ID, false), + AccountMeta::new_readonly(sysvar::slot_hashes::ID, false), + ], + data: Bet { + amount: amount.to_le_bytes(), + seed: seed.unwrap_or([0; 32]), + } + .to_bytes(), + } +} diff --git a/program/Cargo.toml b/program/Cargo.toml index 1bc1bca..4e68d0b 100644 --- a/program/Cargo.toml +++ b/program/Cargo.toml @@ -19,6 +19,7 @@ default = [] [dependencies] drillx.workspace = true +meteora-pools-sdk.workspace = true mpl-token-metadata.workspace = true ore-api.workspace = true ore-boost-api.workspace = true diff --git a/program/src/bet.rs b/program/src/bet.rs index 3b303c3..be6fd5e 100644 --- a/program/src/bet.rs +++ b/program/src/bet.rs @@ -11,7 +11,7 @@ pub fn process_bet(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { // Load accounts. let clock = Clock::get()?; - let [signer_info, block_info, wager_info, block_bets_info, sender_info, system_program, token_program, slot_hashes_sysvar] = + let [signer_info, block_info, block_bets_info, sender_info, wager_info, system_program, token_program, slot_hashes_sysvar] = accounts else { return Err(ProgramError::NotEnoughAccountKeys); diff --git a/program/src/bury.rs b/program/src/bury.rs new file mode 100644 index 0000000..6dcff58 --- /dev/null +++ b/program/src/bury.rs @@ -0,0 +1,69 @@ +use meteora_pools_sdk::instructions::{SwapCpi, SwapCpiAccounts, SwapInstructionArgs}; +use ore_api::prelude::*; +use steel::*; + +pub fn process_bury(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult { + // Load accounts. + let (required_accounts, meteora_accounts) = accounts.split_at(5); + let [signer_info, block_info, block_bets_info, block_ore_info, bet_mint_info, ore_mint_info] = + required_accounts + else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + signer_info.is_signer()?.has_address(&INITIALIZER_ADDRESS)?; + block_info.as_account::(&ore_api::ID)?; + let block_bets = + block_bets_info.as_associated_token_account(block_info.key, bet_mint_info.key)?; + block_ore_info.as_associated_token_account(block_info.key, &MINT_ADDRESS)?; + bet_mint_info.as_mint()?; + ore_mint_info.has_address(&MINT_ADDRESS)?.as_mint()?; + + // Load meteora accounts. + let [pool_info, a_vault_info, b_vault_info, a_token_vault_info, b_token_vault_info, a_vault_lp_mint_info, b_vault_lp_mint_info, a_vault_lp_info, b_vault_lp_info, protocol_token_fee_info, vault_program_info, token_program_info, meteora_pools_program] = + meteora_accounts + else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + meteora_pools_program.is_program(&meteora_pools_sdk::programs::AMM_ID)?; + + // Execute swap. + let swap = SwapCpi::new( + &meteora_pools_program, + SwapCpiAccounts { + pool: pool_info, + user_source_token: block_bets_info, + user_destination_token: block_ore_info, + a_vault: a_vault_info, + b_vault: b_vault_info, + a_token_vault: a_token_vault_info, + b_token_vault: b_token_vault_info, + a_vault_lp_mint: a_vault_lp_mint_info, + b_vault_lp_mint: b_vault_lp_mint_info, + a_vault_lp: a_vault_lp_info, + b_vault_lp: b_vault_lp_info, + protocol_token_fee: protocol_token_fee_info, + user: block_info, + vault_program: vault_program_info, + token_program: token_program_info, + }, + SwapInstructionArgs { + in_amount: block_bets.amount(), + minimum_out_amount: 0, // TODO: Calculate minimum out amount with slippage + }, + ); + let block_bump = block_pda().1; + swap.invoke_signed(&[&[BLOCK, &[block_bump]]])?; + + // Burn (bury) the purchased ORE. + let block_ore = block_ore_info.as_associated_token_account(block_info.key, &MINT_ADDRESS)?; + burn_signed( + block_ore_info, + ore_mint_info, + block_info, + token_program_info, + block_ore.amount(), + &[BLOCK, &[block_bump]], + )?; + + Ok(()) +} diff --git a/program/src/initialize.rs b/program/src/initialize.rs index c541ddd..f74c69a 100644 --- a/program/src/initialize.rs +++ b/program/src/initialize.rs @@ -4,7 +4,7 @@ use steel::*; /// Initialize sets up the ORE program to begin mining. pub fn process_initialize(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult { // Load accounts. - let [signer_info, block_info, block_bets_info, sol_mint_info, system_program, token_program, associated_token_program] = + let [signer_info, block_info, block_bets_info, block_ore_info, ore_mint_info, sol_mint_info, system_program, token_program, associated_token_program] = accounts else { return Err(ProgramError::NotEnoughAccountKeys); @@ -15,6 +15,8 @@ pub fn process_initialize(accounts: &[AccountInfo<'_>], _data: &[u8]) -> Program .is_writable()? .has_seeds(&[BLOCK], &ore_api::ID)?; block_bets_info.is_empty()?.is_writable()?; + block_ore_info.is_empty()?.is_writable()?; + ore_mint_info.has_address(&MINT_ADDRESS)?.as_mint()?; sol_mint_info .has_address(&spl_token::native_mint::ID)? .as_mint()?; @@ -41,7 +43,7 @@ pub fn process_initialize(accounts: &[AccountInfo<'_>], _data: &[u8]) -> Program block.reward = 0; block.noise = [0; 32]; - // Initialize treasury token account. + // Initialize block token accounts. create_associated_token_account( signer_info, block_info, @@ -51,6 +53,15 @@ pub fn process_initialize(accounts: &[AccountInfo<'_>], _data: &[u8]) -> Program token_program, associated_token_program, )?; + create_associated_token_account( + signer_info, + block_info, + block_ore_info, + ore_mint_info, + system_program, + token_program, + associated_token_program, + )?; Ok(()) } diff --git a/program/src/lib.rs b/program/src/lib.rs index 4a594ae..146316f 100644 --- a/program/src/lib.rs +++ b/program/src/lib.rs @@ -1,10 +1,12 @@ mod bet; +mod bury; mod close; mod initialize; mod payout; mod reset; use bet::*; +use bury::*; use close::*; use initialize::*; use payout::*; @@ -22,6 +24,7 @@ pub fn process_instruction( match ix { OreInstruction::Bet => process_bet(accounts, data)?, + OreInstruction::Bury => process_bury(accounts, data)?, OreInstruction::Close => process_close(accounts, data)?, OreInstruction::Reset => process_reset(accounts, data)?, OreInstruction::Initialize => process_initialize(accounts, data)?, diff --git a/program/src/reset.rs b/program/src/reset.rs index b5a67e0..18401c4 100644 --- a/program/src/reset.rs +++ b/program/src/reset.rs @@ -26,6 +26,7 @@ pub fn process_reset(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResul token_program.is_program(&spl_token::ID)?; slot_hashes_sysvar.is_sysvar(&sysvar::slot_hashes::ID)?; + // Load boost accounts. let [boost_config_info, boost_proof_info] = boost_accounts else { return Err(ProgramError::NotEnoughAccountKeys); };