lib.rs 2.1 KB

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