mirror of
https://github.com/d0zingcat/ore.git
synced 2026-05-18 23:16:48 +00:00
remove staking program
This commit is contained in:
133
api/src/consts.rs
Normal file
133
api/src/consts.rs
Normal file
@@ -0,0 +1,133 @@
|
||||
use array_const_fn_init::array_const_fn_init;
|
||||
use const_crypto::ed25519;
|
||||
use solana_program::{pubkey, pubkey::Pubkey};
|
||||
|
||||
/// The reward rate to intialize the program with.
|
||||
pub const INITIAL_BASE_REWARD_RATE: u64 = 10u64.pow(3u32);
|
||||
|
||||
/// The admin allowed to initialize the program.
|
||||
pub const INITIAL_ADMIN: Pubkey = pubkey!("HBUh9g46wk2X89CvaNN15UmsznP59rh6od1h8JwYAopk");
|
||||
|
||||
/// The spam/liveness tolerance in seconds.
|
||||
pub const TOLERANCE: i64 = 5;
|
||||
|
||||
/// The minimum difficulty required of all submitted hashes.
|
||||
pub const MIN_DIFFICULTY: u32 = 8;
|
||||
|
||||
/// The decimal precision of the ORE token.
|
||||
/// There are 100 billion indivisible units per ORE (called "grains").
|
||||
pub const TOKEN_DECIMALS: u8 = 11;
|
||||
|
||||
/// The decimal precision of the ORE v1 token.
|
||||
pub const TOKEN_DECIMALS_V1: u8 = 9;
|
||||
|
||||
/// One ORE token, denominated in indivisible units.
|
||||
pub const ONE_ORE: u64 = 10u64.pow(TOKEN_DECIMALS as u32);
|
||||
|
||||
/// The duration of one minute, in seconds.
|
||||
pub const ONE_MINUTE: i64 = 60;
|
||||
|
||||
/// The number of minutes in a program epoch.
|
||||
pub const EPOCH_MINUTES: i64 = 1;
|
||||
|
||||
/// The duration of a program epoch, in seconds.
|
||||
pub const EPOCH_DURATION: i64 = ONE_MINUTE.saturating_mul(EPOCH_MINUTES);
|
||||
|
||||
/// The maximum token supply (21 million).
|
||||
pub const MAX_SUPPLY: u64 = ONE_ORE.saturating_mul(21_000_000);
|
||||
|
||||
/// The target quantity of ORE to be mined per epoch.
|
||||
pub const TARGET_EPOCH_REWARDS: u64 = ONE_ORE.saturating_mul(EPOCH_MINUTES as u64);
|
||||
|
||||
/// The maximum quantity of ORE that can be mined per epoch.
|
||||
/// Inflation rate ≈ 1 ORE / min (min 0, max 8)
|
||||
pub const MAX_EPOCH_REWARDS: u64 = TARGET_EPOCH_REWARDS.saturating_mul(BUS_COUNT as u64);
|
||||
|
||||
/// The quantity of ORE each bus is allowed to issue per epoch.
|
||||
pub const BUS_EPOCH_REWARDS: u64 = MAX_EPOCH_REWARDS.saturating_div(BUS_COUNT as u64);
|
||||
|
||||
/// The number of bus accounts, for parallelizing mine operations.
|
||||
pub const BUS_COUNT: usize = 8;
|
||||
|
||||
/// The smoothing factor for reward rate changes. The reward rate cannot change by more or less
|
||||
/// than a factor of this constant from one epoch to the next.
|
||||
pub const SMOOTHING_FACTOR: u64 = 2;
|
||||
|
||||
// Assert MAX_EPOCH_REWARDS is evenly divisible by BUS_COUNT.
|
||||
static_assertions::const_assert!(
|
||||
(MAX_EPOCH_REWARDS / BUS_COUNT as u64) * BUS_COUNT as u64 == MAX_EPOCH_REWARDS
|
||||
);
|
||||
|
||||
/// The seed of the bus account PDA.
|
||||
pub const BUS: &[u8] = b"bus";
|
||||
|
||||
/// The seed of the config account PDA.
|
||||
pub const CONFIG: &[u8] = b"config";
|
||||
|
||||
/// The seed of the metadata account PDA.
|
||||
pub const METADATA: &[u8] = b"metadata";
|
||||
|
||||
/// The seed of the mint account PDA.
|
||||
pub const MINT: &[u8] = b"mint";
|
||||
|
||||
/// The seed of proof account PDAs.
|
||||
pub const PROOF: &[u8] = b"proof";
|
||||
|
||||
/// The seed of the treasury account PDA.
|
||||
pub const TREASURY: &[u8] = b"treasury";
|
||||
|
||||
/// Noise for deriving the mint pda
|
||||
pub const MINT_NOISE: [u8; 16] = [
|
||||
166, 199, 85, 221, 225, 119, 21, 185, 160, 82, 242, 237, 194, 84, 250, 252,
|
||||
];
|
||||
|
||||
/// The name for token metadata.
|
||||
pub const METADATA_NAME: &str = "ORE";
|
||||
|
||||
/// The ticker symbol for token metadata.
|
||||
pub const METADATA_SYMBOL: &str = "ORE";
|
||||
|
||||
/// The uri for token metdata.
|
||||
pub const METADATA_URI: &str = "https://ore.supply/metadata.json";
|
||||
|
||||
/// Program id for const pda derivations
|
||||
const PROGRAM_ID: [u8; 32] = unsafe { *(&crate::id() as *const Pubkey as *const [u8; 32]) };
|
||||
|
||||
/// The addresses of the bus accounts.
|
||||
pub const BUS_ADDRESSES: [Pubkey; BUS_COUNT] = array_const_fn_init![const_bus_address; 8];
|
||||
|
||||
/// Function to derive const bus addresses.
|
||||
const fn const_bus_address(i: usize) -> Pubkey {
|
||||
Pubkey::new_from_array(ed25519::derive_program_address(&[BUS, &[i as u8]], &PROGRAM_ID).0)
|
||||
}
|
||||
|
||||
/// The address of the config account.
|
||||
pub const CONFIG_ADDRESS: Pubkey =
|
||||
Pubkey::new_from_array(ed25519::derive_program_address(&[CONFIG], &PROGRAM_ID).0);
|
||||
|
||||
/// The address of the mint metadata account.
|
||||
pub const METADATA_ADDRESS: Pubkey = Pubkey::new_from_array(
|
||||
ed25519::derive_program_address(
|
||||
&[
|
||||
METADATA,
|
||||
unsafe { &*(&mpl_token_metadata::ID as *const Pubkey as *const [u8; 32]) },
|
||||
unsafe { &*(&MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
|
||||
],
|
||||
unsafe { &*(&mpl_token_metadata::ID as *const Pubkey as *const [u8; 32]) },
|
||||
)
|
||||
.0,
|
||||
);
|
||||
|
||||
/// The address of the mint account.
|
||||
pub const MINT_ADDRESS: Pubkey =
|
||||
Pubkey::new_from_array(ed25519::derive_program_address(&[MINT, &MINT_NOISE], &PROGRAM_ID).0);
|
||||
|
||||
/// The address of the v1 mint account.
|
||||
pub const MINT_V1_ADDRESS: Pubkey = pubkey!("oreoN2tQbHXVaZsr3pf66A48miqcBXCDJozganhEJgz");
|
||||
|
||||
/// The address of the treasury account.
|
||||
pub const TREASURY_ADDRESS: Pubkey =
|
||||
Pubkey::new_from_array(ed25519::derive_program_address(&[TREASURY], &PROGRAM_ID).0);
|
||||
|
||||
/// The bump of the treasury account, for cpis.
|
||||
pub const TREASURY_BUMP: u8 = ed25519::derive_program_address(&[TREASURY], &PROGRAM_ID).1;
|
||||
32
api/src/error.rs
Normal file
32
api/src/error.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
use num_enum::IntoPrimitive;
|
||||
use solana_program::program_error::ProgramError;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error, Clone, Copy, PartialEq, Eq, IntoPrimitive)]
|
||||
#[repr(u32)]
|
||||
pub enum OreError {
|
||||
#[error("The epoch has ended and needs reset")]
|
||||
NeedsReset = 0,
|
||||
#[error("The provided hash is invalid")]
|
||||
HashInvalid = 1,
|
||||
#[error("The provided hash did not satisfy the minimum required difficulty")]
|
||||
HashTooEasy = 2,
|
||||
#[error("The claim amount cannot be greater than the claimable rewards")]
|
||||
ClaimTooLarge = 3,
|
||||
#[error("The clock time is invalid")]
|
||||
ClockInvalid = 4,
|
||||
#[error("You are trying to submit too soon")]
|
||||
Spam = 5,
|
||||
#[error("Only one hash may be validated per transaction")]
|
||||
TransactionInvalid = 6,
|
||||
#[error("The tolerance cannot exceed i64 max value")]
|
||||
ToleranceOverflow = 7,
|
||||
#[error("The maximum supply has been reached")]
|
||||
MaxSupply = 8,
|
||||
}
|
||||
|
||||
impl From<OreError> for ProgramError {
|
||||
fn from(e: OreError) -> Self {
|
||||
ProgramError::Custom(e as u32)
|
||||
}
|
||||
}
|
||||
13
api/src/event.rs
Normal file
13
api/src/event.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
use crate::utils::impl_to_bytes;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
|
||||
pub struct MineEvent {
|
||||
pub difficulty: u64,
|
||||
pub reward: u64,
|
||||
pub timing: i64,
|
||||
}
|
||||
|
||||
impl_to_bytes!(MineEvent);
|
||||
442
api/src/instruction.rs
Normal file
442
api/src/instruction.rs
Normal file
@@ -0,0 +1,442 @@
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use drillx::Solution;
|
||||
use num_enum::TryFromPrimitive;
|
||||
use shank::ShankInstruction;
|
||||
use solana_program::{
|
||||
instruction::{AccountMeta, Instruction},
|
||||
pubkey::Pubkey,
|
||||
system_program, sysvar,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
consts::*,
|
||||
utils::{impl_instruction_from_bytes, impl_to_bytes},
|
||||
};
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, ShankInstruction, TryFromPrimitive)]
|
||||
#[rustfmt::skip]
|
||||
pub enum OreInstruction {
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
#[account(2, name = "beneficiary", desc = "Beneficiary token account", writable)]
|
||||
#[account(3, name = "proof", desc = "Ore proof account", writable)]
|
||||
#[account(4, name = "treasury", desc = "Ore treasury account", writable)]
|
||||
#[account(5, name = "treasury_tokens", desc = "Ore treasury token account", writable)]
|
||||
#[account(6, name = "token_program", desc = "SPL token program")]
|
||||
Claim = 0,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
#[account(2, name = "proof", desc = "Ore proof account", writable)]
|
||||
#[account(3, name = "system_program", desc = "Solana system program")]
|
||||
Close = 1,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
#[account(2, name = "config", desc = "Ore config account", writable)]
|
||||
#[account(3, name = "proof", desc = "Ore proof account – current top staker")]
|
||||
#[account(4, name = "proof_new", desc = "Ore proof account – new top staker")]
|
||||
Crown = 2,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
#[account(2, name = "bus", desc = "Ore bus account", writable)]
|
||||
#[account(3, name = "config", desc = "Ore config account")]
|
||||
#[account(4, name = "noise", desc = "Ore noise account")]
|
||||
#[account(5, name = "proof", desc = "Ore proof account", writable)]
|
||||
#[account(6, name = "slot_hashes", desc = "Solana slot hashes sysvar")]
|
||||
Mine = 3,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
#[account(2, name = "proof", desc = "Ore proof account", writable)]
|
||||
#[account(3, name = "system_program", desc = "Solana system program")]
|
||||
Open = 4,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
#[account(2, name = "bus_0", desc = "Ore bus account 0", writable)]
|
||||
#[account(3, name = "bus_1", desc = "Ore bus account 1", writable)]
|
||||
#[account(4, name = "bus_2", desc = "Ore bus account 2", writable)]
|
||||
#[account(5, name = "bus_3", desc = "Ore bus account 3", writable)]
|
||||
#[account(6, name = "bus_4", desc = "Ore bus account 4", writable)]
|
||||
#[account(7, name = "bus_5", desc = "Ore bus account 5", writable)]
|
||||
#[account(8, name = "bus_6", desc = "Ore bus account 6", writable)]
|
||||
#[account(9, name = "bus_7", desc = "Ore bus account 7", writable)]
|
||||
#[account(10, name = "config", desc = "Ore config account")]
|
||||
#[account(11, name = "mint", desc = "Ore token mint account", writable)]
|
||||
#[account(12, name = "treasury", desc = "Ore treasury account", writable)]
|
||||
#[account(13, name = "treasury_tokens", desc = "Ore treasury token account", writable)]
|
||||
#[account(14, name = "token_program", desc = "SPL token program")]
|
||||
Reset = 5,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
#[account(2, name = "proof", desc = "Ore proof account", writable)]
|
||||
#[account(3, name = "sender", desc = "Signer token account", writable)]
|
||||
#[account(4, name = "treasury_tokens", desc = "Ore treasury token account", writable)]
|
||||
#[account(5, name = "token_program", desc = "SPL token program")]
|
||||
Stake = 6,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
#[account(2, name = "proof", desc = "Ore proof account", writable)]
|
||||
Update = 7,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
#[account(2, name = "beneficiary", desc = "Beneficiary token account", writable)]
|
||||
#[account(3, name = "sender", desc = "Signer token account", writable)]
|
||||
#[account(4, name = "treasury", desc = "Ore treasury account", writable)]
|
||||
#[account(5, name = "mint", desc = "Ore token mint account", writable)]
|
||||
#[account(6, name = "mint_v1", desc = "Ore v1 token mint account", writable)]
|
||||
#[account(7, name = "token_program", desc = "SPL token program")]
|
||||
Upgrade = 8,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Admin signer", signer)]
|
||||
#[account(2, name = "bus_0", desc = "Ore bus account 0", writable)]
|
||||
#[account(3, name = "bus_1", desc = "Ore bus account 1", writable)]
|
||||
#[account(4, name = "bus_2", desc = "Ore bus account 2", writable)]
|
||||
#[account(5, name = "bus_3", desc = "Ore bus account 3", writable)]
|
||||
#[account(6, name = "bus_4", desc = "Ore bus account 4", writable)]
|
||||
#[account(7, name = "bus_5", desc = "Ore bus account 5", writable)]
|
||||
#[account(8, name = "bus_6", desc = "Ore bus account 6", writable)]
|
||||
#[account(9, name = "bus_7", desc = "Ore bus account 7", writable)]
|
||||
#[account(10, name = "metadata", desc = "Ore mint metadata account", writable)]
|
||||
#[account(11, name = "mint", desc = "Ore mint account", writable)]
|
||||
#[account(12, name = "noise", desc = "Ore noise account", writable)]
|
||||
#[account(13, name = "treasury", desc = "Ore treasury account", writable)]
|
||||
#[account(14, name = "treasury_tokens", desc = "Ore treasury token account", writable)]
|
||||
#[account(15, name = "system_program", desc = "Solana system program")]
|
||||
#[account(16, name = "token_program", desc = "SPL token program")]
|
||||
#[account(17, name = "associated_token_program", desc = "SPL associated token program")]
|
||||
#[account(18, name = "mpl_metadata_program", desc = "Metaplex metadata program")]
|
||||
#[account(19, name = "rent", desc = "Solana rent sysvar")]
|
||||
Initialize = 100,
|
||||
}
|
||||
|
||||
impl OreInstruction {
|
||||
pub fn to_vec(&self) -> Vec<u8> {
|
||||
vec![*self as u8]
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
|
||||
pub struct InitializeArgs {
|
||||
pub bus_0_bump: u8,
|
||||
pub bus_1_bump: u8,
|
||||
pub bus_2_bump: u8,
|
||||
pub bus_3_bump: u8,
|
||||
pub bus_4_bump: u8,
|
||||
pub bus_5_bump: u8,
|
||||
pub bus_6_bump: u8,
|
||||
pub bus_7_bump: u8,
|
||||
pub config_bump: u8,
|
||||
pub metadata_bump: u8,
|
||||
pub mint_bump: u8,
|
||||
pub treasury_bump: u8,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
|
||||
pub struct OpenArgs {
|
||||
pub bump: u8,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
|
||||
pub struct MineArgs {
|
||||
pub digest: [u8; 16],
|
||||
pub nonce: [u8; 8],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
|
||||
pub struct ClaimArgs {
|
||||
pub amount: [u8; 8],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
|
||||
pub struct StakeArgs {
|
||||
pub amount: [u8; 8],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
|
||||
pub struct UpgradeArgs {
|
||||
pub amount: [u8; 8],
|
||||
}
|
||||
|
||||
impl_to_bytes!(InitializeArgs);
|
||||
impl_to_bytes!(OpenArgs);
|
||||
impl_to_bytes!(MineArgs);
|
||||
impl_to_bytes!(ClaimArgs);
|
||||
impl_to_bytes!(StakeArgs);
|
||||
impl_to_bytes!(UpgradeArgs);
|
||||
|
||||
impl_instruction_from_bytes!(InitializeArgs);
|
||||
impl_instruction_from_bytes!(OpenArgs);
|
||||
impl_instruction_from_bytes!(MineArgs);
|
||||
impl_instruction_from_bytes!(ClaimArgs);
|
||||
impl_instruction_from_bytes!(StakeArgs);
|
||||
impl_instruction_from_bytes!(UpgradeArgs);
|
||||
|
||||
/// Builds a claim instruction.
|
||||
pub fn claim(signer: Pubkey, beneficiary: Pubkey, amount: u64) -> Instruction {
|
||||
let proof = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id()).0;
|
||||
let treasury_tokens = spl_associated_token_account::get_associated_token_address(
|
||||
&TREASURY_ADDRESS,
|
||||
&MINT_ADDRESS,
|
||||
);
|
||||
Instruction {
|
||||
program_id: crate::id(),
|
||||
accounts: vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new(beneficiary, false),
|
||||
AccountMeta::new(MINT_ADDRESS, false),
|
||||
AccountMeta::new(proof, false),
|
||||
AccountMeta::new_readonly(TREASURY_ADDRESS, false),
|
||||
AccountMeta::new(treasury_tokens, false),
|
||||
AccountMeta::new_readonly(spl_token::id(), false),
|
||||
],
|
||||
data: [
|
||||
OreInstruction::Claim.to_vec(),
|
||||
ClaimArgs {
|
||||
amount: amount.to_le_bytes(),
|
||||
}
|
||||
.to_bytes()
|
||||
.to_vec(),
|
||||
]
|
||||
.concat(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds a close instruction.
|
||||
pub fn close(signer: Pubkey) -> Instruction {
|
||||
let proof_pda = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id());
|
||||
Instruction {
|
||||
program_id: crate::id(),
|
||||
accounts: vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new(proof_pda.0, false),
|
||||
AccountMeta::new_readonly(solana_program::system_program::id(), false),
|
||||
],
|
||||
data: OreInstruction::Close.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds a mine instruction.
|
||||
pub fn mine(signer: Pubkey, bus: Pubkey, solution: Solution) -> Instruction {
|
||||
let proof = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id()).0;
|
||||
Instruction {
|
||||
program_id: crate::id(),
|
||||
accounts: vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new(bus, false),
|
||||
AccountMeta::new_readonly(CONFIG_ADDRESS, false),
|
||||
AccountMeta::new(proof, false),
|
||||
AccountMeta::new_readonly(sysvar::instructions::id(), false),
|
||||
AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
|
||||
],
|
||||
data: [
|
||||
OreInstruction::Mine.to_vec(),
|
||||
MineArgs {
|
||||
digest: solution.d,
|
||||
nonce: solution.n,
|
||||
}
|
||||
.to_bytes()
|
||||
.to_vec(),
|
||||
]
|
||||
.concat(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds an open instruction.
|
||||
pub fn open(signer: Pubkey, miner: Pubkey) -> Instruction {
|
||||
let proof_pda = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id());
|
||||
Instruction {
|
||||
program_id: crate::id(),
|
||||
accounts: vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new_readonly(miner, false),
|
||||
AccountMeta::new(proof_pda.0, false),
|
||||
AccountMeta::new_readonly(solana_program::system_program::id(), false),
|
||||
AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
|
||||
],
|
||||
data: [
|
||||
OreInstruction::Open.to_vec(),
|
||||
OpenArgs { bump: proof_pda.1 }.to_bytes().to_vec(),
|
||||
]
|
||||
.concat(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds a reset instruction.
|
||||
pub fn reset(signer: Pubkey) -> Instruction {
|
||||
let treasury_tokens = spl_associated_token_account::get_associated_token_address(
|
||||
&TREASURY_ADDRESS,
|
||||
&MINT_ADDRESS,
|
||||
);
|
||||
Instruction {
|
||||
program_id: crate::id(),
|
||||
accounts: vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new(BUS_ADDRESSES[0], false),
|
||||
AccountMeta::new(BUS_ADDRESSES[1], false),
|
||||
AccountMeta::new(BUS_ADDRESSES[2], false),
|
||||
AccountMeta::new(BUS_ADDRESSES[3], false),
|
||||
AccountMeta::new(BUS_ADDRESSES[4], false),
|
||||
AccountMeta::new(BUS_ADDRESSES[5], false),
|
||||
AccountMeta::new(BUS_ADDRESSES[6], false),
|
||||
AccountMeta::new(BUS_ADDRESSES[7], false),
|
||||
AccountMeta::new(CONFIG_ADDRESS, false),
|
||||
AccountMeta::new(MINT_ADDRESS, false),
|
||||
AccountMeta::new(TREASURY_ADDRESS, false),
|
||||
AccountMeta::new(treasury_tokens, false),
|
||||
AccountMeta::new_readonly(spl_token::id(), false),
|
||||
],
|
||||
data: OreInstruction::Reset.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a stake instruction.
|
||||
pub fn stake(signer: Pubkey, sender: Pubkey, amount: u64) -> Instruction {
|
||||
let proof = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id()).0;
|
||||
let treasury_tokens = spl_associated_token_account::get_associated_token_address(
|
||||
&TREASURY_ADDRESS,
|
||||
&MINT_ADDRESS,
|
||||
);
|
||||
Instruction {
|
||||
program_id: crate::id(),
|
||||
accounts: vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new(proof, false),
|
||||
AccountMeta::new(sender, false),
|
||||
AccountMeta::new(treasury_tokens, false),
|
||||
AccountMeta::new_readonly(spl_token::id(), false),
|
||||
],
|
||||
data: [
|
||||
OreInstruction::Stake.to_vec(),
|
||||
StakeArgs {
|
||||
amount: amount.to_le_bytes(),
|
||||
}
|
||||
.to_bytes()
|
||||
.to_vec(),
|
||||
]
|
||||
.concat(),
|
||||
}
|
||||
}
|
||||
|
||||
// Build an update instruction.
|
||||
pub fn update(signer: Pubkey, miner: Pubkey) -> Instruction {
|
||||
let proof = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id()).0;
|
||||
Instruction {
|
||||
program_id: crate::id(),
|
||||
accounts: vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new_readonly(miner, false),
|
||||
AccountMeta::new(proof, false),
|
||||
],
|
||||
data: OreInstruction::Update.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
// Build an upgrade instruction.
|
||||
pub fn upgrade(signer: Pubkey, beneficiary: Pubkey, sender: Pubkey, amount: u64) -> Instruction {
|
||||
Instruction {
|
||||
program_id: crate::id(),
|
||||
accounts: vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new(beneficiary, false),
|
||||
AccountMeta::new(MINT_ADDRESS, false),
|
||||
AccountMeta::new(MINT_V1_ADDRESS, false),
|
||||
AccountMeta::new(sender, false),
|
||||
AccountMeta::new(TREASURY_ADDRESS, false),
|
||||
AccountMeta::new_readonly(spl_token::id(), false),
|
||||
],
|
||||
data: [
|
||||
OreInstruction::Upgrade.to_vec(),
|
||||
UpgradeArgs {
|
||||
amount: amount.to_le_bytes(),
|
||||
}
|
||||
.to_bytes()
|
||||
.to_vec(),
|
||||
]
|
||||
.concat(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds an initialize instruction.
|
||||
pub fn initialize(signer: Pubkey) -> Instruction {
|
||||
let bus_pdas = [
|
||||
Pubkey::find_program_address(&[BUS, &[0]], &crate::id()),
|
||||
Pubkey::find_program_address(&[BUS, &[1]], &crate::id()),
|
||||
Pubkey::find_program_address(&[BUS, &[2]], &crate::id()),
|
||||
Pubkey::find_program_address(&[BUS, &[3]], &crate::id()),
|
||||
Pubkey::find_program_address(&[BUS, &[4]], &crate::id()),
|
||||
Pubkey::find_program_address(&[BUS, &[5]], &crate::id()),
|
||||
Pubkey::find_program_address(&[BUS, &[6]], &crate::id()),
|
||||
Pubkey::find_program_address(&[BUS, &[7]], &crate::id()),
|
||||
];
|
||||
let config_pda = Pubkey::find_program_address(&[CONFIG], &crate::id());
|
||||
let mint_pda = Pubkey::find_program_address(&[MINT, MINT_NOISE.as_slice()], &crate::id());
|
||||
let treasury_pda = Pubkey::find_program_address(&[TREASURY], &crate::id());
|
||||
let treasury_tokens =
|
||||
spl_associated_token_account::get_associated_token_address(&treasury_pda.0, &mint_pda.0);
|
||||
let metadata_pda = Pubkey::find_program_address(
|
||||
&[
|
||||
METADATA,
|
||||
mpl_token_metadata::ID.as_ref(),
|
||||
mint_pda.0.as_ref(),
|
||||
],
|
||||
&mpl_token_metadata::ID,
|
||||
);
|
||||
Instruction {
|
||||
program_id: crate::id(),
|
||||
accounts: vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new(bus_pdas[0].0, false),
|
||||
AccountMeta::new(bus_pdas[1].0, false),
|
||||
AccountMeta::new(bus_pdas[2].0, false),
|
||||
AccountMeta::new(bus_pdas[3].0, false),
|
||||
AccountMeta::new(bus_pdas[4].0, false),
|
||||
AccountMeta::new(bus_pdas[5].0, false),
|
||||
AccountMeta::new(bus_pdas[6].0, false),
|
||||
AccountMeta::new(bus_pdas[7].0, false),
|
||||
AccountMeta::new(config_pda.0, false),
|
||||
AccountMeta::new(metadata_pda.0, false),
|
||||
AccountMeta::new(mint_pda.0, false),
|
||||
AccountMeta::new(treasury_pda.0, false),
|
||||
AccountMeta::new(treasury_tokens, 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(mpl_token_metadata::ID, false),
|
||||
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
||||
],
|
||||
data: [
|
||||
OreInstruction::Initialize.to_vec(),
|
||||
InitializeArgs {
|
||||
bus_0_bump: bus_pdas[0].1,
|
||||
bus_1_bump: bus_pdas[1].1,
|
||||
bus_2_bump: bus_pdas[2].1,
|
||||
bus_3_bump: bus_pdas[3].1,
|
||||
bus_4_bump: bus_pdas[4].1,
|
||||
bus_5_bump: bus_pdas[5].1,
|
||||
bus_6_bump: bus_pdas[6].1,
|
||||
bus_7_bump: bus_pdas[7].1,
|
||||
config_bump: config_pda.1,
|
||||
metadata_bump: metadata_pda.1,
|
||||
mint_bump: mint_pda.1,
|
||||
treasury_bump: treasury_pda.1,
|
||||
}
|
||||
.to_bytes()
|
||||
.to_vec(),
|
||||
]
|
||||
.concat(),
|
||||
}
|
||||
}
|
||||
11
api/src/lib.rs
Normal file
11
api/src/lib.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
pub mod consts;
|
||||
pub mod error;
|
||||
pub mod event;
|
||||
pub mod instruction;
|
||||
pub mod state;
|
||||
|
||||
pub(crate) use utils;
|
||||
|
||||
use solana_program::declare_id;
|
||||
|
||||
declare_id!("mineRHF5r6S7HyD9SppBfVMXMavDkJsxwGesEvxZr2A");
|
||||
31
api/src/state/bus.rs
Normal file
31
api/src/state/bus.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use shank::ShankAccount;
|
||||
|
||||
use crate::utils::{impl_account_from_bytes, impl_to_bytes, Discriminator};
|
||||
|
||||
use super::AccountDiscriminator;
|
||||
|
||||
/// Bus accounts are responsible for distributing mining rewards.
|
||||
/// There are 8 busses total to minimize write-lock contention and allow for parallel mine operations.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Pod, ShankAccount, Zeroable)]
|
||||
pub struct Bus {
|
||||
/// The ID of the bus account.
|
||||
pub id: u64,
|
||||
|
||||
/// The remaining rewards this bus has left to payout in the current epoch.
|
||||
pub rewards: u64,
|
||||
|
||||
/// The rewards this bus would have paid out in the current epoch if there no limit.
|
||||
/// Used to calculate the updated reward rate.
|
||||
pub theoretical_rewards: u64,
|
||||
}
|
||||
|
||||
impl Discriminator for Bus {
|
||||
fn discriminator() -> u8 {
|
||||
AccountDiscriminator::Bus.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl_to_bytes!(Bus);
|
||||
impl_account_from_bytes!(Bus);
|
||||
36
api/src/state/config.rs
Normal file
36
api/src/state/config.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use shank::ShankAccount;
|
||||
use solana_program::pubkey::Pubkey;
|
||||
|
||||
use crate::utils::{impl_account_from_bytes, impl_to_bytes, Discriminator};
|
||||
|
||||
use super::AccountDiscriminator;
|
||||
|
||||
/// Config is a singleton account which manages admin configurable variables.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Pod, ShankAccount, Zeroable)]
|
||||
pub struct Config {
|
||||
/// The admin authority with permission to update the difficulty.
|
||||
pub admin: Pubkey,
|
||||
|
||||
/// The base reward rate paid out for a hash of minimum difficulty.
|
||||
pub base_reward_rate: u64,
|
||||
|
||||
/// The timestamp of the last reset.
|
||||
pub last_reset_at: i64,
|
||||
|
||||
/// The largest known stake balance on the network.
|
||||
pub max_stake: u64,
|
||||
|
||||
/// The address of the proof account with the highest stake balance.
|
||||
pub top_staker: Pubkey,
|
||||
}
|
||||
|
||||
impl Discriminator for Config {
|
||||
fn discriminator() -> u8 {
|
||||
AccountDiscriminator::Config.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl_to_bytes!(Config);
|
||||
impl_account_from_bytes!(Config);
|
||||
20
api/src/state/mod.rs
Normal file
20
api/src/state/mod.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
mod bus;
|
||||
mod config;
|
||||
mod proof;
|
||||
mod treasury;
|
||||
|
||||
pub use bus::*;
|
||||
pub use config::*;
|
||||
pub use proof::*;
|
||||
pub use treasury::*;
|
||||
|
||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
|
||||
pub enum AccountDiscriminator {
|
||||
Bus = 100,
|
||||
Config = 101,
|
||||
Proof = 102,
|
||||
Treasury = 103,
|
||||
}
|
||||
49
api/src/state/proof.rs
Normal file
49
api/src/state/proof.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use shank::ShankAccount;
|
||||
use solana_program::pubkey::Pubkey;
|
||||
|
||||
use crate::utils::{impl_account_from_bytes, impl_to_bytes, Discriminator};
|
||||
|
||||
use super::AccountDiscriminator;
|
||||
|
||||
/// Proof accounts track a miner's current hash, claimable rewards, and lifetime stats.
|
||||
/// Every miner is allowed one proof account which is required by the program to mine or claim rewards.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Pod, ShankAccount, Zeroable)]
|
||||
pub struct Proof {
|
||||
/// The signer authorized to use this proof.
|
||||
pub authority: Pubkey,
|
||||
|
||||
/// The quantity of tokens this miner has staked or earned.
|
||||
pub balance: u64,
|
||||
|
||||
/// The current mining challenge.
|
||||
pub challenge: [u8; 32],
|
||||
|
||||
/// The last hash the miner provided.
|
||||
pub last_hash: [u8; 32],
|
||||
|
||||
/// The last time this account provided a hash.
|
||||
pub last_hash_at: i64,
|
||||
|
||||
/// The last time stake was deposited into this account.
|
||||
pub last_stake_at: i64,
|
||||
|
||||
/// The keypair which has permission to submit hashes for mining.
|
||||
pub miner: Pubkey,
|
||||
|
||||
/// The total lifetime hashes provided by this miner.
|
||||
pub total_hashes: u64,
|
||||
|
||||
/// The total lifetime rewards distributed to this miner.
|
||||
pub total_rewards: u64,
|
||||
}
|
||||
|
||||
impl Discriminator for Proof {
|
||||
fn discriminator() -> u8 {
|
||||
AccountDiscriminator::Proof.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl_to_bytes!(Proof);
|
||||
impl_account_from_bytes!(Proof);
|
||||
21
api/src/state/treasury.rs
Normal file
21
api/src/state/treasury.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use shank::ShankAccount;
|
||||
|
||||
use crate::utils::{impl_account_from_bytes, impl_to_bytes, Discriminator};
|
||||
|
||||
use super::AccountDiscriminator;
|
||||
|
||||
/// Treasury is a singleton account which manages all program wide variables.
|
||||
/// It is the mint authority for the Ore token and also the authority of the program-owned token account.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Pod, ShankAccount, Zeroable)]
|
||||
pub struct Treasury {}
|
||||
|
||||
impl Discriminator for Treasury {
|
||||
fn discriminator() -> u8 {
|
||||
AccountDiscriminator::Treasury.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl_to_bytes!(Treasury);
|
||||
impl_account_from_bytes!(Treasury);
|
||||
Reference in New Issue
Block a user