delegation_manager/
lib.rs1use anchor_lang::prelude::*;
8declare_id!("UPLdquGEBVnVK5TmccSue5gyPkxSRT4poezHShoEzg8");
9
10#[constant]
11pub const AUTHORIZE_SEED: &'static [u8] = b"authorize";
12#[program]
14pub mod delegation_manager {
15 use super::*;
16
17 pub fn initialize_delegate(ctx: Context<InitializeDelegation>) -> Result<()> {
20 let delegation = &mut ctx.accounts.delegation;
21 delegation.master = ctx.accounts.master.key();
22 delegation.representative = ctx.accounts.representative.key();
23 delegation.authorised = false;
24 Ok(())
25 }
26
27 pub fn confirm_delegate(ctx: Context<ConfirmDelegation>) -> Result<()> {
30 let delegation = &mut ctx.accounts.delegation;
31 require!(
32 ctx.accounts.representative.key() == delegation.representative,
33 DelegationError::WrongRepresentative
34 );
35 require!(!delegation.authorised, DelegationError::AlreadyAuthorised);
36 delegation.authorised = true;
37 Ok(())
38 }
39
40 pub fn cancel_delegate<'a, 'b, 'c, 'info>(
44 ctx: Context<'a, 'b, 'c, 'info, CancelDelegation<'info>>,
45 ) -> Result<()> {
46 let delegation = &mut ctx.accounts.delegation;
47 let remaining_accounts = &mut ctx.remaining_accounts.iter();
48 let master = remaining_accounts
49 .next()
50 .expect("Expected master as remaining account");
51 let representative = remaining_accounts
52 .next()
53 .expect("Expected representative as remaining account");
54 require!(
55 master.key() == delegation.master,
56 DelegationError::WrongMaster
57 );
58 require!(
59 representative.key() == delegation.representative,
60 DelegationError::WrongRepresentative
61 );
62 require!(
63 master.is_signer || representative.is_signer,
64 DelegationError::WrongSigner
65 );
66
67 delegation.close(master.to_account_info())?;
68
69 Ok(())
70 }
71}
72
73#[derive(Accounts)]
75pub struct InitializeDelegation<'info> {
76 #[account(mut)]
77 pub master: Signer<'info>,
79 pub representative: UncheckedAccount<'info>,
81 #[account(
82 init,
83 seeds = [AUTHORIZE_SEED, master.key().as_ref(), representative.key().as_ref()],
84 bump,
85 space = 8 + 32 + 32 + 1,
86 payer = master
87 )]
88 pub delegation: Box<Account<'info, Delegation>>,
90 pub system_program: Program<'info, System>,
91}
92
93#[derive(Accounts)]
95pub struct ConfirmDelegation<'info> {
96 #[account(mut)]
97 pub representative: Signer<'info>,
98 #[account(mut)]
99 pub delegation: Box<Account<'info, Delegation>>,
100 pub system_program: Program<'info, System>,
101}
102
103#[derive(Accounts)]
105pub struct CancelDelegation<'info> {
106 #[account(mut)]
107 pub delegation: Box<Account<'info, Delegation>>,
108 pub system_program: Program<'info, System>,
109}
110
111#[account]
113#[derive(Debug)]
114pub struct Delegation {
115 pub master: Pubkey,
117 pub representative: Pubkey,
119 pub authorised: bool,
121}
122
123#[error_code]
125pub enum DelegationError {
126 #[msg("Wrong representative!")]
127 WrongRepresentative,
128 #[msg("Wrong authority!")]
129 WrongMaster,
130 #[msg("Wrong signer!")]
131 WrongSigner,
132 #[msg("Authorization already approved!")]
133 AlreadyAuthorised,
134 #[msg("The account provided has no authority!")]
135 NotAuthorized,
136}
137
138pub fn check_authorization(
142 master: &AccountInfo,
143 representative: &AccountInfo,
144 delegation_option: Option<&AccountInfo>,
145) -> Result<()> {
146 if master.key() != representative.key() {
147 let delegation_info = delegation_option.expect("Missing Delegation Account");
148 require_keys_eq!(*delegation_info.owner, ID);
149 let delegation = Box::new(
150 Account::<Delegation>::try_from(delegation_info)
151 .expect("Wrong account passed as Delegation account"),
152 );
153 require_keys_eq!(master.key(), delegation.master);
154 require_keys_eq!(representative.key(), delegation.representative);
155 require!(delegation.authorised, DelegationError::NotAuthorized);
156 }
157 Ok(())
158}
159
160pub fn get_delegation_address(master: &Pubkey, representative: &Pubkey) -> Pubkey {
161 Pubkey::find_program_address(&get_delegation_address_seeds(master, representative), &ID).0
162}
163
164pub fn get_delegation_address_seeds<'a>(
165 master: &'a Pubkey,
166 representative: &'a Pubkey,
167) -> [&'a [u8]; 3] {
168 [AUTHORIZE_SEED, &master.as_ref(), &representative.as_ref()]
169}