diff --git a/api/src/consts.rs b/api/src/consts.rs index 4341a97..35f6cb9 100644 --- a/api/src/consts.rs +++ b/api/src/consts.rs @@ -35,9 +35,6 @@ pub const MINER: &[u8] = b"miner"; /// The seed of the mint account PDA. pub const MINT: &[u8] = b"mint"; -/// The seed of the log authority PDA. -// pub const LOG: &[u8] = b"log"; - /// The seed of the permit account PDA. pub const PERMIT: &[u8] = b"permit"; @@ -84,6 +81,3 @@ pub const NUGGET_DIFFICULTY: u64 = 10; // The fee to open a block. // pub const OPEN_FEE: u64 = ONE_ORE / 100; - -// The reward rate per satisfying hash (0.002048 ORE). -// pub const REWARD_RATE: u64 = 204_800_000; diff --git a/api/src/event.rs b/api/src/event.rs index 976d8e7..9f83b48 100644 --- a/api/src/event.rs +++ b/api/src/event.rs @@ -1,16 +1,11 @@ use steel::*; -use crate::state::{RewardConfig, SwapDirection}; +use crate::state::SwapDirection; pub enum OreEvent { - Commit = 0, - Deposit = 1, - Mine = 2, - Open = 3, - Reward = 4, - Swap = 5, - Uncommit = 6, - Withdraw = 7, + Mine = 1, + Reward = 2, + Swap = 3, } #[repr(C)] @@ -112,186 +107,6 @@ pub struct MineEvent { pub ts: i64, } -#[repr(u8)] -#[derive(Clone, Copy, Debug, Eq, PartialEq, TryFromPrimitive)] -pub enum RewardsType { - Nugget = 0, - Lode = 1, -} - -#[repr(C)] -#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] -pub struct OpenEvent { - /// The event discriminator. - pub disc: u64, - - /// The signer of the open transaction. - pub signer: Pubkey, - - /// The id of the block. - pub id: u64, - - /// The start slot of the block. - pub start_slot: u64, - - /// The base liquidity in the market. - pub liquidity_base: u64, - - /// The quote liquidity in the market. - pub liquidity_quote: u64, - - /// The reward configuration. - pub reward_config: RewardConfig, - - /// The timestamp of the event. - pub ts: i64, -} - -#[repr(C)] -#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] -pub struct CloseEvent { - /// The authority of the close transaction. - pub authority: Pubkey, - - /// The id of the block. - pub id: u64, - - /// The amount of base (hashpower) liquidity burned. - pub burned_base: u64, - - /// The amount of quote (ORE) liquidity burned. - pub burned_quote: u64, - - /// The timestamp of the event. - pub ts: i64, -} - -#[repr(C)] -#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] -pub struct CommitEvent { - /// The event discriminator. - pub disc: u64, - - /// The amount of hashpower committed. - pub amount: u64, - - /// The authority of the commit transaction. - pub authority: Pubkey, - - /// The id of the block. - pub block_id: u64, - - /// The total amount of hashpower committed to the block. - pub block_commitment: u64, - - /// The total amount of hashpower this miner has committed to the block. - pub permit_commitment: u64, - - /// The fee paid per hash. - pub fee: u64, - - /// The timestamp of the event. - pub ts: i64, -} - -#[repr(C)] -#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] -pub struct UncommitEvent { - /// The event discriminator. - pub disc: u64, - - /// The amount of hashpower committed. - pub amount: u64, - - /// The authority of the commit transaction. - pub authority: Pubkey, - - /// The id of the block. - pub block_id: u64, - - /// The total amount of hashpower committed to the block. - pub block_commitment: u64, - - /// The total amount of hashpower this miner has committed to the block. - pub permit_commitment: u64, - - /// The fee paid per hash. - pub fee: u64, - - /// The timestamp of the event. - pub ts: i64, -} - -#[repr(C)] -#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] -pub struct DepositEvent { - /// The event discriminator. - pub disc: u64, - - /// The amount of ORE collateral deposited. - pub amount: u64, - - /// The authority of the commit transaction. - pub authority: Pubkey, - - /// The id of the block. - pub block_id: u64, - - /// The total amount of ORE this user has deposited as collateral. - pub collateral: u64, - - /// The timestamp of the event. - pub ts: i64, -} - -#[repr(C)] -#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] -pub struct WithdrawEvent { - /// The event discriminator. - pub disc: u64, - - /// The amount of ORE collateral withdrawn. - pub amount: u64, - - /// The authority of the commit transaction. - pub authority: Pubkey, - - /// The id of the block. - pub block_id: u64, - - /// The total amount of ORE this user has deposited as collateral. - pub collateral: u64, - - /// The timestamp of the event. - pub ts: i64, -} - event!(SwapEvent); event!(RewardEvent); -event!(OpenEvent); -event!(CommitEvent); -event!(DepositEvent); -event!(WithdrawEvent); -event!(UncommitEvent); event!(MineEvent); -event!(CloseEvent); - -#[cfg(test)] -mod tests { - use super::*; - use base64::{prelude::BASE64_STANDARD, Engine}; - - #[test] - fn test_parse_commit_event() { - // Create sample return data - let data = "BQAAAAAAAAB9607Qp9I2VxNo2rSPHAz/tR2pJzGu9om7qHP71TpKqciMAwAAAAAAAAAAAAAAAAA2CwUAAAAAAADodkgXAAAAAAAAAAAAAAAAAAAAAAAAADYLBQAAAAAAAB7cDBcAAAAAypo7AAAAAMMQW2gAAAAA"; - let bytes = BASE64_STANDARD.decode(data).unwrap(); - - // Parse into CommitEvent - let event: &SwapEvent = bytemuck::try_from_bytes(&bytes).unwrap(); - - // Verify fields - println!("{:?}", event); - assert!(false); - } -} diff --git a/api/src/instruction.rs b/api/src/instruction.rs index f78a90a..7d9a0ef 100644 --- a/api/src/instruction.rs +++ b/api/src/instruction.rs @@ -4,21 +4,15 @@ use steel::*; #[derive(Clone, Copy, Debug, Eq, PartialEq, TryFromPrimitive)] pub enum OreInstruction { // User - Open = 0, - Close = 1, - Commit = 2, - Deposit = 3, - Log = 4, - Mine = 5, - Swap = 6, - Uncommit = 7, - Withdraw = 8, + Log = 1, + Mine = 2, + Swap = 3, + Initialize = 4, // Admin SetAdmin = 9, - SetBlockLimit = 10, - SetFeeCollector = 11, - SetFeeRate = 12, + SetFeeCollector = 10, + SetFeeRate = 11, } #[repr(C)] @@ -42,9 +36,7 @@ pub struct Commit { #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] -pub struct Deposit { - pub amount: [u8; 8], -} +pub struct Initialize {} #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] @@ -72,24 +64,12 @@ pub struct Uncommit { pub amount: [u8; 8], } -#[repr(C)] -#[derive(Clone, Copy, Debug, Pod, Zeroable)] -pub struct Withdraw { - pub amount: [u8; 8], -} - #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] pub struct SetAdmin { pub admin: [u8; 32], } -#[repr(C)] -#[derive(Clone, Copy, Debug, Pod, Zeroable)] -pub struct SetBlockLimit { - pub block_limit: [u8; 8], -} - #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] pub struct SetFeeCollector { @@ -102,16 +82,10 @@ pub struct SetFeeRate { pub fee_rate: [u8; 8], } -instruction!(OreInstruction, Open); -instruction!(OreInstruction, Close); -instruction!(OreInstruction, Commit); -instruction!(OreInstruction, Deposit); instruction!(OreInstruction, Log); instruction!(OreInstruction, Mine); instruction!(OreInstruction, Swap); -instruction!(OreInstruction, Uncommit); -instruction!(OreInstruction, Withdraw); +instruction!(OreInstruction, Initialize); instruction!(OreInstruction, SetAdmin); -instruction!(OreInstruction, SetBlockLimit); instruction!(OreInstruction, SetFeeCollector); instruction!(OreInstruction, SetFeeRate); diff --git a/api/src/sdk.rs b/api/src/sdk.rs index 204b014..cc2a5ec 100644 --- a/api/src/sdk.rs +++ b/api/src/sdk.rs @@ -7,90 +7,6 @@ use crate::{ state::*, }; -pub fn open(signer: Pubkey, id: u64) -> Instruction { - let block_adddress = block_pda(id).0; - let config_address = config_pda().0; - let market_address = market_pda(id).0; - let base_mint_address = mint_pda(id).0; - let collateral_address = collateral_pda(id).0; - let commitment_address = commitment_pda(id).0; - let sender_address = get_associated_token_address(&signer, &MINT_ADDRESS); - let vault_base_address = vault_base_pda(id).0; - let vault_quote_address = vault_quote_pda(id).0; - Instruction { - program_id: crate::ID, - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(block_adddress, false), - AccountMeta::new(config_address, false), - AccountMeta::new(collateral_address, false), - AccountMeta::new(commitment_address, false), - AccountMeta::new(market_address, false), - AccountMeta::new(base_mint_address, false), - AccountMeta::new(MINT_ADDRESS, false), - AccountMeta::new(sender_address, false), - AccountMeta::new(TREASURY_ADDRESS, false), - AccountMeta::new(vault_base_address, false), - AccountMeta::new(vault_quote_address, false), - AccountMeta::new_readonly(system_program::ID, false), - AccountMeta::new_readonly(spl_token::ID, false), - AccountMeta::new_readonly(spl_associated_token_account::ID, false), - AccountMeta::new_readonly(crate::ID, false), - AccountMeta::new_readonly(sysvar::rent::ID, false), - ], - data: Open { - id: id.to_le_bytes(), - } - .to_bytes(), - } -} - -// let [signer_info, block_info, config_info, collateral_info, commitment_info, fee_collector_info, market_info, miner_info, mint_base_info, mint_quote_info, opener_info, recipient_info, treasury_info, vault_base_info, vault_quote_info, system_program, token_program, ore_program] = - -pub fn close( - signer: Pubkey, - fee_collector: Pubkey, - opener: Pubkey, - load_authority: Pubkey, - id: u64, -) -> Instruction { - let block_adddress = block_pda(id).0; - let config_address = config_pda().0; - let collateral_address = collateral_pda(id).0; - let commitment_address = commitment_pda(id).0; - let fee_collector_address = get_associated_token_address(&fee_collector, &MINT_ADDRESS); - let market_address = market_pda(id).0; - let base_mint_address = mint_pda(id).0; - let vault_base = vault_base_pda(id).0; - let vault_quote = vault_quote_pda(id).0; - let miner_address = miner_pda(load_authority).0; - let recipient = get_associated_token_address(&load_authority, &MINT_ADDRESS); - Instruction { - program_id: crate::ID, - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(block_adddress, false), - AccountMeta::new(config_address, false), - AccountMeta::new(collateral_address, false), - AccountMeta::new(commitment_address, false), - AccountMeta::new(fee_collector_address, false), - AccountMeta::new(market_address, false), - AccountMeta::new(miner_address, false), - AccountMeta::new(base_mint_address, false), - AccountMeta::new(MINT_ADDRESS, false), - AccountMeta::new(opener, false), - AccountMeta::new(recipient, false), - AccountMeta::new(TREASURY_ADDRESS, false), - AccountMeta::new(vault_base, false), - AccountMeta::new(vault_quote, false), - AccountMeta::new_readonly(system_program::ID, false), - AccountMeta::new_readonly(spl_token::ID, false), - AccountMeta::new_readonly(crate::ID, false), - ], - data: Close {}.to_bytes(), - } -} - pub fn log(signer: Pubkey, block_id: u64, msg: &[u8]) -> Instruction { let mut data = Log { block_id: block_id.to_le_bytes(), @@ -119,11 +35,8 @@ pub fn program_log( pub fn mine(signer: Pubkey, authority: Pubkey, id: u64, amount: u64) -> Instruction { let block_adddress = block_pda(id).0; - let commitment_address = commitment_pda(id).0; - let market_address = market_pda(id).0; - let base_mint_address = mint_pda(id).0; + let market_address = market_pda().0; let miner_address = miner_pda(authority).0; - let permit_address = permit_pda(authority, id).0; let recipient = get_associated_token_address(&authority, &MINT_ADDRESS); Instruction { program_id: crate::ID, @@ -131,12 +44,9 @@ pub fn mine(signer: Pubkey, authority: Pubkey, id: u64, amount: u64) -> Instruct AccountMeta::new(signer, true), AccountMeta::new(authority, false), AccountMeta::new(block_adddress, false), - AccountMeta::new(commitment_address, false), AccountMeta::new(market_address, false), AccountMeta::new(miner_address, false), - AccountMeta::new(base_mint_address, false), AccountMeta::new(MINT_ADDRESS, false), - AccountMeta::new(permit_address, false), AccountMeta::new(recipient, false), AccountMeta::new(TREASURY_ADDRESS, false), AccountMeta::new_readonly(system_program::ID, false), @@ -151,126 +61,6 @@ pub fn mine(signer: Pubkey, authority: Pubkey, id: u64, amount: u64) -> Instruct } } -pub fn commit( - signer: Pubkey, - amount: u64, - executor: Pubkey, - fee: u64, - id: u64, - seed: [u8; 32], -) -> Instruction { - let block_adddress = block_pda(id).0; - let market_address = market_pda(id).0; - let base_mint_address = mint_pda(id).0; - let miner_address = miner_pda(signer).0; - let permit_address = permit_pda(signer, id).0; - let commitment_address = commitment_pda(id).0; - let sender_address = get_associated_token_address(&signer, &base_mint_address); - Instruction { - program_id: crate::ID, - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(block_adddress, false), - AccountMeta::new(commitment_address, false), - AccountMeta::new(market_address, false), - AccountMeta::new(miner_address, false), - AccountMeta::new(base_mint_address, false), - AccountMeta::new(permit_address, false), - AccountMeta::new(sender_address, false), - AccountMeta::new_readonly(system_program::ID, false), - AccountMeta::new_readonly(spl_token::ID, false), - AccountMeta::new_readonly(crate::ID, false), - ], - data: Commit { - amount: amount.to_le_bytes(), - executor: executor.to_bytes(), - fee: fee.to_le_bytes(), - seed: seed, - } - .to_bytes(), - } -} - -pub fn uncommit(signer: Pubkey, amount: u64, id: u64) -> Instruction { - let block_adddress = block_pda(id).0; - let market_address = market_pda(id).0; - let base_mint_address = mint_pda(id).0; - let miner_address = miner_pda(signer).0; - let permit_address = permit_pda(signer, id).0; - let commitment_address = commitment_pda(id).0; - let recipient_address = get_associated_token_address(&signer, &MINT_ADDRESS); - Instruction { - program_id: crate::ID, - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(block_adddress, false), - AccountMeta::new(commitment_address, false), - AccountMeta::new(market_address, false), - AccountMeta::new(miner_address, false), - AccountMeta::new(base_mint_address, false), - AccountMeta::new(permit_address, false), - AccountMeta::new(recipient_address, false), - AccountMeta::new_readonly(system_program::ID, false), - AccountMeta::new_readonly(spl_token::ID, false), - AccountMeta::new_readonly(crate::ID, false), - ], - data: Uncommit { - amount: amount.to_le_bytes(), - } - .to_bytes(), - } -} - -pub fn deposit(signer: Pubkey, id: u64, amount: u64) -> Instruction { - let block_adddress = block_pda(id).0; - let collateral_address = collateral_pda(id).0; - let stake_address = stake_pda(signer, id).0; - let sender = get_associated_token_address(&signer, &MINT_ADDRESS); - Instruction { - program_id: crate::ID, - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(block_adddress, false), - AccountMeta::new(collateral_address, false), - AccountMeta::new(MINT_ADDRESS, false), - AccountMeta::new(sender, false), - AccountMeta::new(stake_address, false), - AccountMeta::new_readonly(system_program::ID, false), - AccountMeta::new_readonly(spl_token::ID, false), - AccountMeta::new_readonly(crate::ID, false), - ], - data: Deposit { - amount: amount.to_le_bytes(), - } - .to_bytes(), - } -} - -pub fn withdraw(signer: Pubkey, id: u64, amount: u64) -> Instruction { - let block_adddress = block_pda(id).0; - let collateral_address = collateral_pda(id).0; - let stake_address = stake_pda(signer, id).0; - let recipient_address = get_associated_token_address(&signer, &MINT_ADDRESS); - Instruction { - program_id: crate::ID, - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(block_adddress, false), - AccountMeta::new(collateral_address, false), - AccountMeta::new(MINT_ADDRESS, false), - AccountMeta::new(recipient_address, false), - AccountMeta::new(stake_address, false), - AccountMeta::new_readonly(system_program::ID, false), - AccountMeta::new_readonly(spl_token::ID, false), - AccountMeta::new_readonly(crate::ID, false), - ], - data: Withdraw { - amount: amount.to_le_bytes(), - } - .to_bytes(), - } -} - pub fn swap( signer: Pubkey, id: u64, @@ -279,27 +69,18 @@ pub fn swap( precision: SwapPrecision, ) -> Instruction { let block_adddress = block_pda(id).0; - let market_address = market_pda(id).0; - let base_mint_address = mint_pda(id).0; - let stake_address = stake_pda(signer, id).0; - let tokens_base_address = get_associated_token_address(&signer, &base_mint_address); + let market_address = market_pda().0; let tokens_quote_address = get_associated_token_address(&signer, &MINT_ADDRESS); - let vault_base_address = vault_base_pda(id).0; - let vault_quote_address = vault_quote_pda(id).0; + let vault_address = vault_pda().0; Instruction { program_id: crate::ID, accounts: vec![ AccountMeta::new(signer, true), AccountMeta::new(block_adddress, false), - // AccountMeta::new(collateral_address, false), AccountMeta::new(market_address, false), - AccountMeta::new(base_mint_address, false), AccountMeta::new(MINT_ADDRESS, false), - AccountMeta::new(stake_address, false), - AccountMeta::new(tokens_base_address, false), AccountMeta::new(tokens_quote_address, false), - AccountMeta::new(vault_base_address, false), - AccountMeta::new(vault_quote_address, false), + AccountMeta::new(vault_address, false), AccountMeta::new_readonly(system_program::ID, false), AccountMeta::new_readonly(spl_token::ID, false), AccountMeta::new_readonly(spl_associated_token_account::ID, false), @@ -330,22 +111,6 @@ pub fn set_admin(signer: Pubkey, admin: Pubkey) -> Instruction { } } -pub fn set_block_limit(signer: Pubkey, block_limit: u64) -> 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_readonly(system_program::ID, false), - ], - data: SetBlockLimit { - block_limit: block_limit.to_le_bytes(), - } - .to_bytes(), - } -} - pub fn set_fee_collector(signer: Pubkey, fee_collector: Pubkey) -> Instruction { let config_address = config_pda().0; Instruction { diff --git a/api/src/state/block.rs b/api/src/state/block.rs index 3368615..54e575f 100644 --- a/api/src/state/block.rs +++ b/api/src/state/block.rs @@ -4,12 +4,6 @@ use crate::state::block_pda; use super::OreAccount; -// What could be variable? -// - Payout style (winner take all / difficulty / both) -// - Payout skew (larger / neutral / smaller) -// - Jackpot possiblity (yes / no) -// - Known / unknown - #[repr(C)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] pub struct Block { @@ -20,42 +14,19 @@ pub struct Block { pub opener: Pubkey, /// The reward configuration. - pub reward: RewardConfig, + pub reward: u64, - /// The hash of the starting slot. - pub slot_hash: [u8; 32], - - /// The starting slot of the block. - pub start_slot: u64, - - /// The total number of hashes submitted to the block. - pub total_committed: u64, - - /// The total number of hashes deployed to the block. - pub total_deployed: u64, - - /// The total amount of rewards paid out to miners. - pub total_rewards: u64, -} - -/// Configuration specifying how rewards are paid out. -#[repr(C)] -#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] -pub struct RewardConfig { - /// The reward paid to the submitter of the best hash. - pub lode_reward: u64, + /// The best hash submitted to the block. + pub best_hash: [u8; 32], /// The authority of the miner who submitted the best hash. - pub lode_authority: Pubkey, + pub best_hash_miner: Pubkey, - /// The best hash. - pub lode_hash: [u8; 32], + /// The hash of the starting slot, used for random number generation. + pub slot_hash: [u8; 32], - /// The reward rate paid to hashes satisfying the difficulty threshold. - pub nugget_reward: u64, - - /// The minimum difficulty required for payout. - pub nugget_threshold: u64, + /// The total amount of hashpower bought in the block. + pub total_hashpower: u64, } impl Block { diff --git a/api/src/state/config.rs b/api/src/state/config.rs index 5153097..5e66cda 100644 --- a/api/src/state/config.rs +++ b/api/src/state/config.rs @@ -10,9 +10,6 @@ pub struct Config { // The address that can set the admin. pub admin: Pubkey, - /// Number of blocks that can be open for trading at one time. - pub block_limit: u64, - // The address that receives fees. pub fee_collector: Pubkey, diff --git a/api/src/state/market/market.rs b/api/src/state/market/market.rs index 287b413..1d97d6f 100644 --- a/api/src/state/market/market.rs +++ b/api/src/state/market/market.rs @@ -20,13 +20,13 @@ pub struct Market { /// Snapshot of the market state at the time of the last swap. pub snapshot: Snapshot, - /// The id of the block this market is associated with. - pub id: u64, + /// The id of the current block. + pub block_id: u64, } impl Market { pub fn pda(&self) -> (Pubkey, u8) { - market_pda(self.id) + market_pda() } pub fn base_vault(&self) -> Pubkey { @@ -449,7 +449,7 @@ mod tests { quote_balance: 0, slot: 0, }, - id: 0, + block_id: 0, } } } diff --git a/api/src/state/miner.rs b/api/src/state/miner.rs index eb52ed7..169bb07 100644 --- a/api/src/state/miner.rs +++ b/api/src/state/miner.rs @@ -16,11 +16,14 @@ pub struct Miner { /// The hash of the last block this miner mined in. pub hash: [u8; 32], - /// The total number of hashes this miner has committed to the block. - pub total_committed: u64, + /// The amount of hashpower this miner has committed to the current block. + pub hashpower: u64, - /// The total number of hashes this miner has deployed to the block. - pub total_deployed: u64, + /// A user-supplied seed for random number generation. + pub seed: [u8; 32], + + /// The total amount of hashpower this miner has committed across all blocks. + pub total_hashpower: u64, /// The total amount of ORE this miner has mined across all blocks. pub total_rewards: u64, diff --git a/api/src/state/mod.rs b/api/src/state/mod.rs index c7eceb8..7c199fe 100644 --- a/api/src/state/mod.rs +++ b/api/src/state/mod.rs @@ -2,16 +2,12 @@ mod block; mod config; mod market; mod miner; -mod permit; -mod stake; mod treasury; pub use block::*; pub use config::*; pub use market::*; pub use miner::*; -pub use permit::*; -pub use stake::*; pub use treasury::*; use crate::consts::*; @@ -25,9 +21,7 @@ pub enum OreAccount { Config = 101, Market = 102, Miner = 103, - Permit = 104, - Stake = 105, - Treasury = 106, + Treasury = 104, } pub fn block_pda(id: u64) -> (Pubkey, u8) { @@ -38,58 +32,16 @@ pub fn config_pda() -> (Pubkey, u8) { Pubkey::find_program_address(&[CONFIG], &crate::ID) } -pub fn market_pda(id: u64) -> (Pubkey, u8) { - Pubkey::find_program_address(&[MARKET, &id.to_le_bytes()], &crate::ID) +pub fn market_pda() -> (Pubkey, u8) { + Pubkey::find_program_address(&[MARKET], &crate::ID) } pub fn miner_pda(authority: Pubkey) -> (Pubkey, u8) { Pubkey::find_program_address(&[MINER, &authority.to_bytes()], &crate::ID) } -pub fn mint_pda(id: u64) -> (Pubkey, u8) { - Pubkey::find_program_address(&[MINT, &id.to_le_bytes()], &crate::ID) -} - -pub fn collateral_pda(block_id: u64) -> (Pubkey, u8) { - let block_address = block_pda(block_id).0; - Pubkey::find_program_address( - &[ - &block_address.to_bytes(), - &spl_token::ID.to_bytes(), - &MINT_ADDRESS.to_bytes(), - ], - &crate::ID, - ) -} - -pub fn commitment_pda(block_id: u64) -> (Pubkey, u8) { - let block_address = block_pda(block_id).0; - let mint_address = mint_pda(block_id).0; - Pubkey::find_program_address( - &[ - &block_address.to_bytes(), - &spl_token::ID.to_bytes(), - &mint_address.to_bytes(), - ], - &crate::ID, - ) -} - -pub fn vault_base_pda(block_id: u64) -> (Pubkey, u8) { - let market_address = market_pda(block_id).0; - let mint_address = mint_pda(block_id).0; - Pubkey::find_program_address( - &[ - &market_address.to_bytes(), - &spl_token::ID.to_bytes(), - &mint_address.to_bytes(), - ], - &crate::ID, - ) -} - -pub fn vault_quote_pda(block_id: u64) -> (Pubkey, u8) { - let market_address = market_pda(block_id).0; +pub fn vault_pda() -> (Pubkey, u8) { + let market_address = market_pda().0; Pubkey::find_program_address( &[ &market_address.to_bytes(), @@ -100,20 +52,6 @@ pub fn vault_quote_pda(block_id: u64) -> (Pubkey, u8) { ) } -pub fn permit_pda(authority: Pubkey, block_id: u64) -> (Pubkey, u8) { - Pubkey::find_program_address( - &[PERMIT, &authority.to_bytes(), &block_id.to_le_bytes()], - &crate::ID, - ) -} - -pub fn stake_pda(authority: Pubkey, block_id: u64) -> (Pubkey, u8) { - Pubkey::find_program_address( - &[STAKE, &authority.to_bytes(), &block_id.to_le_bytes()], - &crate::ID, - ) -} - pub fn treasury_pda() -> (Pubkey, u8) { Pubkey::find_program_address(&[TREASURY], &crate::ID) } diff --git a/api/src/state/permit.rs b/api/src/state/permit.rs deleted file mode 100644 index a51bcc6..0000000 --- a/api/src/state/permit.rs +++ /dev/null @@ -1,35 +0,0 @@ -use steel::*; - -use crate::state::permit_pda; - -use super::OreAccount; - -#[repr(C)] -#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] -pub struct Permit { - /// The authority of the miner account. - pub authority: Pubkey, - - /// The ID of the block this permit is for. - pub block_id: u64, - - /// The amount of hash tokens this miner has committed to the block. - pub commitment: u64, - - /// The executor of the permit. - pub executor: Pubkey, - - /// The fee paid to the executor. - pub fee: u64, - - /// A user-supplied seed for random number generation. - pub seed: [u8; 32], -} - -impl Permit { - pub fn pda(&self) -> (Pubkey, u8) { - permit_pda(self.authority, self.block_id) - } -} - -account!(OreAccount, Permit); diff --git a/api/src/state/stake.rs b/api/src/state/stake.rs deleted file mode 100644 index c593cd3..0000000 --- a/api/src/state/stake.rs +++ /dev/null @@ -1,29 +0,0 @@ -use steel::*; - -use crate::state::stake_pda; - -use super::OreAccount; - -#[repr(C)] -#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] -pub struct Stake { - /// The authority of the miner account. - pub authority: Pubkey, - - /// The ID of the block this collateral is associated with. - pub block_id: u64, - - /// The amount of ORE this miner has deposited as collateral for trading. - pub collateral: u64, - - /// The amount of ORE this miner has spent on hashpower in this market. - pub spend: u64, -} - -impl Stake { - pub fn pda(&self) -> (Pubkey, u8) { - stake_pda(self.authority, self.block_id) - } -} - -account!(OreAccount, Stake); diff --git a/cli/src/main.rs b/cli/src/main.rs index 3f855b8..8d66764 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -26,15 +26,6 @@ async fn main() { .expect("Missing COMMAND env var") .as_str() { - "open" => { - open(&rpc, &payer).await.unwrap(); - } - "close" => { - close(&rpc, &payer).await.unwrap(); - } - "close_all" => { - close_all(&rpc, &payer).await.unwrap(); - } "clock" => { log_clock(&rpc).await.unwrap(); } @@ -44,108 +35,19 @@ async fn main() { "blocks" => { log_blocks(&rpc).await.unwrap(); } - "deposit" => { - deposit(&rpc, &payer).await.unwrap(); - } "swap" => { swap(&rpc, &payer).await.unwrap(); } - "commit" => { - commit(&rpc, &payer).await.unwrap(); - } "set_admin" => { set_admin(&rpc, &payer).await.unwrap(); } - // "set_block_limit" => { - // set_block_limit(&rpc, &payer).await.unwrap(); - // } - // "uncommit" => { - // uncommit(&rpc, &payer).await.unwrap(); - // } + "benchmark" => { + benchmark_keccak().await.unwrap(); + } _ => panic!("Invalid command"), }; } -async fn open( - rpc: &RpcClient, - payer: &solana_sdk::signer::keypair::Keypair, -) -> Result<(), anyhow::Error> { - let id_str = std::env::var("ID").expect("Missing ID env var"); - let id = id_str.parse::()?; - let ix = ore_api::sdk::open(payer.pubkey(), id); - submit_transaction(rpc, payer, &[ix]).await?; - Ok(()) -} - -async fn close( - rpc: &RpcClient, - payer: &solana_sdk::signer::keypair::Keypair, -) -> Result<(), anyhow::Error> { - let id_str = std::env::var("ID").expect("Missing ID env var"); - let id = id_str.parse::()?; - let block = get_block(rpc, id).await?; - let config = get_config(rpc).await?; - let ix = ore_api::sdk::close( - payer.pubkey(), - config.fee_collector, - block.opener, - payer.pubkey(), - id, - ); - submit_transaction(rpc, payer, &[ix]).await?; - Ok(()) -} - -async fn close_all( - rpc: &RpcClient, - payer: &solana_sdk::signer::keypair::Keypair, -) -> Result<(), anyhow::Error> { - let config = get_config(rpc).await?; - let clock = get_clock(rpc).await?; - let blocks = get_blocks(rpc).await?; - for (_, block) in blocks { - if clock.slot > block.start_slot + 1500 { - println!("Closing block {}", block.id); - println!(" fee_collector: {}", config.fee_collector); - println!(" opener: {}", block.opener); - println!(" payer: {}", payer.pubkey()); - println!(" id: {}", block.id); - let ix = ore_api::sdk::close( - payer.pubkey(), - config.fee_collector, - block.opener, - payer.pubkey(), - block.id, - ); - submit_transaction(rpc, payer, &[ix]).await?; - // simulate_transaction(rpc, payer, &[ix]).await; - } - } - Ok(()) -} - -async fn commit( - rpc: &RpcClient, - payer: &solana_sdk::signer::keypair::Keypair, -) -> Result<(), anyhow::Error> { - let id_str = std::env::var("ID").expect("Missing ID env var"); - let id = id_str.parse::()?; - let ix = ore_api::sdk::commit(payer.pubkey(), 10000000, Pubkey::default(), 0, id, [0; 32]); - submit_transaction(rpc, payer, &[ix]).await?; - Ok(()) -} - -async fn deposit( - rpc: &RpcClient, - payer: &solana_sdk::signer::keypair::Keypair, -) -> Result<(), anyhow::Error> { - let id_str = std::env::var("ID").expect("Missing ID env var"); - let id = id_str.parse::()?; - let ix = ore_api::sdk::deposit(payer.pubkey(), id, 10000000); - submit_transaction(rpc, payer, &[ix]).await?; - Ok(()) -} - async fn swap( rpc: &RpcClient, payer: &solana_sdk::signer::keypair::Keypair, @@ -195,20 +97,9 @@ async fn log_block(rpc: &RpcClient) -> Result<(), anyhow::Error> { fn print_block(block: Block, clock: &Clock) { let address = block_pda(block.id).0; let current_slot = clock.slot; - let elapsed_time = (block.start_slot - current_slot) as f64 * 0.4; println!("Address: {:?}", address); println!(" Id: {:?}", block.id); - println!(" Start slot: {:?}", block.start_slot); - println!(" Starts in: {:?} sec", elapsed_time as u64); println!(" Slot hash: {:?}", block.slot_hash); - println!(" Total hashes: {:?}", block.total_committed); - println!(" Total deployed: {:?}", block.total_deployed); - println!(" Total rewards: {:?}", block.total_rewards); - println!(" Lode reward: {:?}", block.reward.lode_reward); - println!(" Lode authority: {:?}", block.reward.lode_authority); - println!(" Lode hash: {:?}", block.reward.lode_hash); - println!(" Nugget reward: {:?}", block.reward.nugget_reward); - println!(" Nugget threshold: {:?}", block.reward.nugget_threshold); } async fn log_blocks(rpc: &RpcClient) -> Result<(), anyhow::Error> { @@ -350,3 +241,25 @@ where }, } } + +async fn benchmark_keccak() -> Result<(), anyhow::Error> { + use solana_program::keccak::hash; + use std::time::Instant; + + const NUM_HASHES: u64 = 1_000_000; + let start = Instant::now(); + + for i in 0..NUM_HASHES { + let _ = hash(&i.to_le_bytes()); + } + + let duration = start.elapsed(); + let hashes_per_sec = NUM_HASHES as f64 / duration.as_secs_f64(); + + println!("\nKeccak-256 Benchmark:"); + println!("Time elapsed: {:.2?}", duration); + println!("Hashes computed: {}", NUM_HASHES); + println!("Hashes per second: {:.0}", hashes_per_sec); + + Ok(()) +} diff --git a/program/src/commit.rs b/program/src/commit.rs deleted file mode 100644 index 520514e..0000000 --- a/program/src/commit.rs +++ /dev/null @@ -1,136 +0,0 @@ -use ore_api::{prelude::*, sdk::program_log}; -use solana_program::rent::Rent; -use steel::*; - -/// Commit to a block. -pub fn process_commit(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { - // 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()?; - let [signer_info, block_info, commitment_info, market_info, miner_info, mint_info, permit_info, sender_info, system_program, token_program, ore_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - signer_info.is_signer()?; - let block = block_info - .as_account_mut::(&ore_api::ID)? - .assert_mut(|b| clock.slot < b.start_slot)?; - commitment_info - .has_address(&commitment_pda(block.id).0)? - .as_token_account()? - .assert(|t| t.mint() == *mint_info.key)? - .assert(|t| t.owner() == *block_info.key)?; - let market = market_info - .as_account::(&ore_api::ID)? - .assert(|m| m.id == block.id)?; - mint_info.has_address(&market.base.mint)?.as_mint()?; - let sender = sender_info - .is_writable()? - .as_associated_token_account(signer_info.key, &mint_info.key)?; - system_program.is_program(&system_program::ID)?; - token_program.is_program(&spl_token::ID)?; - ore_program.is_program(&ore_api::ID)?; - - // 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_committed = 0; - miner.total_deployed = 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::( - permit_info, - system_program, - signer_info, - &ore_api::ID, - &[PERMIT, &signer_info.key.to_bytes(), &block.id.to_le_bytes()], - )?; - let permit = permit_info.as_account_mut::(&ore_api::ID)?; - permit.authority = *signer_info.key; - permit.block_id = block.id; - permit.commitment = 0; - permit.executor = Pubkey::default(); - permit.fee = 0; - permit.seed = [0; 32]; - permit - } else { - permit_info - .as_account_mut::(&ore_api::ID)? - .assert_mut(|p| p.authority == *signer_info.key)? - .assert_mut(|p| p.block_id == block.id)? - }; - - // Update executor logic. - permit.executor = executor; - permit.fee = fee; - permit.seed = args.seed; - - // Send lamports to permit account to pay for fee. - if permit.fee > 0 { - let rent_exempt_balance = Rent::get()?.minimum_balance(std::mem::size_of::()); - let surplus_balance = permit_info.lamports().saturating_sub(rent_exempt_balance); - let total_fees = permit.commitment * permit.fee; - let required_fees = total_fees.saturating_sub(surplus_balance); - permit_info.collect(required_fees, signer_info)?; - } - - // Transfer hash tokens. - transfer( - signer_info, - sender_info, - commitment_info, - token_program, - amount, - )?; - - // Update block. - permit.commitment += amount; - miner.total_committed += amount; - block.total_committed += amount; - - // Emit event. - program_log( - block.id, - &[block_info.clone(), ore_program.clone()], - &CommitEvent { - disc: OreEvent::Commit as u64, - authority: *signer_info.key, - block_id: block.id, - amount, - block_commitment: block.total_committed, - permit_commitment: permit.commitment, - fee, - ts: clock.unix_timestamp, - } - .to_bytes(), - )?; - - Ok(()) -} diff --git a/program/src/deposit.rs b/program/src/deposit.rs deleted file mode 100644 index 63840fa..0000000 --- a/program/src/deposit.rs +++ /dev/null @@ -1,86 +0,0 @@ -use ore_api::{prelude::*, sdk::program_log}; -use steel::*; - -/// Deposits collateral. -pub fn process_deposit(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { - // Parse data. - let args = Deposit::try_from_bytes(data)?; - let amount = u64::from_le_bytes(args.amount); - - // Load accounts. - let clock = Clock::get()?; - let [signer_info, block_info, collateral_info, mint_ore_info, sender_info, stake_info, system_program, token_program, ore_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - signer_info.is_signer()?; - let block = block_info - .as_account_mut::(&ore_api::ID)? - .assert_mut(|b| clock.slot < b.start_slot)?; - collateral_info - .is_writable()? - .has_address(&collateral_pda(block.id).0)? - .as_token_account()? - .assert(|t| t.mint() == *mint_ore_info.key)? - .assert(|t| t.owner() == *block_info.key)?; - mint_ore_info.has_address(&MINT_ADDRESS)?.as_mint()?; - sender_info - .is_writable()? - .as_associated_token_account(signer_info.key, &mint_ore_info.key)? - .assert(|t| t.amount() >= amount)?; - system_program.is_program(&system_program::ID)?; - token_program.is_program(&spl_token::ID)?; - ore_program.is_program(&ore_api::ID)?; - - // Load stake account. - let stake = if stake_info.data_is_empty() { - create_program_account::( - stake_info, - system_program, - signer_info, - &ore_api::ID, - &[STAKE, &signer_info.key.to_bytes(), &block.id.to_le_bytes()], - )?; - let stake = stake_info.as_account_mut::(&ore_api::ID)?; - stake.authority = *signer_info.key; - stake.block_id = block.id; - stake.collateral = 0; - stake.spend = 0; - stake - } else { - stake_info - .as_account_mut::(&ore_api::ID)? - .assert_mut(|p| p.authority == *signer_info.key)? - .assert_mut(|p| p.block_id == block.id)? - }; - - // Update stake state. - stake.collateral += amount; - - // Transfer collateral. - transfer( - signer_info, - sender_info, - collateral_info, - token_program, - amount, - )?; - - // Emit event. - program_log( - block.id, - &[block_info.clone(), ore_program.clone()], - &DepositEvent { - disc: OreEvent::Deposit as u64, - authority: *signer_info.key, - block_id: block.id, - amount, - collateral: stake.collateral, - ts: clock.unix_timestamp, - } - .to_bytes(), - )?; - - Ok(()) -} diff --git a/program/src/initialize.rs b/program/src/initialize.rs new file mode 100644 index 0000000..3b327d5 --- /dev/null +++ b/program/src/initialize.rs @@ -0,0 +1,84 @@ +use ore_api::prelude::*; +use steel::*; + +/// Sets the admin. +pub fn process_initialize(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult { + // Parse data. + // let args = Initialize::try_from_bytes(data)?; + + // Load accounts. + let [signer_info, config_info, market_info, treasury_info, system_program] = accounts else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + signer_info.is_signer()?.has_address(&ADMIN_ADDRESS)?; + config_info + .is_writable()? + .is_empty()? + .has_seeds(&[CONFIG], &ore_api::ID)?; + market_info + .is_writable()? + .is_empty()? + .has_seeds(&[MARKET], &ore_api::ID)?; + treasury_info + .is_writable()? + .is_empty()? + .has_seeds(&[TREASURY], &ore_api::ID)?; + system_program.is_program(&system_program::ID)?; + + // Create config account. + create_program_account::( + config_info, + system_program, + signer_info, + &ore_api::ID, + &[CONFIG], + )?; + let config = config_info.as_account_mut::(&ore_api::ID)?; + config.admin = *signer_info.key; + config.fee_collector = *signer_info.key; + config.fee_rate = 0; + + // Initialize market. + let initial_id: u64 = 0; + create_program_account::( + market_info, + system_program, + signer_info, + &ore_api::ID, + &[MARKET], + )?; + let market = market_info.as_account_mut::(&ore_api::ID)?; + market.base = TokenParams { + mint: Pubkey::default(), // Virtual token + balance: 0, + balance_virtual: 0, + }; + market.quote = TokenParams { + mint: MINT_ADDRESS, + balance: 0, + balance_virtual: 0, + }; + market.fee = FeeParams { + rate: FEE_RATE_BPS, + uncollected: 0, + cumulative: 0, + }; + market.snapshot = Snapshot { + enabled: 1, + base_balance: 0, + quote_balance: 0, + slot: 0, + }; + market.block_id = initial_id; + + // Create treasury account. + create_program_account::( + treasury_info, + system_program, + signer_info, + &ore_api::ID, + &[TREASURY], + )?; + + Ok(()) +} diff --git a/program/src/lib.rs b/program/src/lib.rs index d63b7d5..68971ec 100644 --- a/program/src/lib.rs +++ b/program/src/lib.rs @@ -1,30 +1,18 @@ -mod close; -mod commit; -mod deposit; +mod initialize; mod log; mod mine; -mod open; mod set_admin; -mod set_block_limit; mod set_fee_collector; mod set_fee_rate; mod swap; -mod uncommit; -mod withdraw; -use close::*; -use commit::*; -use deposit::*; +use initialize::*; use log::*; use mine::*; -use open::*; use set_admin::*; -use set_block_limit::*; use set_fee_collector::*; use set_fee_rate::*; use swap::*; -use uncommit::*; -use withdraw::*; use ore_api::instruction::*; use steel::*; @@ -37,19 +25,18 @@ pub fn process_instruction( let (ix, data) = parse_instruction(&ore_api::ID, program_id, data)?; match ix { - OreInstruction::Open => process_open(accounts, data)?, - OreInstruction::Close => process_close(accounts, data)?, - OreInstruction::Commit => process_commit(accounts, data)?, - OreInstruction::Deposit => process_deposit(accounts, data)?, + // User OreInstruction::Log => process_log(accounts, data)?, OreInstruction::Mine => process_mine(accounts, data)?, OreInstruction::Swap => process_swap(accounts, data)?, - OreInstruction::Uncommit => process_uncommit(accounts, data)?, - OreInstruction::Withdraw => process_withdraw(accounts, data)?, + OreInstruction::Initialize => process_initialize(accounts, data)?, + + // Admin OreInstruction::SetAdmin => process_set_admin(accounts, data)?, - OreInstruction::SetBlockLimit => process_set_block_limit(accounts, data)?, OreInstruction::SetFeeCollector => process_set_fee_collector(accounts, data)?, OreInstruction::SetFeeRate => process_set_fee_rate(accounts, data)?, + + _ => panic!("Not implemented"), } Ok(()) diff --git a/program/src/mine.rs b/program/src/mine.rs index d518a08..3d71493 100644 --- a/program/src/mine.rs +++ b/program/src/mine.rs @@ -1,6 +1,6 @@ use ore_api::{prelude::*, sdk::program_log}; use solana_nostd_keccak::hash; -use solana_program::slot_hashes::SlotHashes; +use solana_program::{log::sol_log, slot_hashes::SlotHashes}; use steel::*; /// Mine a block. @@ -11,34 +11,23 @@ pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult // Load accounts. let clock = Clock::get()?; - 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, ore_program, slot_hashes_sysvar] = + let [signer_info, authority_info, block_info, market_info, miner_info, mint_info, recipient_info, treasury_info, system_program, token_program, ore_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)? - .assert_mut(|b| clock.slot < b.start_slot + 1500)?; - commitment_info - .is_writable()? - .has_address(&commitment_pda(block.id).0)? - .as_token_account()?; + let block = block_info.as_account_mut::(&ore_api::ID)?; + // .assert_mut(|b| clock.slot >= b.start_slot)? + // .assert_mut(|b| clock.slot < b.start_slot + 1500)?; let market = market_info .as_account::(&ore_api::ID)? - .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()?; + .assert(|m| m.block_id == block.id)?; + mint_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 == 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(&miner.authority, &MINT_ADDRESS)?; @@ -48,130 +37,82 @@ pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult ore_program.is_program(&ore_api::ID)?; slot_hashes_sysvar.is_sysvar(&sysvar::slot_hashes::ID)?; - // Reduce permit amount. - let amount = permit.commitment.min(amount); - permit.commitment -= amount; - - // Pay executor fee. - // if permit.fee > 0 { - // permit_info.send(permit.fee * amount, signer_info); - // } - - // Close permit account, if empty. - let permit_commitment = permit.commitment; - if permit_commitment == 0 { - permit_info.close(authority_info)?; - } - // Burn hash tokens. - burn_signed( - commitment_info, - mint_hash_info, - block_info, - token_program, - amount, - &[BLOCK, &block.id.to_le_bytes()], - )?; + // burn_signed( + // commitment_info, + // mint_hash_info, + // block_info, + // token_program, + // amount, + // &[BLOCK, &block.id.to_le_bytes()], + // )?; // Set block slot hash. - if block.slot_hash == [0; 32] { - let slot_hashes = - bincode::deserialize::(slot_hashes_sysvar.data.borrow().as_ref()).unwrap(); - let Some(slot_hash) = slot_hashes.get(&block.start_slot) else { - // If mine is not called within ~2.5 minutes of the block starting, - // then the slot hash will be unavailable and secure hashes cannot be generated. - return Ok(()); - }; - block.slot_hash = slot_hash.to_bytes(); - } + // if block.slot_hash == [0; 32] { + // let slot_hashes = + // bincode::deserialize::(slot_hashes_sysvar.data.borrow().as_ref()).unwrap(); + // let Some(slot_hash) = slot_hashes.get(&block.start_slot) else { + // // If mine is not called within ~2.5 minutes of the block starting, + // // then the slot hash will be unavailable and secure hashes cannot be generated. + // return Ok(()); + // }; + // block.slot_hash = slot_hash.to_bytes(); + // } // Reset miner hash if mining new block. - if miner.block_id != block.id { - let mut args = [0u8; 104]; - args[..8].copy_from_slice(&block.id.to_le_bytes()); - args[8..40].copy_from_slice(&block.slot_hash); - args[40..72].copy_from_slice(&permit.authority.to_bytes()); - args[72..].copy_from_slice(&permit.seed); - miner.hash = hash(&args); - miner.block_id = block.id; - } + // if miner.block_id != block.id { + // let mut args = [0u8; 104]; + // args[..8].copy_from_slice(&block.id.to_le_bytes()); + // args[8..40].copy_from_slice(&block.slot_hash); + // args[40..72].copy_from_slice(&miner.authority.to_bytes()); + // args[72..].copy_from_slice(&miner.seed); + // miner.hash = hash(&args); + // miner.block_id = block.id; + // } // Mine and accumulate rewards. - let mut nugget_reward = 0; - for _ in 0..amount { - // Update stats - block.total_deployed += 1; - miner.total_deployed += 1; + // let mut nugget_reward = 0; + // for _ in 0..amount { + // // Update stats + // // block.total_deployed += 1; - // Generate hash. - miner.hash = hash(miner.hash.as_ref()); + // // Generate hash. + // miner.hash = hash(miner.hash.as_ref()); - // Score and increment rewards. - let score = difficulty(miner.hash) as u64; - if score >= block.reward.nugget_threshold { - nugget_reward += block.reward.nugget_reward; - } + // // Score and increment rewards. + // let score = difficulty(miner.hash) as u64; + // if score >= block.reward.nugget_threshold { + // nugget_reward += block.reward.nugget_reward; + // } - // If hash is best hash, update best hash. - if miner.hash < block.reward.lode_hash { - block.reward.lode_hash = miner.hash; - block.reward.lode_authority = miner.authority; - } - } + // // If hash is best hash, update best hash. + // if miner.hash < block.reward.lode_hash { + // block.reward.lode_hash = miner.hash; + // block.reward.lode_authority = miner.authority; + // } + // } - // Payout ORE. - if nugget_reward > 0 { - // Limit payout to supply cap. - let ore_mint = mint_ore_info.as_mint()?; - let max_reward = MAX_SUPPLY.saturating_sub(ore_mint.supply()); - let reward_amount = nugget_reward.min(max_reward); - - // Update stats. - block.total_rewards += reward_amount; - miner.total_rewards += reward_amount; - - // Mint to recipient. - mint_to_signed_with_bump( - mint_ore_info, - recipient_info, - treasury_info, - token_program, - reward_amount, - &[TREASURY], - TREASURY_BUMP, - )?; - - // Emit event. - program_log( - block.id, - &[block_info.clone(), ore_program.clone()], - &RewardEvent { - disc: OreEvent::Reward as u64, - amount: reward_amount, - authority: miner.authority, - block_id: block.id, - rewards_type: RewardsType::Nugget as u64, - ts: clock.unix_timestamp, - } - .to_bytes(), - )?; - } + // Log mint. + // let ore_mint = mint_ore_info.as_mint()?; + // let mint_authority = ore_mint.mint_authority(); + // sol_log(format!("mint_authority: {:?}", mint_authority).as_str()); + // sol_log(format!("treasury: {:?}", treasury_info.key).as_str()); // Emit event. - program_log( - block.id, - &[block_info.clone(), ore_program.clone()], - &MineEvent { - disc: OreEvent::Mine as u64, - authority: miner.authority, - block_id: block.id, - deployed: amount, - total_deployed: block.total_deployed, - remaining_commitment: permit_commitment, - ts: clock.unix_timestamp, - } - .to_bytes(), - )?; + // program_log( + // block.id, + // &[block_info.clone(), ore_program.clone()], + // &MineEvent { + // disc: OreEvent::Mine as u64, + // authority: miner.authority, + // block_id: block.id, + // deployed: amount, + // total_deployed: block.total_deployed, + // remaining_commitment: 0, + // ts: clock.unix_timestamp, + // } + // .to_bytes(), + // )?; Ok(()) } diff --git a/program/src/open.rs b/program/src/open.rs index 8b9a793..4ce3c36 100644 --- a/program/src/open.rs +++ b/program/src/open.rs @@ -219,7 +219,7 @@ pub fn process_open(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult .assert(|t| t.owner() == *block_info.key)?; } - // Initialize vault token accounts. + // Initialize base vault token account. if vault_base_info.data_is_empty() { let vault_base_pda = vault_base_pda(id); allocate_account_with_bump( @@ -256,6 +256,8 @@ pub fn process_open(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult .assert(|t| t.mint() == *mint_base_info.key)? .assert(|t| t.owner() == *market_info.key)?; } + + // Initialize quote vault token account. if vault_quote_info.data_is_empty() { let vault_quote_pda = vault_quote_pda(id); allocate_account_with_bump( diff --git a/program/src/set_admin.rs b/program/src/set_admin.rs index 655bff9..9d332c0 100644 --- a/program/src/set_admin.rs +++ b/program/src/set_admin.rs @@ -12,33 +12,11 @@ pub fn process_set_admin(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramRe return Err(ProgramError::NotEnoughAccountKeys); }; signer_info.is_signer()?; + let config = config_info + .as_account_mut::(&ore_api::ID)? + .assert_mut(|c| c.admin == *signer_info.key)?; system_program.is_program(&system_program::ID)?; - // Load config account. - let config = if config_info.data_is_empty() { - // Assert signer is admin. - // signer_info.has_address(&ADMIN_ADDRESS)?; - - // Create config account. - create_program_account::( - config_info, - system_program, - signer_info, - &ore_api::ID, - &[CONFIG], - )?; - let config = config_info.as_account_mut::(&ore_api::ID)?; - config.admin = *signer_info.key; - config.block_limit = 100; - config.fee_collector = *signer_info.key; - config.fee_rate = 0; - config - } else { - config_info - .as_account_mut::(&ore_api::ID)? - .assert_mut(|c| c.admin == *signer_info.key)? - }; - // Set admin. config.admin = new_admin; diff --git a/program/src/set_block_limit.rs b/program/src/set_block_limit.rs deleted file mode 100644 index 65948d6..0000000 --- a/program/src/set_block_limit.rs +++ /dev/null @@ -1,24 +0,0 @@ -use ore_api::prelude::*; -use steel::*; - -/// Sets the block limit. -pub fn process_set_block_limit(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { - // Parse data. - let args = SetBlockLimit::try_from_bytes(data)?; - let new_block_limit = u64::from_le_bytes(args.block_limit); - - // Load accounts. - let [signer_info, config_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(|c| c.admin == *signer_info.key)?; - system_program.is_program(&system_program::ID)?; - - // Set block limit. - config.block_limit = new_block_limit; - - Ok(()) -} diff --git a/program/src/swap.rs b/program/src/swap.rs index 401dc03..53fdf86 100644 --- a/program/src/swap.rs +++ b/program/src/swap.rs @@ -11,35 +11,23 @@ pub fn process_swap(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult // Load accounts. let clock = Clock::get()?; - let [signer_info, block_info, market_info, mint_base_info, mint_quote_info, stake_info, tokens_base_info, tokens_quote_info, vault_base_info, vault_quote_info, system_program, token_program, associated_token_program, ore_program] = + let [signer_info, block_info, market_info, mint_quote_info, tokens_info, vault_info, system_program, token_program, associated_token_program, ore_program] = accounts else { return Err(ProgramError::NotEnoughAccountKeys); }; signer_info.is_signer()?; - let block: &mut Block = block_info - .as_account_mut::(&ore_api::ID)? - .assert_mut(|b| clock.slot < b.start_slot)?; + let block: &mut Block = block_info.as_account_mut::(&ore_api::ID)?; + // .assert_mut(|b| clock.slot < b.start_slot)?; let market = market_info .as_account_mut::(&ore_api::ID)? - .assert_mut(|m| m.id == block.id)? + .assert_mut(|m| m.block_id == block.id)? .assert_mut(|m| m.base.liquidity() > 0)? .assert_mut(|m| m.quote.liquidity() > 0)?; - mint_base_info.has_address(&market.base.mint)?.as_mint()?; mint_quote_info.has_address(&market.quote.mint)?.as_mint()?; - let stake = stake_info - .as_account_mut::(&ore_api::ID)? - .assert_mut(|p| p.authority == *signer_info.key)? - .assert_mut(|p| p.block_id == block.id)?; - vault_base_info + vault_info .is_writable()? - .has_address(&vault_base_pda(block.id).0)? - .as_token_account()? - .assert(|t| t.mint() == *mint_base_info.key)? - .assert(|t| t.owner() == *market_info.key)?; - vault_quote_info - .is_writable()? - .has_address(&vault_quote_pda(block.id).0)? + .has_address(&vault_pda().0)? .as_token_account()? .assert(|t| t.mint() == *mint_quote_info.key)? .assert(|t| t.owner() == *market_info.key)?; @@ -49,33 +37,18 @@ pub fn process_swap(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult ore_program.is_program(&ore_api::ID)?; // Load token acccounts. - if tokens_base_info.data_is_empty() { + if tokens_info.data_is_empty() { create_associated_token_account( signer_info, signer_info, - tokens_base_info, - mint_base_info, - system_program, - token_program, - associated_token_program, - )?; - } else { - tokens_base_info - .is_writable()? - .as_associated_token_account(signer_info.key, mint_base_info.key)?; - } - if tokens_quote_info.data_is_empty() { - create_associated_token_account( - signer_info, - signer_info, - tokens_quote_info, + tokens_info, mint_quote_info, system_program, token_program, associated_token_program, )?; } else { - tokens_quote_info + tokens_info .is_writable()? .as_associated_token_account(signer_info.key, mint_quote_info.key)?; } @@ -85,57 +58,33 @@ pub fn process_swap(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult swap_event.authority = *signer_info.key; swap_event.block_id = block.id; - // Get transfer amounts and accounts. - let (in_amount, in_from, in_to, out_amount, out_from, out_to) = match direction { - SwapDirection::Buy => ( - swap_event.quote_to_transfer, - tokens_quote_info, - vault_quote_info, - swap_event.base_to_transfer, - vault_base_info, - tokens_base_info, - ), - SwapDirection::Sell => ( - swap_event.base_to_transfer, - tokens_base_info, - vault_base_info, - swap_event.quote_to_transfer, - vault_quote_info, - tokens_quote_info, - ), - }; - - // Update stake state. + // Transfer tokens match direction { SwapDirection::Buy => { - // TODO Fail if out_amount is zero - stake.spend += in_amount; + transfer( + signer_info, + tokens_info, + vault_info, + token_program, + swap_event.quote_to_transfer, + )?; } SwapDirection::Sell => { - stake.spend = stake.spend.saturating_sub(out_amount); + transfer_signed( + market_info, + vault_info, + tokens_info, + token_program, + swap_event.quote_to_transfer, + &[MARKET], + )?; } - } - - // Assert utilization is not greater than capacity. - if stake.spend > stake.collateral { - panic!("spend is greater than collateral"); - } - - // Transfer tokens. - transfer(signer_info, in_from, in_to, token_program, in_amount)?; - transfer_signed( - market_info, - out_from, - out_to, - token_program, - out_amount, - &[MARKET, market.id.to_le_bytes().as_ref()], - )?; + }; // Validate vault reserves. - let vault_base = vault_base_info.as_token_account()?; - let vault_quote = vault_quote_info.as_token_account()?; - market.check_vaults(&vault_base, &vault_quote)?; + // let vault_base = vault_base_info.as_token_account()?; + // let vault_quote = vault_quote_info.as_token_account()?; + // market.check_vaults(&vault_base, &vault_quote)?; // Emit event. program_log( diff --git a/program/src/uncommit.rs b/program/src/uncommit.rs deleted file mode 100644 index 6c7a133..0000000 --- a/program/src/uncommit.rs +++ /dev/null @@ -1,88 +0,0 @@ -use ore_api::{prelude::*, sdk::program_log}; -use steel::*; - -/// Uncommit from a block. -pub fn process_uncommit(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { - // Parse data. - let args = Uncommit::try_from_bytes(data)?; - let amount = u64::from_le_bytes(args.amount); - - // Load accounts. - let clock = Clock::get()?; - let [signer_info, block_info, commitment_info, market_info, miner_info, mint_info, permit_info, recipient_info, system_program, token_program, ore_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - signer_info.is_signer()?; - let block = block_info - .as_account_mut::(&ore_api::ID)? - .assert_mut(|b| clock.slot < b.start_slot)?; - commitment_info - .is_writable()? - .has_address(&commitment_pda(block.id).0)? - .as_token_account()? - .assert(|t| t.mint() == *mint_info.key)? - .assert(|t| t.owner() == *block_info.key)?; - let market = market_info - .as_account::(&ore_api::ID)? - .assert(|m| m.id == block.id)?; - let miner = miner_info - .as_account_mut::(&ore_api::ID)? - .assert_mut(|m| m.authority == *signer_info.key)?; - mint_info.has_address(&market.base.mint)?.as_mint()?; - let permit = permit_info - .as_account_mut::(&ore_api::ID)? - .assert_mut(|p| p.authority == *signer_info.key)? - .assert_mut(|p| p.block_id == block.id)?; - recipient_info - .is_writable()? - .as_associated_token_account(signer_info.key, &mint_info.key)?; - system_program.is_program(&system_program::ID)?; - token_program.is_program(&spl_token::ID)?; - ore_program.is_program(&ore_api::ID)?; - - // Normalize amount. - let amount = permit.commitment.min(amount); - - // Transfer hash tokens. - transfer_signed( - block_info, - commitment_info, - recipient_info, - token_program, - amount, - &[BLOCK, &block.id.to_le_bytes()], - )?; - - // Update block. - permit.commitment -= amount; - miner.total_committed -= amount; - block.total_committed -= amount; - - // Close permit account, if empty. - let fee = permit.fee; - let commitment = permit.commitment; - if permit.commitment == 0 { - permit_info.close(signer_info)?; - } - - // Emit event. - program_log( - block.id, - &[block_info.clone(), ore_program.clone()], - &UncommitEvent { - disc: OreEvent::Uncommit as u64, - authority: *signer_info.key, - block_id: block.id, - block_commitment: block.total_committed, - permit_commitment: commitment, - amount, - fee, - ts: clock.unix_timestamp, - } - .to_bytes(), - )?; - - Ok(()) -} diff --git a/program/src/withdraw.rs b/program/src/withdraw.rs deleted file mode 100644 index d4f7e5a..0000000 --- a/program/src/withdraw.rs +++ /dev/null @@ -1,81 +0,0 @@ -use ore_api::{prelude::*, sdk::program_log}; -use steel::*; - -/// Withdraws collateral. -pub fn process_withdraw(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { - // Parse data. - let args = Withdraw::try_from_bytes(data)?; - let amount = u64::from_le_bytes(args.amount); - - // Load accounts. - let clock = Clock::get()?; - let [signer_info, block_info, collateral_info, mint_ore_info, recipient_info, stake_info, system_program, token_program, ore_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - signer_info.is_signer()?; - mint_ore_info.has_address(&MINT_ADDRESS)?.as_mint()?; - recipient_info - .is_writable()? - .as_associated_token_account(signer_info.key, &mint_ore_info.key)?; - let stake = stake_info - .as_account_mut::(&ore_api::ID)? - .assert_mut(|p| p.authority == *signer_info.key)?; - let block_pda = block_pda(stake.block_id); - block_info.has_address(&block_pda.0)?; - collateral_info - .is_writable()? - .has_address(&collateral_pda(stake.block_id).0)? - .as_token_account()? - .assert(|t| t.mint() == *mint_ore_info.key)? - .assert(|t| t.owner() == *block_info.key)?; - system_program.is_program(&system_program::ID)?; - token_program.is_program(&spl_token::ID)?; - ore_program.is_program(&ore_api::ID)?; - - // Check timestamp. Collateral can only be withdrawn after the block has started mining - let start_slot = stake.block_id * 1500; - if clock.slot < start_slot { - return Err(ProgramError::InvalidArgument); - } - - // Normalize amount - let amount = amount.min(stake.collateral); - - // Update stake state. - stake.collateral -= amount; - - // Transfer collateral. - transfer_signed_with_bump( - block_info, - collateral_info, - recipient_info, - token_program, - amount, - &[BLOCK, &stake.block_id.to_le_bytes()], - block_pda.1, - )?; - - // Close stake account, if empty. - if stake.collateral == 0 { - stake_info.close(signer_info)?; - } - - // Emit event. - program_log( - stake.block_id, - &[block_info.clone(), ore_program.clone()], - &WithdrawEvent { - disc: OreEvent::Withdraw as u64, - authority: *signer_info.key, - block_id: stake.block_id, - amount, - collateral: stake.collateral, - ts: clock.unix_timestamp, - } - .to_bytes(), - )?; - - Ok(()) -}