-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathprocess_deposit_governing_tokens.rs
More file actions
139 lines (122 loc) · 4.91 KB
/
process_deposit_governing_tokens.rs
File metadata and controls
139 lines (122 loc) · 4.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//! Program state processor
use solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint::ProgramResult,
pubkey::Pubkey,
rent::Rent,
sysvar::Sysvar,
};
use spl_governance_tools::account::create_and_serialize_account_signed;
use crate::{
error::GovernanceError,
state::{
enums::GovernanceAccountType,
realm::get_realm_data,
realm_config::get_realm_config_data_for_realm,
token_owner_record::{
get_token_owner_record_address_seeds, get_token_owner_record_data_for_seeds,
TokenOwnerRecordV2, TOKEN_OWNER_RECORD_LAYOUT_VERSION,
},
},
tools::spl_token::{
get_spl_token_mint, is_spl_token_account, is_spl_token_mint, mint_spl_tokens_to,
transfer_spl_tokens,
},
};
/// Processes DepositGoverningTokens instruction
pub fn process_deposit_governing_tokens(
program_id: &Pubkey,
accounts: &[AccountInfo],
amount: u64,
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let realm_info = next_account_info(account_info_iter)?; // 0
let governing_token_holding_info = next_account_info(account_info_iter)?; // 1
let governing_token_source_info = next_account_info(account_info_iter)?; // 2
let governing_token_owner_info = next_account_info(account_info_iter)?; // 3
let governing_token_source_authority_info = next_account_info(account_info_iter)?; // 4
let token_owner_record_info = next_account_info(account_info_iter)?; // 5
let payer_info = next_account_info(account_info_iter)?; // 6
let system_info = next_account_info(account_info_iter)?; // 7
let spl_token_info = next_account_info(account_info_iter)?; // 8
let realm_config_info = next_account_info(account_info_iter)?; // 9
let rent = Rent::get()?;
let realm_data = get_realm_data(program_id, realm_info)?;
let governing_token_mint = get_spl_token_mint(governing_token_holding_info)?;
realm_data.assert_is_valid_governing_token_mint_and_holding(
program_id,
realm_info.key,
&governing_token_mint,
governing_token_holding_info.key,
)?;
let realm_config_data =
get_realm_config_data_for_realm(program_id, realm_config_info, realm_info.key)?;
realm_config_data.assert_can_deposit_governing_token(&realm_data, &governing_token_mint)?;
if is_spl_token_account(governing_token_source_info) {
// If the source is spl-token token account then transfer tokens from it
transfer_spl_tokens(
governing_token_source_info,
governing_token_holding_info,
governing_token_source_authority_info,
amount,
spl_token_info,
)?;
} else if is_spl_token_mint(governing_token_source_info) {
// If it's a mint then mint the tokens
mint_spl_tokens_to(
governing_token_source_info,
governing_token_holding_info,
governing_token_source_authority_info,
amount,
spl_token_info,
)?;
} else {
return Err(GovernanceError::InvalidGoverningTokenSource.into());
}
let token_owner_record_address_seeds = get_token_owner_record_address_seeds(
realm_info.key,
&governing_token_mint,
governing_token_owner_info.key,
);
if token_owner_record_info.data_is_empty() {
// Deposited tokens can only be withdrawn by the owner so let's make sure the owner signed the transaction
if !governing_token_owner_info.is_signer {
return Err(GovernanceError::GoverningTokenOwnerMustSign.into());
}
let token_owner_record_data = TokenOwnerRecordV2 {
account_type: GovernanceAccountType::TokenOwnerRecordV2,
realm: *realm_info.key,
governing_token_owner: *governing_token_owner_info.key,
governing_token_deposit_amount: amount,
governing_token_mint,
governance_delegate: None,
unrelinquished_votes_count: 0,
outstanding_proposal_count: 0,
version: TOKEN_OWNER_RECORD_LAYOUT_VERSION,
reserved: [0; 6],
reserved_v2: [0; 128],
};
create_and_serialize_account_signed(
payer_info,
token_owner_record_info,
&token_owner_record_data,
&token_owner_record_address_seeds,
program_id,
system_info,
&rent,
0,
)?;
} else {
let mut token_owner_record_data = get_token_owner_record_data_for_seeds(
program_id,
token_owner_record_info,
&token_owner_record_address_seeds,
)?;
token_owner_record_data.governing_token_deposit_amount = token_owner_record_data
.governing_token_deposit_amount
.checked_add(amount)
.unwrap();
token_owner_record_data.serialize(&mut *token_owner_record_info.data.borrow_mut())?;
}
Ok(())
}