From 1ee9ad86ac313d8df82973a540914dba8653f484 Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Tue, 10 Jun 2025 07:52:45 -0700 Subject: [PATCH] executor fee --- ore/README.md | 2 +- ore/api/src/instruction.rs | 2 ++ ore/api/src/state/permit.rs | 6 +++++ ore/program/src/commit.rs | 31 +++++++++++++++++++++--- ore/program/src/mine.rs | 47 +++++++++++++------------------------ 5 files changed, 53 insertions(+), 35 deletions(-) diff --git a/ore/README.md b/ore/README.md index 93183f6..da5d0b8 100644 --- a/ore/README.md +++ b/ore/README.md @@ -1,6 +1,6 @@ # ORE -**Mine blockspace. Trade hashpower. Win rewards.** +**Mine blockspace. Trade hashpower. Earn rewards.** ## API - [`Consts`](api/src/consts.rs) – Program constants. diff --git a/ore/api/src/instruction.rs b/ore/api/src/instruction.rs index 492f0b5..845f83e 100644 --- a/ore/api/src/instruction.rs +++ b/ore/api/src/instruction.rs @@ -27,6 +27,8 @@ pub struct Close {} #[derive(Clone, Copy, Debug, Pod, Zeroable)] pub struct Commit { pub amount: [u8; 8], + pub executor: [u8; 32], + pub fee: [u8; 8], } #[repr(C)] diff --git a/ore/api/src/state/permit.rs b/ore/api/src/state/permit.rs index 2ae6e9f..5d664b8 100644 --- a/ore/api/src/state/permit.rs +++ b/ore/api/src/state/permit.rs @@ -15,6 +15,12 @@ pub struct Permit { /// The ID of the block this permit is for. pub block_id: u64, + + /// The executor of the permit. + pub executor: Pubkey, + + /// The fee paid to the executor. + pub fee: u64, } impl Permit { diff --git a/ore/program/src/commit.rs b/ore/program/src/commit.rs index 67ebaaf..38356c8 100644 --- a/ore/program/src/commit.rs +++ b/ore/program/src/commit.rs @@ -6,6 +6,8 @@ pub fn process_commit(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResul // Parse data. let args = Commit::try_from_bytes(data)?; let amount = u64::from_le_bytes(args.amount); + let executor = Pubkey::new_from_array(args.executor); + let fee = u64::from_le_bytes(args.fee); // Load accounts. let clock = Clock::get()?; @@ -22,9 +24,6 @@ pub fn process_commit(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResul let market = market_info .as_account::(&ore_api::ID)? .assert(|m| m.id == block.id)?; - miner_info - .as_account::(&ore_api::ID)? - .assert(|m| m.authority == *signer_info.key)?; mint_info.has_address(&market.base.mint)?.as_mint()?; let sender = sender_info .is_writable()? @@ -36,6 +35,28 @@ pub fn process_commit(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResul // Normalize amount. let amount = sender.amount().min(amount); + // Load miner account. + let _miner = if miner_info.data_is_empty() { + create_program_account::( + miner_info, + system_program, + signer_info, + &ore_api::ID, + &[MINER, &signer_info.key.to_bytes()], + )?; + let miner = miner_info.as_account_mut::(&ore_api::ID)?; + miner.authority = *signer_info.key; + miner.block_id = 0; + miner.hash = [0; 32]; + miner.total_hashes = 0; + miner.total_rewards = 0; + miner + } else { + miner_info + .as_account_mut::(&ore_api::ID)? + .assert_mut(|m| m.authority == *signer_info.key)? + }; + // Load permit account. let permit = if permit_info.data_is_empty() { create_program_account::( @@ -57,6 +78,10 @@ pub fn process_commit(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResul .assert_mut(|p| p.block_id == block.id)? }; + // Update executor logic. + permit.executor = executor; + permit.fee = fee; + // Transfer hash tokens. transfer( signer_info, diff --git a/ore/program/src/mine.rs b/ore/program/src/mine.rs index b15c57c..1b7a39a 100644 --- a/ore/program/src/mine.rs +++ b/ore/program/src/mine.rs @@ -11,12 +11,13 @@ pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult // Load accounts. let clock = Clock::get()?; - let [signer_info, block_info, commitment_info, market_info, miner_info, mint_hash_info, mint_ore_info, permit_info, recipient_info, sender_info, treasury_info, system_program, token_program, slot_hashes_sysvar] = + let [signer_info, authority_info, block_info, commitment_info, market_info, miner_info, mint_hash_info, mint_ore_info, permit_info, recipient_info, treasury_info, system_program, token_program, slot_hashes_sysvar] = accounts else { return Err(ProgramError::NotEnoughAccountKeys); }; signer_info.is_signer()?; + authority_info.is_writable()?; let block = block_info .as_account_mut::(&ore_api::ID)? .assert_mut(|b| clock.slot >= b.start_slot)? @@ -29,50 +30,34 @@ pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult .assert(|m| m.id == block.id)?; mint_hash_info.has_address(&market.base.mint)?.as_mint()?; mint_ore_info.has_address(&MINT_ADDRESS)?.as_mint()?; + let miner = miner_info + .as_account_mut::(&ore_api::ID)? + .assert_mut(|m| m.authority == *authority_info.key)?; let permit = permit_info .as_account_mut::(&ore_api::ID)? - .assert_mut(|p| p.authority == *signer_info.key)? - .assert_mut(|p| p.amount >= amount)?; + .assert_mut(|p| p.authority == miner.authority)? + .assert_mut(|p| p.block_id == block.id)? + .assert_mut(|p| p.executor == *signer_info.key || p.executor == Pubkey::default())?; recipient_info .is_writable()? - .as_associated_token_account(signer_info.key, &MINT_ADDRESS)?; - sender_info - .is_writable()? - .as_associated_token_account(signer_info.key, &mint_hash_info.key)? - .assert(|t| t.amount() >= amount)?; + .as_associated_token_account(&miner.authority, &MINT_ADDRESS)?; treasury_info.has_address(&TREASURY_ADDRESS)?; system_program.is_program(&system_program::ID)?; token_program.is_program(&spl_token::ID)?; slot_hashes_sysvar.is_sysvar(&sysvar::slot_hashes::ID)?; - // Load miner account. - let miner = if miner_info.data_is_empty() { - create_program_account::( - miner_info, - system_program, - signer_info, - &ore_api::ID, - &[MINER, &signer_info.key.to_bytes()], - )?; - let miner = miner_info.as_account_mut::(&ore_api::ID)?; - miner.authority = *signer_info.key; - miner.block_id = 0; - miner.hash = [0; 32]; - miner.total_hashes = 0; - miner.total_rewards = 0; - miner - } else { - miner_info - .as_account_mut::(&ore_api::ID)? - .assert_mut(|m| m.authority == *signer_info.key)? - }; - // Reduce permit amount. + let amount = permit.amount.min(amount); permit.amount -= amount; + // Pay executor fee. + if permit.fee > 0 { + permit_info.send(permit.fee * amount, signer_info); + } + // Close permit account, if empty. if permit.amount == 0 { - permit_info.close(signer_info)?; + permit_info.close(authority_info)?; } // Burn hash tokens.