Skip to content

Commit

Permalink
Using part of locked tokens to calculate voter_weight #17
Browse files Browse the repository at this point in the history
  • Loading branch information
Semen Medvedev committed Apr 1, 2022
1 parent 0a0013a commit fb41043
Show file tree
Hide file tree
Showing 5 changed files with 316 additions and 56 deletions.
6 changes: 6 additions & 0 deletions addin-vesting/program/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ pub enum VestingError {

#[error("Invalid MaxVoterWeightRecord linkage")]
InvalidMaxVoterWeightRecordLinkage,

#[error("VestingIsNotUnderRealm")]
VestingIsNotUnderRealm,

#[error("InvalidPercentage")]
InvalidPercentage,
}

impl From<VestingError> for ProgramError {
Expand Down
90 changes: 73 additions & 17 deletions addin-vesting/program/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ pub enum VestingInstruction {
/// * Single owner
/// 0. `[]` The system program account
/// 1. `[]` The spl-token program account
/// 2. `[writable]` The vesting account (vesting owner account: PDA seeds: [seeds])
/// 3. `[writable]` The vesting spl-token account (vesting balance account)
/// 4. `[signer]` The source spl-token account owner (from account owner)
/// 5. `[writable]` The source spl-token account (from account)
/// 2. `[writable]` The vesting account. PDA seeds: [seeds]
/// 3. `[writable]` The vesting spl-token account
/// 4. `[signer]` The source spl-token account owner
/// 5. `[writable]` The source spl-token account
/// 6. `[]` The Vesting Owner account
/// 7. `[signer]` Payer
///
Expand All @@ -51,8 +51,8 @@ pub enum VestingInstruction {
///
/// * Single owner
/// 0. `[]` The spl-token program account
/// 1. `[writable]` The vesting account (vesting owner account: PDA [seeds])
/// 2. `[writable]` The vesting spl-token account (vesting balance account)
/// 1. `[writable]` The vesting account. PDA seeds: [seeds]
/// 2. `[writable]` The vesting spl-token account
/// 3. `[writable]` The destination spl-token account
/// 4. `[signer]` The Vesting Owner account
///
Expand All @@ -76,7 +76,7 @@ pub enum VestingInstruction {
/// Accounts expected by this instruction:
///
/// * Single owner
/// 0. `[writable]` The Vesting account (PDA seeds: [seeds] / [realm, seeds])
/// 0. `[writable]` The Vesting account. PDA seeds: [seeds]
/// 1. `[signer]` The Current Vesting Owner account
/// 2. `[]` The New Vesting Owner account
///
Expand Down Expand Up @@ -104,6 +104,26 @@ pub enum VestingInstruction {
/// 5. `[]` The Mint account
/// 6. `[writable]` The VoterWeightRecord. PDA seeds: ['voter_weight', realm, token_mint, token_owner]
CreateVoterWeightRecord,

/// Set Vote Percentage for calcalate voter_weight from total_amount of deposited tokens
///
/// Accounts expected by this instruction:
///
/// * Single owner
/// 0. `[]` The Vesting account. PDA seeds: [seeds]
/// 1. `[]` The Vesting Owner account
/// 2. `[signer]` The Vesting Authority account
/// 3. `[]` The Governance program account
/// 4. `[]` The Realm account
/// 5. `[]` Governing Owner Record. PDA seeds (governance program): ['governance', realm, token_mint, vesting_owner]
/// 6. `[writable]` The VoterWeight Record. PDA seeds: ['voter_weight', realm, token_mint, vesting_owner]
SetVotePercentage {
#[allow(dead_code)]
seeds: [u8; 32],

#[allow(dead_code)]
vote_percentage: u16,
},
}

/// Creates a `Deposit` instruction to create and initialize the vesting token account
Expand Down Expand Up @@ -252,7 +272,7 @@ pub fn withdraw_with_realm(
})
}

/// Creates a `Withdraw` instruction
/// Creates a `ChangeOwner` instruction
pub fn change_owner(
program_id: &Pubkey,
seeds: [u8; 32],
Expand All @@ -262,8 +282,8 @@ pub fn change_owner(
let vesting_account = Pubkey::create_program_address(&[&seeds], program_id)?;
let accounts = vec![
AccountMeta::new(vesting_account, false),
AccountMeta::new(*vesting_owner, true),
AccountMeta::new(*new_vesting_owner, false),
AccountMeta::new_readonly(*vesting_owner, true),
AccountMeta::new_readonly(*new_vesting_owner, false),
];

let instruction = VestingInstruction::ChangeOwner { seeds };
Expand All @@ -275,7 +295,7 @@ pub fn change_owner(
})
}

/// Creates a `Withdraw` instruction
/// Creates a `ChangeOwner` instruction with realm
pub fn change_owner_with_realm(
program_id: &Pubkey,
seeds: [u8; 32],
Expand All @@ -287,18 +307,18 @@ pub fn change_owner_with_realm(
) -> Result<Instruction, ProgramError> {
let vesting_account = Pubkey::create_program_address(&[&seeds], program_id)?;
let current_owner_record_account = get_token_owner_record_address(governance_id, realm, mint, vesting_owner);
let current_voting_weight_record_account = get_voter_weight_record_address(program_id, realm, mint, vesting_owner);
let new_voting_weight_record_account = get_voter_weight_record_address(program_id, realm, mint, new_vesting_owner);
let current_voter_weight_record_account = get_voter_weight_record_address(program_id, realm, mint, vesting_owner);
let new_voter_weight_record_account = get_voter_weight_record_address(program_id, realm, mint, new_vesting_owner);
let accounts = vec![
AccountMeta::new(vesting_account, false),
AccountMeta::new(*vesting_owner, true),
AccountMeta::new(*new_vesting_owner, false),
AccountMeta::new_readonly(*vesting_owner, true),
AccountMeta::new_readonly(*new_vesting_owner, false),

AccountMeta::new_readonly(*governance_id, false),
AccountMeta::new_readonly(*realm, false),
AccountMeta::new_readonly(current_owner_record_account, false),
AccountMeta::new(current_voting_weight_record_account, false),
AccountMeta::new(new_voting_weight_record_account, false),
AccountMeta::new(current_voter_weight_record_account, false),
AccountMeta::new(new_voter_weight_record_account, false),
];

let instruction = VestingInstruction::ChangeOwner { seeds };
Expand Down Expand Up @@ -340,6 +360,42 @@ pub fn create_voter_weight_record(
data: instruction.try_to_vec().unwrap(),
})
}

/// Creates a `ChangeVotePercentage` instruction with realm
pub fn set_vote_percentage_with_realm(
program_id: &Pubkey,
seeds: [u8; 32],
vesting_owner: &Pubkey,
vesting_authority: &Pubkey,
governance_id: &Pubkey,
realm: &Pubkey,
mint: &Pubkey,
vote_percentage: u16,
) -> Result<Instruction, ProgramError> {
let vesting_account = Pubkey::create_program_address(&[&seeds], program_id)?;
let token_owner_record_account = get_token_owner_record_address(governance_id, realm, mint, vesting_owner);
let voter_weight_record_account = get_voter_weight_record_address(program_id, realm, mint, vesting_owner);
let accounts = vec![
AccountMeta::new_readonly(vesting_account, false),
AccountMeta::new_readonly(*vesting_owner, false),
AccountMeta::new_readonly(*vesting_authority, true),
AccountMeta::new_readonly(*governance_id, false),
AccountMeta::new_readonly(*realm, false),
AccountMeta::new_readonly(token_owner_record_account, false),
AccountMeta::new(voter_weight_record_account, false),
];

let instruction = VestingInstruction::SetVotePercentage { seeds, vote_percentage };

Ok(Instruction {
program_id: *program_id,
accounts,
data: instruction.try_to_vec().unwrap(),
})
}



#[cfg(test)]
mod test {
use super::*;
Expand Down
74 changes: 65 additions & 9 deletions addin-vesting/program/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ impl Processor {
payer_account,
voter_weight_record_account,
system_program_account,
|record| {record.voter_weight = total_amount; Ok(())},
|record| {record.increase_total_amount(total_amount)},
)?;
} else {
let mut voter_weight_record = get_voter_weight_record_data_checked(
Expand All @@ -155,8 +155,7 @@ impl Processor {
&vesting_token_account_data.mint,
vesting_owner_account.key)?;

let voter_weight = &mut voter_weight_record.voter_weight;
*voter_weight = voter_weight.checked_add(total_amount).ok_or(VestingError::OverflowAmount)?;
voter_weight_record.increase_total_amount(total_amount)?;
voter_weight_record.serialize(&mut *voter_weight_record_account.data.borrow_mut())?;
}

Expand Down Expand Up @@ -296,8 +295,7 @@ impl Processor {
&vesting_record.mint,
vesting_owner_account.key)?;

let voter_weight = &mut voter_weight_record.voter_weight;
*voter_weight = voter_weight.checked_sub(total_amount_to_transfer).ok_or(VestingError::UnderflowAmount)?;
voter_weight_record.decrease_total_amount(total_amount_to_transfer)?;
voter_weight_record.serialize(&mut *voter_weight_record_account.data.borrow_mut())?;

let mut max_voter_weight_record = get_max_voter_weight_record_data_checked(
Expand Down Expand Up @@ -390,8 +388,8 @@ impl Processor {
realm_account.key,
&vesting_record.mint,
vesting_owner_account.key)?;
let voter_weight = &mut voter_weight_record.voter_weight;
*voter_weight = voter_weight.checked_sub(total_amount).ok_or(VestingError::UnderflowAmount)?;

voter_weight_record.decrease_total_amount(total_amount)?;
voter_weight_record.serialize(&mut *voter_weight_record_account.data.borrow_mut())?;

let mut new_voter_weight_record = get_voter_weight_record_data_checked(
Expand All @@ -401,8 +399,7 @@ impl Processor {
&vesting_record.mint,
new_vesting_owner_account.key)?;

let new_voter_weight = &mut new_voter_weight_record.voter_weight;
*new_voter_weight = new_voter_weight.checked_add(total_amount).ok_or(VestingError::OverflowAmount)?;
new_voter_weight_record.increase_total_amount(total_amount)?;
new_voter_weight_record.serialize(&mut *new_voter_weight_record_account.data.borrow_mut())?;

}
Expand Down Expand Up @@ -438,6 +435,62 @@ impl Processor {
Ok(())
}

pub fn process_set_vote_percentage(
program_id: &Pubkey,
accounts: &[AccountInfo],
seeds: [u8; 32],
vote_percentage: u16,
) -> ProgramResult {
let accounts_iter = &mut accounts.iter();

let vesting_account = next_account_info(accounts_iter)?;
let vesting_owner_account = next_account_info(accounts_iter)?;
let vesting_authority_account = next_account_info(accounts_iter)?;
let governance_account = next_account_info(accounts_iter)?;
let realm_account = next_account_info(accounts_iter)?;
let owner_record_account = next_account_info(accounts_iter)?;
let voter_weight_record_account = next_account_info(accounts_iter)?;

let vesting_account_key = Pubkey::create_program_address(&[&seeds], program_id)?;
if vesting_account_key != *vesting_account.key {
return Err(VestingError::InvalidVestingAccount.into());
}

let vesting_record = get_account_data::<VestingRecord>(program_id, vesting_account)?;

let expected_realm_account = vesting_record.realm.ok_or(VestingError::VestingIsNotUnderRealm)?;

if *realm_account.key != expected_realm_account {
return Err(VestingError::InvalidRealmAccount.into())
};

let realm_data = get_realm_data(governance_account.key, realm_account)?;
realm_data.assert_is_valid_governing_token_mint(&vesting_record.mint)?;

let owner_record_data = get_token_owner_record_data_for_seeds(
governance_account.key,
owner_record_account,
&get_token_owner_record_address_seeds(
realm_account.key,
&vesting_record.mint,
vesting_owner_account.key,
),
)?;
owner_record_data.assert_token_owner_or_delegate_is_signer(vesting_authority_account)?;

let mut voter_weight_record = get_voter_weight_record_data_checked(
program_id,
voter_weight_record_account,
realm_account.key,
&vesting_record.mint,
vesting_owner_account.key)?;

voter_weight_record.set_vote_percentage(vote_percentage)?;
voter_weight_record.serialize(&mut *voter_weight_record_account.data.borrow_mut())?;

Ok(())
}

pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
Expand All @@ -461,6 +514,9 @@ impl Processor {
VestingInstruction::CreateVoterWeightRecord => {
Self::process_create_voter_weight_record(program_id, accounts)
}
VestingInstruction::SetVotePercentage {seeds, vote_percentage} => {
Self::process_set_vote_percentage(program_id, accounts, seeds, vote_percentage)
}
}
}
}
Loading

0 comments on commit fb41043

Please sign in to comment.