72 lines
2.1 KiB
Rust
72 lines
2.1 KiB
Rust
//! counter is an example program that depends on an external interface
|
|
//! that another program must implement. This allows our program to depend
|
|
//! on another program, without knowing anything about it other than the fact
|
|
//! that it implements the `Auth` trait.
|
|
//!
|
|
//! Here, we have a counter, where, in order to set the count, the `Auth`
|
|
//! program must first approve the transaction.
|
|
|
|
use anchor_lang::prelude::*;
|
|
|
|
#[program]
|
|
pub mod counter {
|
|
use super::*;
|
|
|
|
#[state]
|
|
pub struct Counter {
|
|
pub count: u64,
|
|
pub auth_program: Pubkey,
|
|
}
|
|
|
|
impl Counter {
|
|
pub fn new(_ctx: Context<Empty>, auth_program: Pubkey) -> Result<Self> {
|
|
Ok(Self {
|
|
count: 0,
|
|
auth_program,
|
|
})
|
|
}
|
|
|
|
#[access_control(SetCount::accounts(&self, &ctx))]
|
|
pub fn set_count(&mut self, ctx: Context<SetCount>, new_count: u64) -> Result<()> {
|
|
// Ask the auth program if we should approve the transaction.
|
|
let cpi_program = ctx.accounts.auth_program.clone();
|
|
let cpi_ctx = CpiContext::new(cpi_program, Empty {});
|
|
auth::is_authorized(cpi_ctx, self.count, new_count)?;
|
|
|
|
// Approved, so update.
|
|
self.count = new_count;
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Accounts)]
|
|
pub struct Empty {}
|
|
|
|
#[derive(Accounts)]
|
|
pub struct SetCount<'info> {
|
|
auth_program: AccountInfo<'info>,
|
|
}
|
|
|
|
impl<'info> SetCount<'info> {
|
|
// Auxiliary account validation requiring program inputs. As a convention,
|
|
// we separate it from the business logic of the instruction handler itself.
|
|
pub fn accounts(counter: &Counter, ctx: &Context<SetCount>) -> Result<()> {
|
|
if ctx.accounts.auth_program.key != &counter.auth_program {
|
|
return Err(ErrorCode::InvalidAuthProgram.into());
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[interface]
|
|
pub trait Auth<'info, T: Accounts<'info>> {
|
|
fn is_authorized(ctx: Context<T>, current: u64, new: u64) -> ProgramResult;
|
|
}
|
|
|
|
#[error]
|
|
pub enum ErrorCode {
|
|
#[msg("Invalid auth program.")]
|
|
InvalidAuthProgram,
|
|
}
|