#![deny(rustdoc::all)]
#![allow(rustdoc::missing_doc_code_examples)]
#![allow(deprecated)]
#[macro_use]
mod macros;
mod account_validators;
mod processor;
use processor::*;
pub(crate) mod account_conversions;
pub(crate) mod mm_cpi;
pub mod events;
pub mod state;
use anchor_lang::prelude::*;
use anchor_spl::token::{Mint, Token, TokenAccount};
use vipers::prelude::*;
pub use state::*;
#[cfg(not(feature = "no-entrypoint"))]
solana_security_txt::security_txt! {
name: "Quarry Merge Mine",
project_url: "https://quarry.so",
contacts: "email:team@quarry.so",
policy: "https://github.com/QuarryProtocol/quarry/blob/master/SECURITY.md",
source_code: "https://github.com/QuarryProtocol/quarry",
auditors: "Quantstamp"
}
declare_id!("QMMD16kjauP5knBwxNUJRZ1Z5o3deBuFrqVjBVmmqto");
#[deny(clippy::integer_arithmetic, clippy::float_arithmetic)]
#[program]
pub mod quarry_merge_mine {
use super::*;
#[deprecated(since = "5.0.0", note = "Use `new_pool_v2` instead.")]
#[access_control(ctx.accounts.validate())]
pub fn new_pool(ctx: Context<NewPool>, _bump: u8, _mint_bump: u8) -> Result<()> {
processor::init::new_pool(ctx)
}
#[access_control(ctx.accounts.validate())]
pub fn new_pool_v2(ctx: Context<NewPool>) -> Result<()> {
processor::init::new_pool(ctx)
}
#[deprecated(since = "5.0.0", note = "Use `init_merge_miner_v2` instead.")]
#[access_control(ctx.accounts.validate())]
pub fn init_merge_miner(ctx: Context<InitMergeMiner>, _bump: u8) -> Result<()> {
processor::init::init_merge_miner(ctx)
}
#[access_control(ctx.accounts.validate())]
pub fn init_merge_miner_v2(ctx: Context<InitMergeMiner>) -> Result<()> {
processor::init::init_merge_miner(ctx)
}
#[deprecated(since = "5.0.0", note = "Use `init_miner_v2` instead.")]
#[access_control(ctx.accounts.validate())]
pub fn init_miner(ctx: Context<InitMiner>, _bump: u8) -> Result<()> {
processor::init::init_miner(ctx)
}
#[access_control(ctx.accounts.validate())]
pub fn init_miner_v2(ctx: Context<InitMiner>) -> Result<()> {
processor::init::init_miner(ctx)
}
#[access_control(ctx.accounts.validate())]
pub fn stake_primary_miner(ctx: Context<QuarryStakePrimary>) -> Result<()> {
processor::deposit::stake_primary_miner(ctx)
}
#[access_control(ctx.accounts.validate())]
pub fn stake_replica_miner(ctx: Context<QuarryStakeReplica>) -> Result<()> {
processor::deposit::stake_replica_miner(ctx)
}
#[access_control(ctx.accounts.validate())]
pub fn unstake_primary_miner(ctx: Context<QuarryStakePrimary>, amount: u64) -> Result<()> {
processor::withdraw::unstake_primary_miner(ctx, amount)
}
#[access_control(ctx.accounts.validate())]
pub fn unstake_all_replica_miner(ctx: Context<QuarryStakeReplica>) -> Result<()> {
processor::withdraw::unstake_all_replica_miner(ctx)
}
#[access_control(ctx.accounts.validate())]
pub fn withdraw_tokens(ctx: Context<WithdrawTokens>) -> Result<()> {
processor::withdraw::withdraw_tokens(ctx)
}
#[access_control(ctx.accounts.validate())]
pub fn rescue_tokens(ctx: Context<RescueTokens>) -> Result<()> {
processor::rescue_tokens::handler(ctx)
}
#[access_control(ctx.accounts.validate())]
pub fn claim_rewards(ctx: Context<ClaimRewards>) -> Result<()> {
processor::claim::claim_rewards(ctx)
}
}
#[derive(Accounts)]
pub struct NewPool<'info> {
#[account(
init,
seeds = [
b"MergePool".as_ref(),
primary_mint.key().to_bytes().as_ref()
],
bump,
payer = payer,
space = 8 + MergePool::LEN
)]
pub pool: Account<'info, MergePool>,
pub primary_mint: Account<'info, Mint>,
#[account(
init,
seeds = [
b"ReplicaMint".as_ref(),
pool.key().to_bytes().as_ref()
],
mint::decimals = primary_mint.decimals,
mint::authority = pool,
bump,
payer = payer
)]
pub replica_mint: Account<'info, Mint>,
#[account(mut)]
pub payer: Signer<'info>,
pub token_program: Program<'info, Token>,
pub system_program: Program<'info, System>,
pub rent: Sysvar<'info, Rent>,
}
#[derive(Accounts)]
pub struct InitMergeMiner<'info> {
pub pool: Account<'info, MergePool>,
pub owner: UncheckedAccount<'info>,
#[account(
init,
seeds = [
b"MergeMiner".as_ref(),
pool.key().to_bytes().as_ref(),
owner.key().to_bytes().as_ref()
],
bump,
payer = payer,
space = 8 + MergeMiner::LEN
)]
pub mm: Account<'info, MergeMiner>,
#[account(mut)]
pub payer: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[derive(Accounts)]
pub struct InitMiner<'info> {
pub pool: Account<'info, MergePool>,
pub mm: Account<'info, MergeMiner>,
#[account(mut)]
pub miner: SystemAccount<'info>,
#[account(mut)]
pub quarry: Box<Account<'info, quarry_mine::Quarry>>,
pub rewarder: Box<Account<'info, quarry_mine::Rewarder>>,
pub token_mint: Box<Account<'info, Mint>>,
pub miner_vault: Account<'info, TokenAccount>,
#[account(mut)]
pub payer: Signer<'info>,
pub mine_program: Program<'info, quarry_mine::program::QuarryMine>,
pub system_program: Program<'info, System>,
pub token_program: Program<'info, Token>,
}
#[derive(Accounts)]
pub struct WithdrawTokens<'info> {
pub owner: Signer<'info>,
pub pool: Account<'info, MergePool>,
#[account(mut)]
pub mm: Account<'info, MergeMiner>,
pub withdraw_mint: Account<'info, Mint>,
#[account(mut)]
pub mm_token_account: Account<'info, TokenAccount>,
#[account(mut)]
pub token_destination: Account<'info, TokenAccount>,
pub token_program: Program<'info, Token>,
}
#[derive(Accounts)]
pub struct ClaimRewards<'info> {
#[account(mut)]
pub mint_wrapper: Box<Account<'info, quarry_mint_wrapper::MintWrapper>>,
pub mint_wrapper_program: Program<'info, quarry_mint_wrapper::program::QuarryMintWrapper>,
#[account(mut)]
pub minter: Box<Account<'info, quarry_mint_wrapper::Minter>>,
#[account(mut)]
pub rewards_token_mint: Box<Account<'info, Mint>>,
#[account(mut)]
pub rewards_token_account: Box<Account<'info, TokenAccount>>,
#[account(mut)]
pub claim_fee_token_account: Box<Account<'info, TokenAccount>>,
#[account(mut)]
pub stake_token_account: Box<Account<'info, TokenAccount>>,
pub stake: QuarryStake<'info>,
}
#[derive(Accounts)]
pub struct QuarryStakePrimary<'info> {
#[account(constraint = mm_owner.key() == stake.mm.owner)]
pub mm_owner: Signer<'info>,
#[account(mut)]
pub mm_primary_token_account: Account<'info, TokenAccount>,
pub stake: QuarryStake<'info>,
}
#[derive(Accounts)]
pub struct QuarryStakeReplica<'info> {
#[account(constraint = mm_owner.key() == stake.mm.owner)]
pub mm_owner: Signer<'info>,
#[account(mut)]
pub replica_mint: Account<'info, Mint>,
#[account(mut)]
pub replica_mint_token_account: Account<'info, TokenAccount>,
pub stake: QuarryStake<'info>,
}
#[derive(Accounts)]
pub struct QuarryStake<'info> {
#[account(mut)]
pub pool: Account<'info, MergePool>,
#[account(mut, has_one = pool)]
pub mm: Account<'info, MergeMiner>,
pub rewarder: Box<Account<'info, quarry_mine::Rewarder>>,
#[account(mut, has_one = rewarder)]
pub quarry: Box<Account<'info, quarry_mine::Quarry>>,
#[account(
mut,
has_one = quarry,
constraint = miner.authority == mm.key()
)]
pub miner: Box<Account<'info, quarry_mine::Miner>>,
#[account(mut, constraint = miner_vault.key() == miner.token_vault_key)]
pub miner_vault: Account<'info, TokenAccount>,
pub token_program: Program<'info, Token>,
pub mine_program: Program<'info, quarry_mine::program::QuarryMine>,
}
#[error_code]
pub enum ErrorCode {
#[msg("Unauthorized.")]
Unauthorized,
#[msg("Insufficient balance.")]
InsufficientBalance,
#[msg("Invalid miner for the given quarry.")]
InvalidMiner,
#[msg("Cannot withdraw a replica mint.")]
CannotWithdrawReplicaMint,
#[msg("User must first withdraw from all replica quarries.")]
OutstandingReplicaTokens,
#[msg("The replica mint must have the same number of decimals as the primary mint.")]
ReplicaDecimalsMismatch,
#[msg("The replica mint must have zero supply.")]
ReplicaNonZeroSupply,
}