lib.rs 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. //! counter is an example program that depends on an external interface
  2. //! that another program must implement. This allows our program to depend
  3. //! on another program, without knowing anything about it other than the fact
  4. //! that it implements the `Auth` trait.
  5. //!
  6. //! Here, we have a counter, where, in order to set the count, the `Auth`
  7. //! program must first approve the transaction.
  8. use anchor_lang::prelude::*;
  9. #[program]
  10. pub mod counter {
  11. use super::*;
  12. #[state]
  13. pub struct Counter {
  14. pub count: u64,
  15. pub auth_program: Pubkey,
  16. }
  17. impl Counter {
  18. pub fn new(_ctx: Context<Empty>, auth_program: Pubkey) -> Result<Self> {
  19. Ok(Self {
  20. count: 0,
  21. auth_program,
  22. })
  23. }
  24. #[access_control(SetCount::accounts(&self, &ctx))]
  25. pub fn set_count(&mut self, ctx: Context<SetCount>, new_count: u64) -> Result<()> {
  26. // Ask the auth program if we should approve the transaction.
  27. let cpi_program = ctx.accounts.auth_program.clone();
  28. let cpi_ctx = CpiContext::new(cpi_program, Empty {});
  29. auth::is_authorized(cpi_ctx, self.count, new_count)?;
  30. // Approved, so update.
  31. self.count = new_count;
  32. Ok(())
  33. }
  34. }
  35. }
  36. #[derive(Accounts)]
  37. pub struct Empty {}
  38. #[derive(Accounts)]
  39. pub struct SetCount<'info> {
  40. auth_program: AccountInfo<'info>,
  41. }
  42. impl<'info> SetCount<'info> {
  43. // Auxiliary account validation requiring program inputs. As a convention,
  44. // we separate it from the business logic of the instruction handler itself.
  45. pub fn accounts(counter: &Counter, ctx: &Context<SetCount>) -> Result<()> {
  46. if ctx.accounts.auth_program.key != &counter.auth_program {
  47. return Err(ErrorCode::InvalidAuthProgram.into());
  48. }
  49. Ok(())
  50. }
  51. }
  52. #[interface]
  53. pub trait Auth<'info, T: Accounts<'info>> {
  54. fn is_authorized(ctx: Context<T>, current: u64, new: u64) -> ProgramResult;
  55. }
  56. #[error]
  57. pub enum ErrorCode {
  58. #[msg("Invalid auth program.")]
  59. InvalidAuthProgram,
  60. }