quarry_operator/
lib.rs

1//! Delegates Quarry Rewarder authority roles.
2#![deny(rustdoc::all)]
3#![allow(rustdoc::missing_doc_code_examples)]
4#![allow(deprecated)]
5
6use anchor_lang::prelude::*;
7use quarry_mine::{Quarry, Rewarder};
8use vipers::prelude::*;
9
10mod account_validators;
11mod instructions;
12mod macros;
13mod state;
14
15use instructions::*;
16pub use state::*;
17
18declare_id!("QoP6NfrQbaGnccXQrMLUkog2tQZ4C1RFgJcwDnT8Kmz");
19
20#[cfg(not(feature = "no-entrypoint"))]
21solana_security_txt::security_txt! {
22    name: "Quarry Operator",
23    project_url: "https://quarry.so",
24    contacts: "email:team@quarry.so",
25    policy: "https://github.com/QuarryProtocol/quarry/blob/master/SECURITY.md",
26
27    source_code: "https://github.com/QuarryProtocol/quarry",
28    auditors: "Quantstamp"
29}
30
31/// Quarry Operator program.
32#[program]
33pub mod quarry_operator {
34    use super::*;
35
36    /// Creates a new [Operator].
37    #[deprecated(since = "5.0.0", note = "Use `create_operator_v2` instead.")]
38    #[access_control(ctx.accounts.validate())]
39    pub fn create_operator(ctx: Context<CreateOperator>, _bump: u8) -> Result<()> {
40        instructions::create_operator::handler(ctx)
41    }
42
43    /// Creates a new [Operator].
44    ///
45    /// The V2 variant removes the need for supplying the bump.
46    #[access_control(ctx.accounts.validate())]
47    pub fn create_operator_v2(ctx: Context<CreateOperator>) -> Result<()> {
48        instructions::create_operator::handler(ctx)
49    }
50
51    /// Sets the account that can set roles.
52    #[access_control(ctx.accounts.validate())]
53    pub fn set_admin(ctx: Context<SetRole>) -> Result<()> {
54        let operator = &mut ctx.accounts.operator;
55        operator.admin = ctx.accounts.delegate.key();
56        operator.record_update()?;
57        Ok(())
58    }
59
60    /// Sets who can call [quarry_mine::quarry_mine::set_annual_rewards].
61    #[access_control(ctx.accounts.validate())]
62    pub fn set_rate_setter(ctx: Context<SetRole>) -> Result<()> {
63        let operator = &mut ctx.accounts.operator;
64        operator.rate_setter = ctx.accounts.delegate.key();
65        operator.record_update()?;
66        Ok(())
67    }
68
69    /// Sets who can call [quarry_mine::quarry_mine::create_quarry].
70    #[access_control(ctx.accounts.validate())]
71    pub fn set_quarry_creator(ctx: Context<SetRole>) -> Result<()> {
72        let operator = &mut ctx.accounts.operator;
73        operator.quarry_creator = ctx.accounts.delegate.key();
74        operator.record_update()?;
75        Ok(())
76    }
77
78    /// Sets who can call [quarry_mine::quarry_mine::set_rewards_share].
79    #[access_control(ctx.accounts.validate())]
80    pub fn set_share_allocator(ctx: Context<SetRole>) -> Result<()> {
81        let operator = &mut ctx.accounts.operator;
82        operator.share_allocator = ctx.accounts.delegate.key();
83        operator.record_update()?;
84        Ok(())
85    }
86
87    /// Calls [quarry_mine::quarry_mine::set_annual_rewards].
88    #[access_control(ctx.accounts.validate())]
89    pub fn delegate_set_annual_rewards(
90        ctx: Context<DelegateSetAnnualRewards>,
91        new_rate: u64,
92    ) -> Result<()> {
93        let operator = &ctx.accounts.with_delegate.operator;
94        let signer_seeds: &[&[&[u8]]] = &[gen_operator_signer_seeds!(operator)];
95        quarry_mine::cpi::set_annual_rewards(
96            CpiContext::new_with_signer(
97                ctx.accounts
98                    .with_delegate
99                    .quarry_mine_program
100                    .to_account_info(),
101                quarry_mine::cpi::accounts::SetAnnualRewards {
102                    auth: ctx.accounts.with_delegate.to_auth_accounts(),
103                },
104                signer_seeds,
105            ),
106            new_rate,
107        )?;
108        Ok(())
109    }
110
111    /// Calls [quarry_mine::quarry_mine::create_quarry_v2].
112    #[access_control(ctx.accounts.validate())]
113    pub fn delegate_create_quarry(ctx: Context<DelegateCreateQuarry>, _bump: u8) -> Result<()> {
114        instructions::delegate_create_quarry::handler(ctx)
115    }
116
117    /// Calls [quarry_mine::quarry_mine::create_quarry_v2].
118    #[access_control(ctx.accounts.validate())]
119    pub fn delegate_create_quarry_v2(ctx: Context<DelegateCreateQuarryV2>) -> Result<()> {
120        instructions::delegate_create_quarry_v2::handler(ctx)
121    }
122
123    /// Calls [quarry_mine::quarry_mine::set_rewards_share].
124    #[access_control(ctx.accounts.validate())]
125    pub fn delegate_set_rewards_share(
126        ctx: Context<DelegateSetRewardsShare>,
127        new_share: u64,
128    ) -> Result<()> {
129        let operator = &ctx.accounts.with_delegate.operator;
130        let signer_seeds: &[&[&[u8]]] = &[gen_operator_signer_seeds!(operator)];
131        quarry_mine::cpi::set_rewards_share(
132            CpiContext::new_with_signer(
133                ctx.accounts
134                    .with_delegate
135                    .quarry_mine_program
136                    .to_account_info(),
137                quarry_mine::cpi::accounts::SetRewardsShare {
138                    auth: ctx.accounts.with_delegate.to_auth_accounts(),
139                    quarry: ctx.accounts.quarry.to_account_info(),
140                },
141                signer_seeds,
142            ),
143            new_share,
144        )?;
145        Ok(())
146    }
147
148    /// Calls [quarry_mine::quarry_mine::set_famine].
149    #[access_control(ctx.accounts.validate())]
150    pub fn delegate_set_famine(ctx: Context<DelegateSetFamine>, famine_ts: i64) -> Result<()> {
151        let operator = &ctx.accounts.with_delegate.operator;
152        let signer_seeds: &[&[&[u8]]] = &[gen_operator_signer_seeds!(operator)];
153
154        quarry_mine::cpi::set_famine(
155            CpiContext::new_with_signer(
156                ctx.accounts
157                    .with_delegate
158                    .quarry_mine_program
159                    .to_account_info(),
160                quarry_mine::cpi::accounts::SetFamine {
161                    auth: ctx.accounts.with_delegate.to_readonly_auth_accounts(),
162                    quarry: ctx.accounts.quarry.to_account_info(),
163                },
164                signer_seeds,
165            ),
166            famine_ts,
167        )
168    }
169}
170
171// --------------------------------
172// Instructions
173// --------------------------------
174
175/// Accounts for setting roles.
176#[derive(Accounts)]
177pub struct SetRole<'info> {
178    /// The [Operator] of the [Rewarder].
179    #[account(mut)]
180    pub operator: Account<'info, Operator>,
181    /// The [Operator::admin].
182    pub admin: Signer<'info>,
183    /// The account to give the role to.
184    /// CHECK: Ok
185    pub delegate: UncheckedAccount<'info>,
186}
187
188/// Accounts for [crate::quarry_operator::delegate_set_annual_rewards].
189#[derive(Accounts)]
190pub struct DelegateSetAnnualRewards<'info> {
191    /// Delegate accounts.
192    pub with_delegate: WithDelegate<'info>,
193}
194
195/// Accounts for [crate::quarry_operator::delegate_set_rewards_share].
196#[derive(Accounts)]
197pub struct DelegateSetRewardsShare<'info> {
198    /// Delegate accounts.
199    pub with_delegate: WithDelegate<'info>,
200    /// [Quarry].
201    #[account(
202        mut,
203        constraint = quarry.rewarder == with_delegate.rewarder.key()
204    )]
205    pub quarry: Account<'info, Quarry>,
206}
207
208/// Accounts for [crate::quarry_operator::delegate_set_famine].
209#[derive(Accounts)]
210pub struct DelegateSetFamine<'info> {
211    /// Delegate accounts.
212    pub with_delegate: WithDelegate<'info>,
213    /// [Quarry].
214    #[account(
215        mut,
216        constraint = quarry.rewarder == with_delegate.rewarder.key()
217    )]
218    pub quarry: Account<'info, Quarry>,
219}
220
221/// Accounts struct for instructions that must be signed by one of the delegates on the [Operator].
222#[derive(Accounts, Clone)]
223pub struct WithDelegate<'info> {
224    /// The [Operator] of the [Rewarder].
225    #[account(mut, has_one = rewarder)]
226    pub operator: Account<'info, Operator>,
227    /// The delegated account in one of the [Operator] roles.
228    pub delegate: Signer<'info>,
229    /// The [Rewarder].
230    #[account(
231        mut,
232        constraint = rewarder.authority == operator.key() @ ErrorCode::OperatorNotRewarderAuthority
233    )]
234    pub rewarder: Account<'info, Rewarder>,
235    /// Quarry mine
236    pub quarry_mine_program: Program<'info, quarry_mine::program::QuarryMine>,
237}
238
239impl<'info> WithDelegate<'info> {
240    /// Creates the [quarry_mine::cpi::accounts::MutableRewarderWithAuthority] accounts.
241    pub fn to_auth_accounts(
242        &self,
243    ) -> quarry_mine::cpi::accounts::MutableRewarderWithAuthority<'info> {
244        quarry_mine::cpi::accounts::MutableRewarderWithAuthority {
245            authority: self.operator.to_account_info(),
246            rewarder: self.rewarder.to_account_info(),
247        }
248    }
249
250    /// Creates the [quarry_mine::cpi::accounts::MutableRewarderWithAuthority] accounts.
251    pub fn to_readonly_auth_accounts(
252        &self,
253    ) -> quarry_mine::cpi::accounts::ReadOnlyRewarderWithAuthority<'info> {
254        quarry_mine::cpi::accounts::ReadOnlyRewarderWithAuthority {
255            authority: self.operator.to_account_info(),
256            rewarder: self.rewarder.to_account_info(),
257        }
258    }
259}
260
261/// Errors
262#[error_code]
263pub enum ErrorCode {
264    #[msg("Signer is not authorized to perform this action.")]
265    Unauthorized,
266    #[msg("Pending authority must be set to the created operator.")]
267    PendingAuthorityNotSet,
268    #[msg("Operator is not the Rewarder authority.")]
269    OperatorNotRewarderAuthority,
270}