Governance: Council membership & plugins (#3344)
* chore: Use GovernanceTokenConfig * wip: add council_token_config to RealmConfigAccount * chore: update comment * wip: use GoverningTokenConfigArgs for community token config * chore: Change Proxy token type to Dormant * chore: Update comments * chore: Use GoverningTokenConfigAccountArgs for instructions creators * chore: Use default GoverningTokenType * chore: Make community_token_args optional * chore: Make Clippy happy * chore: Update comments * chore: Always create RealmConfigAccount * chore: Set CouncilTokenConfig when realm is created * feat: Update RealmConfigArgs in SetRealmConfig * chore: Make Clippy happy * chore: Assert RealmConfigAccount PDA * wip: Use default RealmConfigAccount if the account doesn't exist * chore: Remove use_community_voter_weight_addin and use_max_community_voter_weight_addin from RealmConfig * chore: code review cleanup * wip: Use voter weight addin for Council * feat: Use max_voter_weight_plugin for Council * feat: Impl RevokeGoverningTokens instruction * chore: Make Clippy happy * feat: Enforce governing token withdraw and deposit rules * feat: Support minting deposits * feat: Do not enforce token source owner for deposit validation * chore: test_deposit_community_tokens_using_mint * chore: Remove not implemented comment * fix: Fix progrma id for resolving realm config for chat * chore: Update instructions comments * feat: Do not allow community Liquid token change to Membership * chore: test_set_realm_config_with_liquid_community_token_cannot_be_changed_to_memebership_error * chore: test_set_realm_config_for_community_token * chore: use GoverningTokenConfig for test args * chore: Refactor SetRealmConfigArgs * chore: Update RealmSetupArgs names * chore: test_set_realm_config_for_council_token_config * chore: Revoke council tokens tests * chore: test_revoke_council_tokens_with_realm_authority_must_sign_error * chore: test_revoke_council_tokens_with_invalid_realm_authority_error * chore: test_revoke_council_tokens_with_invalid_token_holding_error * chore: RevokeGoverningToken tests * chore: Dormant and Membership tokens tests * chore: Using council plugin tests * chore: RealmConfigAccount validation tests * chore: Update Dormant token type configs * fix: Reset legacy fields * chore: Use Default macro for derivable defaults * Chore: use assert functions to validate spl-token account and mint * chore: Update Membership tokens comments * chore: Pass governing_token_config_args as reference * chore: Use single statement to return InvalidRevokeAmount error * chore: Make Clippy happy - add derived Eq Co-authored-by: Jon Cinque
This commit is contained in:
parent
83b5dabf02
commit
6dfc68db13
|
@ -6,7 +6,7 @@ use spl_governance_tools::account::AccountMaxSize;
|
||||||
|
|
||||||
/// MaxVoterWeightRecord account
|
/// MaxVoterWeightRecord account
|
||||||
/// The account is used as an api interface to provide max voting power to the governance program from external addin contracts
|
/// The account is used as an api interface to provide max voting power to the governance program from external addin contracts
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct MaxVoterWeightRecord {
|
pub struct MaxVoterWeightRecord {
|
||||||
/// VoterWeightRecord discriminator sha256("account:MaxVoterWeightRecord")[..8]
|
/// VoterWeightRecord discriminator sha256("account:MaxVoterWeightRecord")[..8]
|
||||||
/// Note: The discriminator size must match the addin implementing program discriminator size
|
/// Note: The discriminator size must match the addin implementing program discriminator size
|
||||||
|
|
|
@ -5,7 +5,7 @@ use solana_program::{clock::Slot, program_pack::IsInitialized, pubkey::Pubkey};
|
||||||
use spl_governance_tools::account::AccountMaxSize;
|
use spl_governance_tools::account::AccountMaxSize;
|
||||||
|
|
||||||
/// The governance action VoterWeight is evaluated for
|
/// The governance action VoterWeight is evaluated for
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum VoterWeightAction {
|
pub enum VoterWeightAction {
|
||||||
/// Cast vote for a proposal. Target: Proposal
|
/// Cast vote for a proposal. Target: Proposal
|
||||||
CastVote,
|
CastVote,
|
||||||
|
@ -26,7 +26,7 @@ pub enum VoterWeightAction {
|
||||||
|
|
||||||
/// VoterWeightRecord account
|
/// VoterWeightRecord account
|
||||||
/// The account is used as an api interface to provide voting power to the governance program from external addin contracts
|
/// The account is used as an api interface to provide voting power to the governance program from external addin contracts
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct VoterWeightRecord {
|
pub struct VoterWeightRecord {
|
||||||
/// VoterWeightRecord discriminator sha256("account:VoterWeightRecord")[..8]
|
/// VoterWeightRecord discriminator sha256("account:VoterWeightRecord")[..8]
|
||||||
/// Note: The discriminator size must match the addin implementing program discriminator size
|
/// Note: The discriminator size must match the addin implementing program discriminator size
|
||||||
|
|
|
@ -11,7 +11,7 @@ use spl_governance_addin_api::voter_weight::VoterWeightAction;
|
||||||
|
|
||||||
/// Instructions supported by the VoterWeight addin program
|
/// Instructions supported by the VoterWeight addin program
|
||||||
/// This program is a mock program used by spl-governance for testing and not real addin
|
/// This program is a mock program used by spl-governance for testing and not real addin
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
pub enum VoterWeightAddinInstruction {
|
pub enum VoterWeightAddinInstruction {
|
||||||
/// Sets up VoterWeightRecord owned by the program
|
/// Sets up VoterWeightRecord owned by the program
|
||||||
|
|
|
@ -11,7 +11,7 @@ use spl_governance::instruction::with_realm_config_accounts;
|
||||||
use crate::state::MessageBody;
|
use crate::state::MessageBody;
|
||||||
|
|
||||||
/// Instructions supported by the GovernanceChat program
|
/// Instructions supported by the GovernanceChat program
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
pub enum GovernanceChatInstruction {
|
pub enum GovernanceChatInstruction {
|
||||||
/// Posts a message with a comment for a Proposal
|
/// Posts a message with a comment for a Proposal
|
||||||
|
|
|
@ -18,7 +18,8 @@ use solana_program::{
|
||||||
};
|
};
|
||||||
use spl_governance::state::{
|
use spl_governance::state::{
|
||||||
governance::get_governance_data_for_realm, proposal::get_proposal_data_for_governance,
|
governance::get_governance_data_for_realm, proposal::get_proposal_data_for_governance,
|
||||||
realm::get_realm_data, token_owner_record::get_token_owner_record_data_for_realm,
|
realm::get_realm_data, realm_config::get_realm_config_data_for_realm,
|
||||||
|
token_owner_record::get_token_owner_record_data_for_realm,
|
||||||
};
|
};
|
||||||
use spl_governance_addin_api::voter_weight::VoterWeightAction;
|
use spl_governance_addin_api::voter_weight::VoterWeightAction;
|
||||||
use spl_governance_tools::account::create_and_serialize_account;
|
use spl_governance_tools::account::create_and_serialize_account;
|
||||||
|
@ -94,12 +95,13 @@ pub fn process_post_message(
|
||||||
|
|
||||||
let realm_config_info = next_account_info(account_info_iter)?; // 10
|
let realm_config_info = next_account_info(account_info_iter)?; // 10
|
||||||
|
|
||||||
|
let realm_config_data =
|
||||||
|
get_realm_config_data_for_realm(governance_program_id, realm_config_info, realm_info.key)?;
|
||||||
|
|
||||||
let voter_weight = token_owner_record_data.resolve_voter_weight(
|
let voter_weight = token_owner_record_data.resolve_voter_weight(
|
||||||
governance_program_id,
|
account_info_iter, // voter_weight_record *11
|
||||||
realm_config_info,
|
|
||||||
account_info_iter, // 11
|
|
||||||
realm_info.key,
|
|
||||||
&realm_data,
|
&realm_data,
|
||||||
|
&realm_config_data,
|
||||||
VoterWeightAction::CommentProposal,
|
VoterWeightAction::CommentProposal,
|
||||||
proposal_info.key,
|
proposal_info.key,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -8,7 +8,7 @@ use solana_program::{
|
||||||
use spl_governance_tools::account::{assert_is_valid_account_of_type, AccountMaxSize};
|
use spl_governance_tools::account::{assert_is_valid_account_of_type, AccountMaxSize};
|
||||||
|
|
||||||
/// Defines all GovernanceChat accounts types
|
/// Defines all GovernanceChat accounts types
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum GovernanceChatAccountType {
|
pub enum GovernanceChatAccountType {
|
||||||
/// Default uninitialized account state
|
/// Default uninitialized account state
|
||||||
Uninitialized,
|
Uninitialized,
|
||||||
|
@ -18,7 +18,7 @@ pub enum GovernanceChatAccountType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Chat message body
|
/// Chat message body
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum MessageBody {
|
pub enum MessageBody {
|
||||||
/// Text message encoded as utf-8 string
|
/// Text message encoded as utf-8 string
|
||||||
Text(String),
|
Text(String),
|
||||||
|
@ -29,7 +29,7 @@ pub enum MessageBody {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Chat message
|
/// Chat message
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct ChatMessage {
|
pub struct ChatMessage {
|
||||||
/// Account type
|
/// Account type
|
||||||
pub account_type: GovernanceChatAccountType,
|
pub account_type: GovernanceChatAccountType,
|
||||||
|
|
|
@ -13,7 +13,8 @@ use spl_governance::{
|
||||||
enums::{MintMaxVoteWeightSource, VoteThreshold},
|
enums::{MintMaxVoteWeightSource, VoteThreshold},
|
||||||
governance::{get_governance_address, GovernanceConfig},
|
governance::{get_governance_address, GovernanceConfig},
|
||||||
proposal::{get_proposal_address, VoteType},
|
proposal::{get_proposal_address, VoteType},
|
||||||
realm::get_realm_address,
|
realm::{get_realm_address, GoverningTokenConfigAccountArgs},
|
||||||
|
realm_config::GoverningTokenType,
|
||||||
token_owner_record::get_token_owner_record_address,
|
token_owner_record::get_token_owner_record_address,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -108,13 +109,19 @@ impl GovernanceChatProgramTest {
|
||||||
|
|
||||||
let realm_authority = Keypair::new();
|
let realm_authority = Keypair::new();
|
||||||
|
|
||||||
|
let community_token_config_args = GoverningTokenConfigAccountArgs {
|
||||||
|
voter_weight_addin: self.voter_weight_addin_id,
|
||||||
|
max_voter_weight_addin: None,
|
||||||
|
token_type: GoverningTokenType::default(),
|
||||||
|
};
|
||||||
|
|
||||||
let create_realm_ix = create_realm(
|
let create_realm_ix = create_realm(
|
||||||
&self.governance_program_id,
|
&self.governance_program_id,
|
||||||
&realm_authority.pubkey(),
|
&realm_authority.pubkey(),
|
||||||
&governing_token_mint_keypair.pubkey(),
|
&governing_token_mint_keypair.pubkey(),
|
||||||
&self.bench.payer.pubkey(),
|
&self.bench.payer.pubkey(),
|
||||||
None,
|
None,
|
||||||
self.voter_weight_addin_id,
|
Some(community_token_config_args),
|
||||||
None,
|
None,
|
||||||
name.clone(),
|
name.clone(),
|
||||||
1,
|
1,
|
||||||
|
|
|
@ -261,23 +261,23 @@ pub enum GovernanceError {
|
||||||
|
|
||||||
/// Governance PDA must sign
|
/// Governance PDA must sign
|
||||||
#[error("Governance PDA must sign")]
|
#[error("Governance PDA must sign")]
|
||||||
GovernancePdaMustSign,
|
GovernancePdaMustSign, // 561
|
||||||
|
|
||||||
/// Transaction already flagged with error
|
/// Transaction already flagged with error
|
||||||
#[error("Transaction already flagged with error")]
|
#[error("Transaction already flagged with error")]
|
||||||
TransactionAlreadyFlaggedWithError,
|
TransactionAlreadyFlaggedWithError, // 562
|
||||||
|
|
||||||
/// Invalid Realm for Governance
|
/// Invalid Realm for Governance
|
||||||
#[error("Invalid Realm for Governance")]
|
#[error("Invalid Realm for Governance")]
|
||||||
InvalidRealmForGovernance,
|
InvalidRealmForGovernance, // 563
|
||||||
|
|
||||||
/// Invalid Authority for Realm
|
/// Invalid Authority for Realm
|
||||||
#[error("Invalid Authority for Realm")]
|
#[error("Invalid Authority for Realm")]
|
||||||
InvalidAuthorityForRealm,
|
InvalidAuthorityForRealm, // 564
|
||||||
|
|
||||||
/// Realm has no authority
|
/// Realm has no authority
|
||||||
#[error("Realm has no authority")]
|
#[error("Realm has no authority")]
|
||||||
RealmHasNoAuthority,
|
RealmHasNoAuthority, // 565
|
||||||
|
|
||||||
/// Realm authority must sign
|
/// Realm authority must sign
|
||||||
#[error("Realm authority must sign")]
|
#[error("Realm authority must sign")]
|
||||||
|
@ -285,7 +285,7 @@ pub enum GovernanceError {
|
||||||
|
|
||||||
/// Invalid governing token holding account
|
/// Invalid governing token holding account
|
||||||
#[error("Invalid governing token holding account")]
|
#[error("Invalid governing token holding account")]
|
||||||
InvalidGoverningTokenHoldingAccount,
|
InvalidGoverningTokenHoldingAccount, // 567
|
||||||
|
|
||||||
/// Realm council mint change is not supported
|
/// Realm council mint change is not supported
|
||||||
#[error("Realm council mint change is not supported")]
|
#[error("Realm council mint change is not supported")]
|
||||||
|
@ -406,6 +406,34 @@ pub enum GovernanceError {
|
||||||
/// Cannot Relinquish in Finalizing state
|
/// Cannot Relinquish in Finalizing state
|
||||||
#[error("Cannot Relinquish in Finalizing state")]
|
#[error("Cannot Relinquish in Finalizing state")]
|
||||||
CannotRelinquishInFinalizingState,
|
CannotRelinquishInFinalizingState,
|
||||||
|
|
||||||
|
/// Invalid RealmConfig account address
|
||||||
|
#[error("Invalid RealmConfig account address")]
|
||||||
|
InvalidRealmConfigAddress,
|
||||||
|
|
||||||
|
/// Cannot deposit dormant tokens
|
||||||
|
#[error("Cannot deposit dormant tokens")]
|
||||||
|
CannotDepositDormantTokens, // 599
|
||||||
|
|
||||||
|
/// Cannot withdraw membership tokens
|
||||||
|
#[error("Cannot withdraw membership tokens")]
|
||||||
|
CannotWithdrawMembershipTokens, // 600
|
||||||
|
|
||||||
|
/// Cannot revoke GoverningTokens
|
||||||
|
#[error("Cannot revoke GoverningTokens")]
|
||||||
|
CannotRevokeGoverningTokens, // 601
|
||||||
|
|
||||||
|
/// Invalid Revoke amount
|
||||||
|
#[error("Invalid Revoke amount")]
|
||||||
|
InvalidRevokeAmount, // 602
|
||||||
|
|
||||||
|
/// Invalid GoverningToken source
|
||||||
|
#[error("Invalid GoverningToken source")]
|
||||||
|
InvalidGoverningTokenSource, // 603
|
||||||
|
|
||||||
|
/// Cannot change community TokenType to Memebership
|
||||||
|
#[error("Cannot change community TokenType to Memebership")]
|
||||||
|
CannotChangeCommunityTokenTypeToMemebership, // 604
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrintProgramError for GovernanceError {
|
impl PrintProgramError for GovernanceError {
|
||||||
|
|
|
@ -11,8 +11,11 @@ use crate::{
|
||||||
program_metadata::get_program_metadata_address,
|
program_metadata::get_program_metadata_address,
|
||||||
proposal::{get_proposal_address, VoteType},
|
proposal::{get_proposal_address, VoteType},
|
||||||
proposal_transaction::{get_proposal_transaction_address, InstructionData},
|
proposal_transaction::{get_proposal_transaction_address, InstructionData},
|
||||||
realm::SetRealmAuthorityAction,
|
realm::{
|
||||||
realm::{get_governing_token_holding_address, get_realm_address, RealmConfigArgs},
|
get_governing_token_holding_address, get_realm_address,
|
||||||
|
GoverningTokenConfigAccountArgs, RealmConfigArgs,
|
||||||
|
},
|
||||||
|
realm::{GoverningTokenConfigArgs, SetRealmAuthorityAction},
|
||||||
realm_config::get_realm_config_address,
|
realm_config::get_realm_config_address,
|
||||||
signatory_record::get_signatory_record_address,
|
signatory_record::get_signatory_record_address,
|
||||||
token_owner_record::get_token_owner_record_address,
|
token_owner_record::get_token_owner_record_address,
|
||||||
|
@ -29,7 +32,7 @@ use solana_program::{
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Instructions supported by the Governance program
|
/// Instructions supported by the Governance program
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
pub enum GovernanceInstruction {
|
pub enum GovernanceInstruction {
|
||||||
/// Creates Governance Realm account which aggregates governances for given Community Mint and optional Council Mint
|
/// Creates Governance Realm account which aggregates governances for given Community Mint and optional Council Mint
|
||||||
|
@ -48,9 +51,13 @@ pub enum GovernanceInstruction {
|
||||||
/// 9. `[writable]` Council Token Holding account - optional unless council is used. PDA seeds: ['governance',realm,council_mint]
|
/// 9. `[writable]` Council Token Holding account - optional unless council is used. PDA seeds: ['governance',realm,council_mint]
|
||||||
/// The account will be created with the Realm PDA as its owner
|
/// The account will be created with the Realm PDA as its owner
|
||||||
|
|
||||||
/// 10. `[]` Optional Community Voter Weight Addin Program Id
|
/// 10. `[writable]` RealmConfig account. PDA seeds: ['realm-config', realm]
|
||||||
/// 11. `[]` Optional Max Community Voter Weight Addin Program Id
|
|
||||||
/// 12. `[writable]` Optional RealmConfig account. PDA seeds: ['realm-config', realm]
|
/// 11. `[]` Optional Community Voter Weight Addin Program Id
|
||||||
|
/// 12. `[]` Optional Max Community Voter Weight Addin Program Id
|
||||||
|
///
|
||||||
|
/// 13. `[]` Optional Council Voter Weight Addin Program Id
|
||||||
|
/// 14. `[]` Optional Max Council Voter Weight Addin Program Id
|
||||||
CreateRealm {
|
CreateRealm {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
/// UTF-8 encoded Governance Realm name
|
/// UTF-8 encoded Governance Realm name
|
||||||
|
@ -65,16 +72,18 @@ pub enum GovernanceInstruction {
|
||||||
/// Note: If subsequent (top up) deposit is made and there are active votes for the Voter then the vote weights won't be updated automatically
|
/// Note: If subsequent (top up) deposit is made and there are active votes for the Voter then the vote weights won't be updated automatically
|
||||||
/// It can be done by relinquishing votes on active Proposals and voting again with the new weight
|
/// It can be done by relinquishing votes on active Proposals and voting again with the new weight
|
||||||
///
|
///
|
||||||
/// 0. `[]` Governance Realm account
|
/// 0. `[]` Realm account
|
||||||
/// 1. `[writable]` Governing Token Holding account. PDA seeds: ['governance',realm, governing_token_mint]
|
/// 1. `[writable]` Governing Token Holding account. PDA seeds: ['governance',realm, governing_token_mint]
|
||||||
/// 2. `[writable]` Governing Token Source account. All tokens from the account will be transferred to the Holding account
|
/// 2. `[writable]` Governing Token Source account. It can be either spl-token TokenAccount or MintAccount
|
||||||
|
/// Tokens will be transferred or minted to the Holding account
|
||||||
/// 3. `[signer]` Governing Token Owner account
|
/// 3. `[signer]` Governing Token Owner account
|
||||||
/// 4. `[signer]` Governing Token Transfer authority
|
/// 4. `[signer]` Governing Token Source account authority
|
||||||
|
/// It should be owner for TokenAccount and mint_auhtority for MintAccount
|
||||||
/// 5. `[writable]` TokenOwnerRecord account. PDA seeds: ['governance',realm, governing_token_mint, governing_token_owner]
|
/// 5. `[writable]` TokenOwnerRecord account. PDA seeds: ['governance',realm, governing_token_mint, governing_token_owner]
|
||||||
/// 6. `[signer]` Payer
|
/// 6. `[signer]` Payer
|
||||||
/// 7. `[]` System
|
/// 7. `[]` System
|
||||||
/// 8. `[]` SPL Token
|
/// 8. `[]` SPL Token program
|
||||||
/// 9. `[]` Sysvar Rent
|
/// 9. `[]` RealmConfig account. PDA seeds: ['realm-config', realm]
|
||||||
DepositGoverningTokens {
|
DepositGoverningTokens {
|
||||||
/// The amount to deposit into the realm
|
/// The amount to deposit into the realm
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -85,12 +94,13 @@ pub enum GovernanceInstruction {
|
||||||
/// Note: It's only possible to withdraw tokens if the Voter doesn't have any outstanding active votes
|
/// Note: It's only possible to withdraw tokens if the Voter doesn't have any outstanding active votes
|
||||||
/// If there are any outstanding votes then they must be relinquished before tokens could be withdrawn
|
/// If there are any outstanding votes then they must be relinquished before tokens could be withdrawn
|
||||||
///
|
///
|
||||||
/// 0. `[]` Governance Realm account
|
/// 0. `[]` Realm account
|
||||||
/// 1. `[writable]` Governing Token Holding account. PDA seeds: ['governance',realm, governing_token_mint]
|
/// 1. `[writable]` Governing Token Holding account. PDA seeds: ['governance',realm, governing_token_mint]
|
||||||
/// 2. `[writable]` Governing Token Destination account. All tokens will be transferred to this account
|
/// 2. `[writable]` Governing Token Destination account. All tokens will be transferred to this account
|
||||||
/// 3. `[signer]` Governing Token Owner account
|
/// 3. `[signer]` Governing Token Owner account
|
||||||
/// 4. `[writable]` TokenOwnerRecord account. PDA seeds: ['governance',realm, governing_token_mint, governing_token_owner]
|
/// 4. `[writable]` TokenOwnerRecord account. PDA seeds: ['governance',realm, governing_token_mint, governing_token_owner]
|
||||||
/// 5. `[]` SPL Token
|
/// 5. `[]` SPL Token program
|
||||||
|
/// 6. `[]` RealmConfig account. PDA seeds: ['realm-config', realm]
|
||||||
WithdrawGoverningTokens {},
|
WithdrawGoverningTokens {},
|
||||||
|
|
||||||
/// Sets Governance Delegate for the given Realm and Governing Token Mint (Community or Council)
|
/// Sets Governance Delegate for the given Realm and Governing Token Mint (Community or Council)
|
||||||
|
@ -117,7 +127,7 @@ pub enum GovernanceInstruction {
|
||||||
/// 5. `[]` System program
|
/// 5. `[]` System program
|
||||||
/// 6. `[]` Sysvar Rent
|
/// 6. `[]` Sysvar Rent
|
||||||
/// 7. `[signer]` Governance authority
|
/// 7. `[signer]` Governance authority
|
||||||
/// 8. `[]` Realm Config
|
/// 8. `[]` RealmConfig account. PDA seeds: ['realm-config', realm]
|
||||||
/// 9. `[]` Optional Voter Weight Record
|
/// 9. `[]` Optional Voter Weight Record
|
||||||
CreateGovernance {
|
CreateGovernance {
|
||||||
/// Governance config
|
/// Governance config
|
||||||
|
@ -138,7 +148,7 @@ pub enum GovernanceInstruction {
|
||||||
/// 8. `[]` System program
|
/// 8. `[]` System program
|
||||||
/// 9. `[]` Sysvar Rent
|
/// 9. `[]` Sysvar Rent
|
||||||
/// 10. `[signer]` Governance authority
|
/// 10. `[signer]` Governance authority
|
||||||
/// 11. `[]` Realm Config
|
/// 11. `[]` RealmConfig account. PDA seeds: ['realm-config', realm]
|
||||||
/// 12. `[]` Optional Voter Weight Record
|
/// 12. `[]` Optional Voter Weight Record
|
||||||
CreateProgramGovernance {
|
CreateProgramGovernance {
|
||||||
/// Governance config
|
/// Governance config
|
||||||
|
@ -162,7 +172,7 @@ pub enum GovernanceInstruction {
|
||||||
/// 5. `[signer]` Governance Authority (Token Owner or Governance Delegate)
|
/// 5. `[signer]` Governance Authority (Token Owner or Governance Delegate)
|
||||||
/// 6. `[signer]` Payer
|
/// 6. `[signer]` Payer
|
||||||
/// 7. `[]` System program
|
/// 7. `[]` System program
|
||||||
/// 8. `[]` Realm Config
|
/// 8. `[]` RealmConfig account. PDA seeds: ['realm-config', realm]
|
||||||
/// 9. `[]` Optional Voter Weight Record
|
/// 9. `[]` Optional Voter Weight Record
|
||||||
CreateProposal {
|
CreateProposal {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -295,7 +305,7 @@ pub enum GovernanceInstruction {
|
||||||
/// Note: In the current version only Council veto is supported
|
/// Note: In the current version only Council veto is supported
|
||||||
/// 8. `[signer]` Payer
|
/// 8. `[signer]` Payer
|
||||||
/// 9. `[]` System program
|
/// 9. `[]` System program
|
||||||
/// 10. `[]` Realm Config
|
/// 10. `[]` RealmConfig account. PDA seeds: ['realm-config', realm]
|
||||||
/// 11. `[]` Optional Voter Weight Record
|
/// 11. `[]` Optional Voter Weight Record
|
||||||
/// 12. `[]` Optional Max Voter Weight Record
|
/// 12. `[]` Optional Max Voter Weight Record
|
||||||
CastVote {
|
CastVote {
|
||||||
|
@ -311,7 +321,7 @@ pub enum GovernanceInstruction {
|
||||||
/// 2. `[writable]` Proposal account
|
/// 2. `[writable]` Proposal account
|
||||||
/// 3. `[writable]` TokenOwnerRecord of the Proposal owner
|
/// 3. `[writable]` TokenOwnerRecord of the Proposal owner
|
||||||
/// 4. `[]` Governing Token Mint
|
/// 4. `[]` Governing Token Mint
|
||||||
/// 5. `[]` Realm Config
|
/// 5. `[]` RealmConfig account. PDA seeds: ['realm-config', realm]
|
||||||
/// 6. `[]` Optional Max Voter Weight Record
|
/// 6. `[]` Optional Max Voter Weight Record
|
||||||
FinalizeVote {},
|
FinalizeVote {},
|
||||||
|
|
||||||
|
@ -355,7 +365,7 @@ pub enum GovernanceInstruction {
|
||||||
/// 7. `[]` System program
|
/// 7. `[]` System program
|
||||||
/// 8. `[]` Sysvar Rent
|
/// 8. `[]` Sysvar Rent
|
||||||
/// 8. `[signer]` Governance authority
|
/// 8. `[signer]` Governance authority
|
||||||
/// 9. `[]` Realm Config
|
/// 9. `[]` RealmConfig account. PDA seeds: ['realm-config', realm]
|
||||||
/// 10. `[]` Optional Voter Weight Record
|
/// 10. `[]` Optional Voter Weight Record
|
||||||
CreateMintGovernance {
|
CreateMintGovernance {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -381,7 +391,7 @@ pub enum GovernanceInstruction {
|
||||||
/// 7. `[]` System program
|
/// 7. `[]` System program
|
||||||
/// 8. `[]` Sysvar Rent
|
/// 8. `[]` Sysvar Rent
|
||||||
/// 9. `[signer]` Governance authority
|
/// 9. `[signer]` Governance authority
|
||||||
/// 10. `[]` Realm Config
|
/// 10. `[]` RealmConfig account. PDA seeds: ['realm-config', realm]
|
||||||
/// 11. `[]` Optional Voter Weight Record
|
/// 11. `[]` Optional Voter Weight Record
|
||||||
CreateTokenGovernance {
|
CreateTokenGovernance {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -438,10 +448,14 @@ pub enum GovernanceInstruction {
|
||||||
/// The account will be created with the Realm PDA as its owner
|
/// The account will be created with the Realm PDA as its owner
|
||||||
/// 4. `[]` System
|
/// 4. `[]` System
|
||||||
/// 5. `[writable]` RealmConfig account. PDA seeds: ['realm-config', realm]
|
/// 5. `[writable]` RealmConfig account. PDA seeds: ['realm-config', realm]
|
||||||
|
///
|
||||||
/// 6. `[]` Optional Community Voter Weight Addin Program Id
|
/// 6. `[]` Optional Community Voter Weight Addin Program Id
|
||||||
/// 7. `[]` Optional Max Community Voter Weight Addin Program Id
|
/// 7. `[]` Optional Max Community Voter Weight Addin Program Id
|
||||||
/// 8. `[signer]` Optional Payer
|
///
|
||||||
|
/// 8. `[]` Optional Council Voter Weight Addin Program Id
|
||||||
|
/// 9. `[]` Optional Max Council Voter Weight Addin Program Id
|
||||||
|
///
|
||||||
|
/// 10. `[signer]` Optional Payer. Required if RealmConfig doesn't exist and needs to be created
|
||||||
SetRealmConfig {
|
SetRealmConfig {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
/// Realm config args
|
/// Realm config args
|
||||||
|
@ -475,6 +489,22 @@ pub enum GovernanceInstruction {
|
||||||
/// 2. `[signer]` Payer
|
/// 2. `[signer]` Payer
|
||||||
/// 3. `[]` System
|
/// 3. `[]` System
|
||||||
CreateNativeTreasury,
|
CreateNativeTreasury,
|
||||||
|
|
||||||
|
/// Revokes (burns) membership governing tokens for the given TokenOwnerRecord and hence takes away governance power from the TokenOwner
|
||||||
|
/// Note: If there are active votes for the TokenOwner then the vote weights won't be updated automatically
|
||||||
|
///
|
||||||
|
/// 0. `[]` Realm account
|
||||||
|
/// 1. `[signer]` Realm authority
|
||||||
|
/// 2. `[writable]` Governing Token Holding account. PDA seeds: ['governance',realm, governing_token_mint]
|
||||||
|
/// 3. `[writable]` TokenOwnerRecord account. PDA seeds: ['governance',realm, governing_token_mint, governing_token_owner]
|
||||||
|
/// 4. `[writable]` GoverningTokenMint
|
||||||
|
/// 5. `[]` RealmConfig account. PDA seeds: ['realm-config', realm]
|
||||||
|
/// 6. `[]` SPL Token program
|
||||||
|
RevokeGoverningTokens {
|
||||||
|
/// The amount to revoke
|
||||||
|
#[allow(dead_code)]
|
||||||
|
amount: u64,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates CreateRealm instruction
|
/// Creates CreateRealm instruction
|
||||||
|
@ -486,8 +516,9 @@ pub fn create_realm(
|
||||||
community_token_mint: &Pubkey,
|
community_token_mint: &Pubkey,
|
||||||
payer: &Pubkey,
|
payer: &Pubkey,
|
||||||
council_token_mint: Option<Pubkey>,
|
council_token_mint: Option<Pubkey>,
|
||||||
community_voter_weight_addin: Option<Pubkey>,
|
// Accounts Args
|
||||||
max_community_voter_weight_addin: Option<Pubkey>,
|
community_token_config_args: Option<GoverningTokenConfigAccountArgs>,
|
||||||
|
council_token_config_args: Option<GoverningTokenConfigAccountArgs>,
|
||||||
// Args
|
// Args
|
||||||
name: String,
|
name: String,
|
||||||
min_community_weight_to_create_governance: u64,
|
min_community_weight_to_create_governance: u64,
|
||||||
|
@ -519,40 +550,22 @@ pub fn create_realm(
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
let use_community_voter_weight_addin =
|
|
||||||
if let Some(community_voter_weight_addin) = community_voter_weight_addin {
|
|
||||||
accounts.push(AccountMeta::new_readonly(
|
|
||||||
community_voter_weight_addin,
|
|
||||||
false,
|
|
||||||
));
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
let use_max_community_voter_weight_addin =
|
|
||||||
if let Some(max_community_voter_weight_addin) = max_community_voter_weight_addin {
|
|
||||||
accounts.push(AccountMeta::new_readonly(
|
|
||||||
max_community_voter_weight_addin,
|
|
||||||
false,
|
|
||||||
));
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
if use_community_voter_weight_addin || use_max_community_voter_weight_addin {
|
|
||||||
let realm_config_address = get_realm_config_address(program_id, &realm_address);
|
let realm_config_address = get_realm_config_address(program_id, &realm_address);
|
||||||
accounts.push(AccountMeta::new(realm_config_address, false));
|
accounts.push(AccountMeta::new(realm_config_address, false));
|
||||||
}
|
|
||||||
|
let community_token_config_args =
|
||||||
|
with_governing_token_config_args(&mut accounts, community_token_config_args);
|
||||||
|
|
||||||
|
let council_token_config_args =
|
||||||
|
with_governing_token_config_args(&mut accounts, council_token_config_args);
|
||||||
|
|
||||||
let instruction = GovernanceInstruction::CreateRealm {
|
let instruction = GovernanceInstruction::CreateRealm {
|
||||||
config_args: RealmConfigArgs {
|
config_args: RealmConfigArgs {
|
||||||
use_council_mint,
|
use_council_mint,
|
||||||
min_community_weight_to_create_governance,
|
min_community_weight_to_create_governance,
|
||||||
community_mint_max_vote_weight_source,
|
community_mint_max_vote_weight_source,
|
||||||
use_community_voter_weight_addin,
|
community_token_config_args,
|
||||||
use_max_community_voter_weight_addin,
|
council_token_config_args,
|
||||||
},
|
},
|
||||||
name,
|
name,
|
||||||
};
|
};
|
||||||
|
@ -572,7 +585,7 @@ pub fn deposit_governing_tokens(
|
||||||
realm: &Pubkey,
|
realm: &Pubkey,
|
||||||
governing_token_source: &Pubkey,
|
governing_token_source: &Pubkey,
|
||||||
governing_token_owner: &Pubkey,
|
governing_token_owner: &Pubkey,
|
||||||
governing_token_transfer_authority: &Pubkey,
|
governing_token_source_authority: &Pubkey,
|
||||||
payer: &Pubkey,
|
payer: &Pubkey,
|
||||||
// Args
|
// Args
|
||||||
amount: u64,
|
amount: u64,
|
||||||
|
@ -588,16 +601,19 @@ pub fn deposit_governing_tokens(
|
||||||
let governing_token_holding_address =
|
let governing_token_holding_address =
|
||||||
get_governing_token_holding_address(program_id, realm, governing_token_mint);
|
get_governing_token_holding_address(program_id, realm, governing_token_mint);
|
||||||
|
|
||||||
|
let realm_config_address = get_realm_config_address(program_id, realm);
|
||||||
|
|
||||||
let accounts = vec![
|
let accounts = vec![
|
||||||
AccountMeta::new_readonly(*realm, false),
|
AccountMeta::new_readonly(*realm, false),
|
||||||
AccountMeta::new(governing_token_holding_address, false),
|
AccountMeta::new(governing_token_holding_address, false),
|
||||||
AccountMeta::new(*governing_token_source, false),
|
AccountMeta::new(*governing_token_source, false),
|
||||||
AccountMeta::new_readonly(*governing_token_owner, true),
|
AccountMeta::new_readonly(*governing_token_owner, true),
|
||||||
AccountMeta::new_readonly(*governing_token_transfer_authority, true),
|
AccountMeta::new_readonly(*governing_token_source_authority, true),
|
||||||
AccountMeta::new(token_owner_record_address, false),
|
AccountMeta::new(token_owner_record_address, false),
|
||||||
AccountMeta::new(*payer, true),
|
AccountMeta::new(*payer, true),
|
||||||
AccountMeta::new_readonly(system_program::id(), false),
|
AccountMeta::new_readonly(system_program::id(), false),
|
||||||
AccountMeta::new_readonly(spl_token::id(), false),
|
AccountMeta::new_readonly(spl_token::id(), false),
|
||||||
|
AccountMeta::new_readonly(realm_config_address, false),
|
||||||
];
|
];
|
||||||
|
|
||||||
let instruction = GovernanceInstruction::DepositGoverningTokens { amount };
|
let instruction = GovernanceInstruction::DepositGoverningTokens { amount };
|
||||||
|
@ -629,6 +645,8 @@ pub fn withdraw_governing_tokens(
|
||||||
let governing_token_holding_address =
|
let governing_token_holding_address =
|
||||||
get_governing_token_holding_address(program_id, realm, governing_token_mint);
|
get_governing_token_holding_address(program_id, realm, governing_token_mint);
|
||||||
|
|
||||||
|
let realm_config_address = get_realm_config_address(program_id, realm);
|
||||||
|
|
||||||
let accounts = vec![
|
let accounts = vec![
|
||||||
AccountMeta::new_readonly(*realm, false),
|
AccountMeta::new_readonly(*realm, false),
|
||||||
AccountMeta::new(governing_token_holding_address, false),
|
AccountMeta::new(governing_token_holding_address, false),
|
||||||
|
@ -636,6 +654,7 @@ pub fn withdraw_governing_tokens(
|
||||||
AccountMeta::new_readonly(*governing_token_owner, true),
|
AccountMeta::new_readonly(*governing_token_owner, true),
|
||||||
AccountMeta::new(token_owner_record_address, false),
|
AccountMeta::new(token_owner_record_address, false),
|
||||||
AccountMeta::new_readonly(spl_token::id(), false),
|
AccountMeta::new_readonly(spl_token::id(), false),
|
||||||
|
AccountMeta::new_readonly(realm_config_address, false),
|
||||||
];
|
];
|
||||||
|
|
||||||
let instruction = GovernanceInstruction::WithdrawGoverningTokens {};
|
let instruction = GovernanceInstruction::WithdrawGoverningTokens {};
|
||||||
|
@ -1355,8 +1374,9 @@ pub fn set_realm_config(
|
||||||
realm_authority: &Pubkey,
|
realm_authority: &Pubkey,
|
||||||
council_token_mint: Option<Pubkey>,
|
council_token_mint: Option<Pubkey>,
|
||||||
payer: &Pubkey,
|
payer: &Pubkey,
|
||||||
community_voter_weight_addin: Option<Pubkey>,
|
// Accounts Args
|
||||||
max_community_voter_weight_addin: Option<Pubkey>,
|
community_token_config_args: Option<GoverningTokenConfigAccountArgs>,
|
||||||
|
council_token_config_args: Option<GoverningTokenConfigAccountArgs>,
|
||||||
// Args
|
// Args
|
||||||
min_community_weight_to_create_governance: u64,
|
min_community_weight_to_create_governance: u64,
|
||||||
community_mint_max_vote_weight_source: MintMaxVoteWeightSource,
|
community_mint_max_vote_weight_source: MintMaxVoteWeightSource,
|
||||||
|
@ -1384,39 +1404,21 @@ pub fn set_realm_config(
|
||||||
let realm_config_address = get_realm_config_address(program_id, realm);
|
let realm_config_address = get_realm_config_address(program_id, realm);
|
||||||
accounts.push(AccountMeta::new(realm_config_address, false));
|
accounts.push(AccountMeta::new(realm_config_address, false));
|
||||||
|
|
||||||
let use_community_voter_weight_addin =
|
let community_token_config_args =
|
||||||
if let Some(community_voter_weight_addin) = community_voter_weight_addin {
|
with_governing_token_config_args(&mut accounts, community_token_config_args);
|
||||||
accounts.push(AccountMeta::new_readonly(
|
|
||||||
community_voter_weight_addin,
|
|
||||||
false,
|
|
||||||
));
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
let use_max_community_voter_weight_addin =
|
let council_token_config_args =
|
||||||
if let Some(max_community_voter_weight_addin) = max_community_voter_weight_addin {
|
with_governing_token_config_args(&mut accounts, council_token_config_args);
|
||||||
accounts.push(AccountMeta::new_readonly(
|
|
||||||
max_community_voter_weight_addin,
|
|
||||||
false,
|
|
||||||
));
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
if use_community_voter_weight_addin || use_max_community_voter_weight_addin {
|
|
||||||
accounts.push(AccountMeta::new(*payer, true));
|
accounts.push(AccountMeta::new(*payer, true));
|
||||||
}
|
|
||||||
|
|
||||||
let instruction = GovernanceInstruction::SetRealmConfig {
|
let instruction = GovernanceInstruction::SetRealmConfig {
|
||||||
config_args: RealmConfigArgs {
|
config_args: RealmConfigArgs {
|
||||||
use_council_mint,
|
use_council_mint,
|
||||||
min_community_weight_to_create_governance,
|
min_community_weight_to_create_governance,
|
||||||
community_mint_max_vote_weight_source,
|
community_mint_max_vote_weight_source,
|
||||||
use_community_voter_weight_addin,
|
community_token_config_args,
|
||||||
use_max_community_voter_weight_addin,
|
council_token_config_args,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1536,3 +1538,77 @@ pub fn create_native_treasury(
|
||||||
data: instruction.try_to_vec().unwrap(),
|
data: instruction.try_to_vec().unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates RevokeGoverningTokens instruction
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn revoke_governing_tokens(
|
||||||
|
program_id: &Pubkey,
|
||||||
|
// Accounts
|
||||||
|
realm: &Pubkey,
|
||||||
|
realm_authority: &Pubkey,
|
||||||
|
governing_token_owner: &Pubkey,
|
||||||
|
governing_token_mint: &Pubkey,
|
||||||
|
// Args
|
||||||
|
amount: u64,
|
||||||
|
) -> Instruction {
|
||||||
|
let token_owner_record_address = get_token_owner_record_address(
|
||||||
|
program_id,
|
||||||
|
realm,
|
||||||
|
governing_token_mint,
|
||||||
|
governing_token_owner,
|
||||||
|
);
|
||||||
|
|
||||||
|
let governing_token_holding_address =
|
||||||
|
get_governing_token_holding_address(program_id, realm, governing_token_mint);
|
||||||
|
|
||||||
|
let realm_config_address = get_realm_config_address(program_id, realm);
|
||||||
|
|
||||||
|
let accounts = vec![
|
||||||
|
AccountMeta::new_readonly(*realm, false),
|
||||||
|
AccountMeta::new_readonly(*realm_authority, true),
|
||||||
|
AccountMeta::new(governing_token_holding_address, false),
|
||||||
|
AccountMeta::new(token_owner_record_address, false),
|
||||||
|
AccountMeta::new(*governing_token_mint, false),
|
||||||
|
AccountMeta::new_readonly(realm_config_address, false),
|
||||||
|
AccountMeta::new_readonly(spl_token::id(), false),
|
||||||
|
];
|
||||||
|
|
||||||
|
let instruction = GovernanceInstruction::RevokeGoverningTokens { amount };
|
||||||
|
|
||||||
|
Instruction {
|
||||||
|
program_id: *program_id,
|
||||||
|
accounts,
|
||||||
|
data: instruction.try_to_vec().unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds accounts specified by GoverningTokenConfigAccountArgs
|
||||||
|
/// and returns GoverningTokenConfigArgs
|
||||||
|
pub fn with_governing_token_config_args(
|
||||||
|
accounts: &mut Vec<AccountMeta>,
|
||||||
|
governing_token_config_args: Option<GoverningTokenConfigAccountArgs>,
|
||||||
|
) -> GoverningTokenConfigArgs {
|
||||||
|
let governing_token_config_args = governing_token_config_args.unwrap_or_default();
|
||||||
|
|
||||||
|
let use_voter_weight_addin =
|
||||||
|
if let Some(voter_weight_addin) = governing_token_config_args.voter_weight_addin {
|
||||||
|
accounts.push(AccountMeta::new_readonly(voter_weight_addin, false));
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
let use_max_voter_weight_addin =
|
||||||
|
if let Some(max_voter_weight_addin) = governing_token_config_args.max_voter_weight_addin {
|
||||||
|
accounts.push(AccountMeta::new_readonly(max_voter_weight_addin, false));
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
GoverningTokenConfigArgs {
|
||||||
|
use_voter_weight_addin,
|
||||||
|
use_max_voter_weight_addin,
|
||||||
|
token_type: governing_token_config_args.token_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ mod process_insert_transaction;
|
||||||
mod process_relinquish_vote;
|
mod process_relinquish_vote;
|
||||||
mod process_remove_signatory;
|
mod process_remove_signatory;
|
||||||
mod process_remove_transaction;
|
mod process_remove_transaction;
|
||||||
|
mod process_revoke_governing_tokens;
|
||||||
mod process_set_governance_config;
|
mod process_set_governance_config;
|
||||||
mod process_set_governance_delegate;
|
mod process_set_governance_delegate;
|
||||||
mod process_set_realm_authority;
|
mod process_set_realm_authority;
|
||||||
|
@ -48,6 +49,7 @@ use process_insert_transaction::*;
|
||||||
use process_relinquish_vote::*;
|
use process_relinquish_vote::*;
|
||||||
use process_remove_signatory::*;
|
use process_remove_signatory::*;
|
||||||
use process_remove_transaction::*;
|
use process_remove_transaction::*;
|
||||||
|
use process_revoke_governing_tokens::*;
|
||||||
use process_set_governance_config::*;
|
use process_set_governance_config::*;
|
||||||
use process_set_governance_delegate::*;
|
use process_set_governance_delegate::*;
|
||||||
use process_set_realm_authority::*;
|
use process_set_realm_authority::*;
|
||||||
|
@ -213,5 +215,9 @@ pub fn process_instruction(
|
||||||
GovernanceInstruction::CreateNativeTreasury {} => {
|
GovernanceInstruction::CreateNativeTreasury {} => {
|
||||||
process_create_native_treasury(program_id, accounts)
|
process_create_native_treasury(program_id, accounts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GovernanceInstruction::RevokeGoverningTokens { amount } => {
|
||||||
|
process_revoke_governing_tokens(program_id, accounts, amount)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ use crate::{
|
||||||
governance::get_governance_data_for_realm,
|
governance::get_governance_data_for_realm,
|
||||||
proposal::get_proposal_data_for_governance_and_governing_mint,
|
proposal::get_proposal_data_for_governance_and_governing_mint,
|
||||||
realm::get_realm_data_for_governing_token_mint,
|
realm::get_realm_data_for_governing_token_mint,
|
||||||
|
realm_config::get_realm_config_data_for_realm,
|
||||||
token_owner_record::{
|
token_owner_record::{
|
||||||
get_token_owner_record_data_for_proposal_owner,
|
get_token_owner_record_data_for_proposal_owner,
|
||||||
get_token_owner_record_data_for_realm_and_governing_mint,
|
get_token_owner_record_data_for_realm_and_governing_mint,
|
||||||
|
@ -104,17 +105,14 @@ pub fn process_cast_vote(
|
||||||
.checked_add(1)
|
.checked_add(1)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Note: When both voter_weight and max_voter_weight addins are used the realm_config will be deserialized twice in resolve_voter_weight() and resolve_max_voter_weight()
|
|
||||||
// It can't be deserialized eagerly because some realms won't have the config if they don't use any of the advanced options
|
|
||||||
// This extra deserialisation should be acceptable to keep things simple and encapsulated.
|
|
||||||
let realm_config_info = next_account_info(account_info_iter)?; // 9
|
let realm_config_info = next_account_info(account_info_iter)?; // 9
|
||||||
|
let realm_config_data =
|
||||||
|
get_realm_config_data_for_realm(program_id, realm_config_info, realm_info.key)?;
|
||||||
|
|
||||||
let voter_weight = voter_token_owner_record_data.resolve_voter_weight(
|
let voter_weight = voter_token_owner_record_data.resolve_voter_weight(
|
||||||
program_id,
|
account_info_iter, // voter_weight_record *10
|
||||||
realm_config_info,
|
|
||||||
account_info_iter, // voter_weight_record 10
|
|
||||||
realm_info.key,
|
|
||||||
&realm_data,
|
&realm_data,
|
||||||
|
&realm_config_data,
|
||||||
VoterWeightAction::CastVote,
|
VoterWeightAction::CastVote,
|
||||||
proposal_info.key,
|
proposal_info.key,
|
||||||
)?;
|
)?;
|
||||||
|
@ -152,12 +150,11 @@ pub fn process_cast_vote(
|
||||||
}
|
}
|
||||||
|
|
||||||
let max_voter_weight = proposal_data.resolve_max_voter_weight(
|
let max_voter_weight = proposal_data.resolve_max_voter_weight(
|
||||||
program_id,
|
|
||||||
realm_config_info,
|
|
||||||
vote_governing_token_mint_info,
|
|
||||||
account_info_iter, // max_voter_weight_record 11
|
account_info_iter, // max_voter_weight_record 11
|
||||||
realm_info.key,
|
realm_info.key,
|
||||||
&realm_data,
|
&realm_data,
|
||||||
|
&realm_config_data,
|
||||||
|
vote_governing_token_mint_info,
|
||||||
&vote_kind,
|
&vote_kind,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ use crate::{
|
||||||
ProposalOption, ProposalV2, VoteType,
|
ProposalOption, ProposalV2, VoteType,
|
||||||
},
|
},
|
||||||
realm::get_realm_data_for_governing_token_mint,
|
realm::get_realm_data_for_governing_token_mint,
|
||||||
|
realm_config::get_realm_config_data_for_realm,
|
||||||
token_owner_record::get_token_owner_record_data_for_realm,
|
token_owner_record::get_token_owner_record_data_for_realm,
|
||||||
vote_record::VoteKind,
|
vote_record::VoteKind,
|
||||||
},
|
},
|
||||||
|
@ -82,13 +83,13 @@ pub fn process_create_proposal(
|
||||||
.assert_token_owner_or_delegate_is_signer(governance_authority_info)?;
|
.assert_token_owner_or_delegate_is_signer(governance_authority_info)?;
|
||||||
|
|
||||||
let realm_config_info = next_account_info(account_info_iter)?; // 10
|
let realm_config_info = next_account_info(account_info_iter)?; // 10
|
||||||
|
let realm_config_data =
|
||||||
|
get_realm_config_data_for_realm(program_id, realm_config_info, realm_info.key)?;
|
||||||
|
|
||||||
let voter_weight = proposal_owner_record_data.resolve_voter_weight(
|
let voter_weight = proposal_owner_record_data.resolve_voter_weight(
|
||||||
program_id,
|
account_info_iter, // voter_weight_record *11
|
||||||
realm_config_info,
|
|
||||||
account_info_iter,
|
|
||||||
realm_info.key,
|
|
||||||
&realm_data,
|
&realm_data,
|
||||||
|
&realm_config_data,
|
||||||
VoterWeightAction::CreateProposal,
|
VoterWeightAction::CreateProposal,
|
||||||
governance_info.key,
|
governance_info.key,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -17,7 +17,10 @@ use crate::{
|
||||||
assert_valid_realm_config_args, get_governing_token_holding_address_seeds,
|
assert_valid_realm_config_args, get_governing_token_holding_address_seeds,
|
||||||
get_realm_address_seeds, RealmConfig, RealmConfigArgs, RealmV2,
|
get_realm_address_seeds, RealmConfig, RealmConfigArgs, RealmV2,
|
||||||
},
|
},
|
||||||
realm_config::{get_realm_config_address_seeds, RealmConfigAccount},
|
realm_config::{
|
||||||
|
get_realm_config_address_seeds, resolve_governing_token_config, RealmConfigAccount,
|
||||||
|
Reserved110,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
tools::spl_token::create_spl_token_account_signed,
|
tools::spl_token::create_spl_token_account_signed,
|
||||||
};
|
};
|
||||||
|
@ -27,7 +30,7 @@ pub fn process_create_realm(
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
accounts: &[AccountInfo],
|
accounts: &[AccountInfo],
|
||||||
name: String,
|
name: String,
|
||||||
config_args: RealmConfigArgs,
|
realm_config_args: RealmConfigArgs,
|
||||||
) -> ProgramResult {
|
) -> ProgramResult {
|
||||||
let account_info_iter = &mut accounts.iter();
|
let account_info_iter = &mut accounts.iter();
|
||||||
|
|
||||||
|
@ -46,8 +49,9 @@ pub fn process_create_realm(
|
||||||
return Err(GovernanceError::RealmAlreadyExists.into());
|
return Err(GovernanceError::RealmAlreadyExists.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_valid_realm_config_args(&config_args)?;
|
assert_valid_realm_config_args(&realm_config_args)?;
|
||||||
|
|
||||||
|
// Create Community token holding account
|
||||||
create_spl_token_account_signed(
|
create_spl_token_account_signed(
|
||||||
payer_info,
|
payer_info,
|
||||||
governance_token_holding_info,
|
governance_token_holding_info,
|
||||||
|
@ -61,7 +65,8 @@ pub fn process_create_realm(
|
||||||
rent,
|
rent,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let council_token_mint_address = if config_args.use_council_mint {
|
// Create Council token holding account
|
||||||
|
let council_token_mint_address = if realm_config_args.use_council_mint {
|
||||||
let council_token_mint_info = next_account_info(account_info_iter)?; // 8
|
let council_token_mint_info = next_account_info(account_info_iter)?; // 8
|
||||||
let council_token_holding_info = next_account_info(account_info_iter)?; // 9
|
let council_token_holding_info = next_account_info(account_info_iter)?; // 9
|
||||||
|
|
||||||
|
@ -83,35 +88,27 @@ pub fn process_create_realm(
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Setup config for addins
|
// Create and serialzie RealmConfig
|
||||||
|
let realm_config_info = next_account_info(account_info_iter)?; // 10
|
||||||
|
|
||||||
let community_voter_weight_addin = if config_args.use_community_voter_weight_addin {
|
// 11, 12
|
||||||
let community_voter_weight_addin_info = next_account_info(account_info_iter)?; // 10
|
let community_token_config = resolve_governing_token_config(
|
||||||
Some(*community_voter_weight_addin_info.key)
|
account_info_iter,
|
||||||
} else {
|
&realm_config_args.community_token_config_args,
|
||||||
None
|
)?;
|
||||||
};
|
|
||||||
|
|
||||||
let max_community_voter_weight_addin = if config_args.use_max_community_voter_weight_addin {
|
// 13, 14
|
||||||
let max_community_voter_weight_addin_info = next_account_info(account_info_iter)?; // 11
|
let council_token_config = resolve_governing_token_config(
|
||||||
Some(*max_community_voter_weight_addin_info.key)
|
account_info_iter,
|
||||||
} else {
|
&realm_config_args.council_token_config_args,
|
||||||
None
|
)?;
|
||||||
};
|
|
||||||
|
|
||||||
if config_args.use_community_voter_weight_addin
|
|
||||||
|| config_args.use_max_community_voter_weight_addin
|
|
||||||
{
|
|
||||||
let realm_config_info = next_account_info(account_info_iter)?; // 12
|
|
||||||
|
|
||||||
let realm_config_data = RealmConfigAccount {
|
let realm_config_data = RealmConfigAccount {
|
||||||
account_type: GovernanceAccountType::RealmConfig,
|
account_type: GovernanceAccountType::RealmConfig,
|
||||||
realm: *realm_info.key,
|
realm: *realm_info.key,
|
||||||
community_voter_weight_addin,
|
community_token_config,
|
||||||
max_community_voter_weight_addin,
|
council_token_config,
|
||||||
council_voter_weight_addin: None,
|
reserved: Reserved110::default(),
|
||||||
council_max_vote_weight_addin: None,
|
|
||||||
reserved: [0; 128],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
create_and_serialize_account_signed::<RealmConfigAccount>(
|
create_and_serialize_account_signed::<RealmConfigAccount>(
|
||||||
|
@ -123,8 +120,8 @@ pub fn process_create_realm(
|
||||||
system_info,
|
system_info,
|
||||||
rent,
|
rent,
|
||||||
)?;
|
)?;
|
||||||
}
|
|
||||||
|
|
||||||
|
// Create and serialize Realm
|
||||||
let realm_data = RealmV2 {
|
let realm_data = RealmV2 {
|
||||||
account_type: GovernanceAccountType::RealmV2,
|
account_type: GovernanceAccountType::RealmV2,
|
||||||
community_mint: *governance_token_mint_info.key,
|
community_mint: *governance_token_mint_info.key,
|
||||||
|
@ -135,12 +132,12 @@ pub fn process_create_realm(
|
||||||
config: RealmConfig {
|
config: RealmConfig {
|
||||||
council_mint: council_token_mint_address,
|
council_mint: council_token_mint_address,
|
||||||
reserved: [0; 6],
|
reserved: [0; 6],
|
||||||
community_mint_max_vote_weight_source: config_args
|
community_mint_max_vote_weight_source: realm_config_args
|
||||||
.community_mint_max_vote_weight_source,
|
.community_mint_max_vote_weight_source,
|
||||||
min_community_weight_to_create_governance: config_args
|
min_community_weight_to_create_governance: realm_config_args
|
||||||
.min_community_weight_to_create_governance,
|
.min_community_weight_to_create_governance,
|
||||||
use_community_voter_weight_addin: config_args.use_community_voter_weight_addin,
|
legacy1: 0,
|
||||||
use_max_community_voter_weight_addin: config_args.use_max_community_voter_weight_addin,
|
legacy2: 0,
|
||||||
},
|
},
|
||||||
voting_proposal_count: 0,
|
voting_proposal_count: 0,
|
||||||
reserved_v2: [0; 128],
|
reserved_v2: [0; 128],
|
||||||
|
|
|
@ -14,12 +14,16 @@ use crate::{
|
||||||
state::{
|
state::{
|
||||||
enums::GovernanceAccountType,
|
enums::GovernanceAccountType,
|
||||||
realm::get_realm_data,
|
realm::get_realm_data,
|
||||||
|
realm_config::get_realm_config_data_for_realm,
|
||||||
token_owner_record::{
|
token_owner_record::{
|
||||||
get_token_owner_record_address_seeds, get_token_owner_record_data_for_seeds,
|
get_token_owner_record_address_seeds, get_token_owner_record_data_for_seeds,
|
||||||
TokenOwnerRecordV2,
|
TokenOwnerRecordV2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
tools::spl_token::{get_spl_token_mint, get_spl_token_owner, transfer_spl_tokens},
|
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
|
/// Processes DepositGoverningTokens instruction
|
||||||
|
@ -34,11 +38,12 @@ pub fn process_deposit_governing_tokens(
|
||||||
let governing_token_holding_info = next_account_info(account_info_iter)?; // 1
|
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_source_info = next_account_info(account_info_iter)?; // 2
|
||||||
let governing_token_owner_info = next_account_info(account_info_iter)?; // 3
|
let governing_token_owner_info = next_account_info(account_info_iter)?; // 3
|
||||||
let governing_token_transfer_authority_info = next_account_info(account_info_iter)?; // 4
|
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 token_owner_record_info = next_account_info(account_info_iter)?; // 5
|
||||||
let payer_info = next_account_info(account_info_iter)?; // 6
|
let payer_info = next_account_info(account_info_iter)?; // 6
|
||||||
let system_info = next_account_info(account_info_iter)?; // 7
|
let system_info = next_account_info(account_info_iter)?; // 7
|
||||||
let spl_token_info = next_account_info(account_info_iter)?; // 8
|
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 rent = Rent::get()?;
|
||||||
|
|
||||||
|
@ -52,13 +57,32 @@ pub fn process_deposit_governing_tokens(
|
||||||
governing_token_holding_info.key,
|
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(
|
transfer_spl_tokens(
|
||||||
governing_token_source_info,
|
governing_token_source_info,
|
||||||
governing_token_holding_info,
|
governing_token_holding_info,
|
||||||
governing_token_transfer_authority_info,
|
governing_token_source_authority_info,
|
||||||
amount,
|
amount,
|
||||||
spl_token_info,
|
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(
|
let token_owner_record_address_seeds = get_token_owner_record_address_seeds(
|
||||||
realm_info.key,
|
realm_info.key,
|
||||||
|
@ -68,11 +92,7 @@ pub fn process_deposit_governing_tokens(
|
||||||
|
|
||||||
if token_owner_record_info.data_is_empty() {
|
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
|
// Deposited tokens can only be withdrawn by the owner so let's make sure the owner signed the transaction
|
||||||
let governing_token_owner = get_spl_token_owner(governing_token_source_info)?;
|
if !governing_token_owner_info.is_signer {
|
||||||
|
|
||||||
if !(governing_token_owner == *governing_token_owner_info.key
|
|
||||||
&& governing_token_owner_info.is_signer)
|
|
||||||
{
|
|
||||||
return Err(GovernanceError::GoverningTokenOwnerMustSign.into());
|
return Err(GovernanceError::GoverningTokenOwnerMustSign.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use solana_program::{
|
||||||
use crate::state::{
|
use crate::state::{
|
||||||
governance::get_governance_data_for_realm,
|
governance::get_governance_data_for_realm,
|
||||||
proposal::get_proposal_data_for_governance_and_governing_mint,
|
proposal::get_proposal_data_for_governance_and_governing_mint,
|
||||||
realm::get_realm_data_for_governing_token_mint,
|
realm::get_realm_data_for_governing_token_mint, realm_config::get_realm_config_data_for_realm,
|
||||||
token_owner_record::get_token_owner_record_data_for_proposal_owner, vote_record::VoteKind,
|
token_owner_record::get_token_owner_record_data_for_proposal_owner, vote_record::VoteKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,14 +44,15 @@ pub fn process_finalize_vote(program_id: &Pubkey, accounts: &[AccountInfo]) -> P
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let realm_config_info = next_account_info(account_info_iter)?; //5
|
let realm_config_info = next_account_info(account_info_iter)?; //5
|
||||||
|
let realm_config_data =
|
||||||
|
get_realm_config_data_for_realm(program_id, realm_config_info, realm_info.key)?;
|
||||||
|
|
||||||
let max_voter_weight = proposal_data.resolve_max_voter_weight(
|
let max_voter_weight = proposal_data.resolve_max_voter_weight(
|
||||||
program_id,
|
|
||||||
realm_config_info,
|
|
||||||
governing_token_mint_info,
|
|
||||||
account_info_iter, // *6
|
account_info_iter, // *6
|
||||||
realm_info.key,
|
realm_info.key,
|
||||||
&realm_data,
|
&realm_data,
|
||||||
|
&realm_config_data,
|
||||||
|
governing_token_mint_info,
|
||||||
&VoteKind::Electorate,
|
&VoteKind::Electorate,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
//! Program state processor
|
||||||
|
|
||||||
|
use solana_program::{
|
||||||
|
account_info::{next_account_info, AccountInfo},
|
||||||
|
entrypoint::ProgramResult,
|
||||||
|
pubkey::Pubkey,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
error::GovernanceError,
|
||||||
|
state::{
|
||||||
|
realm::{get_realm_address_seeds, get_realm_data_for_authority},
|
||||||
|
realm_config::get_realm_config_data_for_realm,
|
||||||
|
token_owner_record::get_token_owner_record_data_for_realm_and_governing_mint,
|
||||||
|
},
|
||||||
|
tools::spl_token::burn_spl_tokens_signed,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Processes RevokeGoverningTokens instruction
|
||||||
|
pub fn process_revoke_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 realm_authority_info = next_account_info(account_info_iter)?; // 1
|
||||||
|
|
||||||
|
let governing_token_holding_info = next_account_info(account_info_iter)?; // 2
|
||||||
|
let token_owner_record_info = next_account_info(account_info_iter)?; // 3
|
||||||
|
let governing_token_mint_info = next_account_info(account_info_iter)?; // 4
|
||||||
|
let realm_config_info = next_account_info(account_info_iter)?; // 5
|
||||||
|
|
||||||
|
let spl_token_info = next_account_info(account_info_iter)?; // 6
|
||||||
|
|
||||||
|
let realm_data =
|
||||||
|
get_realm_data_for_authority(program_id, realm_info, realm_authority_info.key)?;
|
||||||
|
|
||||||
|
if !realm_authority_info.is_signer {
|
||||||
|
return Err(GovernanceError::RealmAuthorityMustSign.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
realm_data.assert_is_valid_governing_token_mint_and_holding(
|
||||||
|
program_id,
|
||||||
|
realm_info.key,
|
||||||
|
governing_token_mint_info.key,
|
||||||
|
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_revoke_governing_token(&realm_data, governing_token_mint_info.key)?;
|
||||||
|
|
||||||
|
let mut token_owner_record_data = get_token_owner_record_data_for_realm_and_governing_mint(
|
||||||
|
program_id,
|
||||||
|
token_owner_record_info,
|
||||||
|
realm_info.key,
|
||||||
|
governing_token_mint_info.key,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
token_owner_record_data.governing_token_deposit_amount = token_owner_record_data
|
||||||
|
.governing_token_deposit_amount
|
||||||
|
.checked_sub(amount)
|
||||||
|
.ok_or(GovernanceError::InvalidRevokeAmount)?;
|
||||||
|
|
||||||
|
token_owner_record_data.serialize(&mut *token_owner_record_info.data.borrow_mut())?;
|
||||||
|
|
||||||
|
burn_spl_tokens_signed(
|
||||||
|
governing_token_holding_info,
|
||||||
|
governing_token_mint_info,
|
||||||
|
realm_info,
|
||||||
|
&get_realm_address_seeds(&realm_data.name),
|
||||||
|
program_id,
|
||||||
|
amount,
|
||||||
|
spl_token_info,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -13,10 +13,10 @@ use spl_governance_tools::account::create_and_serialize_account_signed;
|
||||||
use crate::{
|
use crate::{
|
||||||
error::GovernanceError,
|
error::GovernanceError,
|
||||||
state::{
|
state::{
|
||||||
enums::GovernanceAccountType,
|
|
||||||
realm::{assert_valid_realm_config_args, get_realm_data_for_authority, RealmConfigArgs},
|
realm::{assert_valid_realm_config_args, get_realm_data_for_authority, RealmConfigArgs},
|
||||||
realm_config::{
|
realm_config::{
|
||||||
get_realm_config_address_seeds, get_realm_config_data_for_realm, RealmConfigAccount,
|
get_realm_config_address_seeds, get_realm_config_data_for_realm,
|
||||||
|
resolve_governing_token_config, RealmConfigAccount,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -75,44 +75,36 @@ pub fn process_set_realm_config(
|
||||||
}
|
}
|
||||||
|
|
||||||
let system_info = next_account_info(account_info_iter)?; // 4
|
let system_info = next_account_info(account_info_iter)?; // 4
|
||||||
|
|
||||||
let realm_config_info = next_account_info(account_info_iter)?; // 5
|
let realm_config_info = next_account_info(account_info_iter)?; // 5
|
||||||
|
let mut realm_config_data =
|
||||||
|
get_realm_config_data_for_realm(program_id, realm_config_info, realm_info.key)?;
|
||||||
|
|
||||||
// Setup config for addins
|
realm_config_data.assert_can_change_config(&realm_config_args)?;
|
||||||
|
|
||||||
let community_voter_weight_addin = if realm_config_args.use_community_voter_weight_addin {
|
// Setup configs for tokens (plugins and token types)
|
||||||
let community_voter_weight_addin_info = next_account_info(account_info_iter)?; // 6
|
|
||||||
Some(*community_voter_weight_addin_info.key)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let max_community_voter_weight_addin = if realm_config_args.use_max_community_voter_weight_addin
|
// 6, 7
|
||||||
{
|
let community_token_config = resolve_governing_token_config(
|
||||||
let max_community_voter_weight_addin_info = next_account_info(account_info_iter)?; // 7
|
account_info_iter,
|
||||||
Some(*max_community_voter_weight_addin_info.key)
|
&realm_config_args.community_token_config_args,
|
||||||
} else {
|
)?;
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
// If any of the addins is needed then update or create (if doesn't exist yet) RealmConfigAccount
|
// 8, 9
|
||||||
let update_realm_config = if realm_config_args.use_community_voter_weight_addin
|
let council_token_config = resolve_governing_token_config(
|
||||||
|| realm_config_args.use_max_community_voter_weight_addin
|
account_info_iter,
|
||||||
{
|
&realm_config_args.council_token_config_args,
|
||||||
// We need the payer to pay for the new account if it's created
|
)?;
|
||||||
let payer_info = next_account_info(account_info_iter)?; // 8
|
|
||||||
|
|
||||||
// If RealmConfigAccount doesn't exist yet then create it
|
realm_config_data.community_token_config = community_token_config;
|
||||||
|
realm_config_data.council_token_config = council_token_config;
|
||||||
|
|
||||||
|
// Update or create RealmConfigAccount
|
||||||
if realm_config_info.data_is_empty() {
|
if realm_config_info.data_is_empty() {
|
||||||
let realm_config_data = RealmConfigAccount {
|
// For older Realms (pre v3) RealmConfigAccount might not exist yet and we have to create it
|
||||||
account_type: GovernanceAccountType::RealmConfig,
|
|
||||||
realm: *realm_info.key,
|
|
||||||
community_voter_weight_addin,
|
|
||||||
max_community_voter_weight_addin,
|
|
||||||
council_voter_weight_addin: None,
|
|
||||||
council_max_vote_weight_addin: None,
|
|
||||||
reserved: [0; 128],
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// We need the payer to pay for the new account if it's created
|
||||||
|
let payer_info = next_account_info(account_info_iter)?; // 10
|
||||||
let rent = Rent::get()?;
|
let rent = Rent::get()?;
|
||||||
|
|
||||||
create_and_serialize_account_signed::<RealmConfigAccount>(
|
create_and_serialize_account_signed::<RealmConfigAccount>(
|
||||||
|
@ -124,38 +116,19 @@ pub fn process_set_realm_config(
|
||||||
system_info,
|
system_info,
|
||||||
&rent,
|
&rent,
|
||||||
)?;
|
)?;
|
||||||
false // RealmConfigAccount didn't exist and was created
|
|
||||||
} else {
|
} else {
|
||||||
true // RealmConfigAccount existed before and needs to be updated
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// True: If RealmConfigAccount existed before we have to update it to remove the addins which are not used any longer
|
|
||||||
// False: We don't want to setup the addins and RealmConfigAccount didn't exist before
|
|
||||||
realm_data.config.use_community_voter_weight_addin
|
|
||||||
|| realm_data.config.use_max_community_voter_weight_addin
|
|
||||||
};
|
|
||||||
|
|
||||||
if update_realm_config {
|
|
||||||
let mut realm_config_data =
|
|
||||||
get_realm_config_data_for_realm(program_id, realm_config_info, realm_info.key)?;
|
|
||||||
|
|
||||||
realm_config_data.community_voter_weight_addin = community_voter_weight_addin;
|
|
||||||
realm_config_data.max_community_voter_weight_addin = max_community_voter_weight_addin;
|
|
||||||
|
|
||||||
realm_config_data.serialize(&mut *realm_config_info.data.borrow_mut())?;
|
realm_config_data.serialize(&mut *realm_config_info.data.borrow_mut())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update RealmConfig (Realm.config field)
|
||||||
realm_data.config.community_mint_max_vote_weight_source =
|
realm_data.config.community_mint_max_vote_weight_source =
|
||||||
realm_config_args.community_mint_max_vote_weight_source;
|
realm_config_args.community_mint_max_vote_weight_source;
|
||||||
|
|
||||||
realm_data.config.min_community_weight_to_create_governance =
|
realm_data.config.min_community_weight_to_create_governance =
|
||||||
realm_config_args.min_community_weight_to_create_governance;
|
realm_config_args.min_community_weight_to_create_governance;
|
||||||
|
|
||||||
realm_data.config.use_community_voter_weight_addin =
|
realm_data.config.legacy1 = 0;
|
||||||
realm_config_args.use_community_voter_weight_addin;
|
realm_data.config.legacy2 = 0;
|
||||||
|
|
||||||
realm_data.config.use_max_community_voter_weight_addin =
|
|
||||||
realm_config_args.use_max_community_voter_weight_addin;
|
|
||||||
|
|
||||||
realm_data.serialize(&mut *realm_info.data.borrow_mut())?;
|
realm_data.serialize(&mut *realm_info.data.borrow_mut())?;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::{
|
||||||
error::GovernanceError,
|
error::GovernanceError,
|
||||||
state::{
|
state::{
|
||||||
realm::{get_realm_address_seeds, get_realm_data},
|
realm::{get_realm_address_seeds, get_realm_data},
|
||||||
|
realm_config::get_realm_config_data_for_realm,
|
||||||
token_owner_record::{
|
token_owner_record::{
|
||||||
get_token_owner_record_address_seeds, get_token_owner_record_data_for_seeds,
|
get_token_owner_record_address_seeds, get_token_owner_record_data_for_seeds,
|
||||||
},
|
},
|
||||||
|
@ -30,6 +31,7 @@ pub fn process_withdraw_governing_tokens(
|
||||||
let governing_token_owner_info = next_account_info(account_info_iter)?; // 3
|
let governing_token_owner_info = next_account_info(account_info_iter)?; // 3
|
||||||
let token_owner_record_info = next_account_info(account_info_iter)?; // 4
|
let token_owner_record_info = next_account_info(account_info_iter)?; // 4
|
||||||
let spl_token_info = next_account_info(account_info_iter)?; // 5
|
let spl_token_info = next_account_info(account_info_iter)?; // 5
|
||||||
|
let realm_config_info = next_account_info(account_info_iter)?; // 6
|
||||||
|
|
||||||
if !governing_token_owner_info.is_signer {
|
if !governing_token_owner_info.is_signer {
|
||||||
return Err(GovernanceError::GoverningTokenOwnerMustSign.into());
|
return Err(GovernanceError::GoverningTokenOwnerMustSign.into());
|
||||||
|
@ -45,6 +47,11 @@ pub fn process_withdraw_governing_tokens(
|
||||||
governing_token_holding_info.key,
|
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_withdraw_governing_token(&realm_data, &governing_token_mint)?;
|
||||||
|
|
||||||
let token_owner_record_address_seeds = get_token_owner_record_address_seeds(
|
let token_owner_record_address_seeds = get_token_owner_record_address_seeds(
|
||||||
realm_info.key,
|
realm_info.key,
|
||||||
&governing_token_mint,
|
&governing_token_mint,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
|
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
|
||||||
|
|
||||||
/// Defines all Governance accounts types
|
/// Defines all Governance accounts types
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum GovernanceAccountType {
|
pub enum GovernanceAccountType {
|
||||||
/// Default uninitialized account state
|
/// Default uninitialized account state
|
||||||
Uninitialized,
|
Uninitialized,
|
||||||
|
@ -96,7 +96,7 @@ impl Default for GovernanceAccountType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// What state a Proposal is in
|
/// What state a Proposal is in
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum ProposalState {
|
pub enum ProposalState {
|
||||||
/// Draft - Proposal enters Draft state when it's created
|
/// Draft - Proposal enters Draft state when it's created
|
||||||
Draft,
|
Draft,
|
||||||
|
@ -141,7 +141,7 @@ impl Default for ProposalState {
|
||||||
/// The type of the vote threshold used to resolve a vote on a Proposal
|
/// The type of the vote threshold used to resolve a vote on a Proposal
|
||||||
///
|
///
|
||||||
/// Note: In the current version only YesVotePercentage and Disabled thresholds are supported
|
/// Note: In the current version only YesVotePercentage and Disabled thresholds are supported
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum VoteThreshold {
|
pub enum VoteThreshold {
|
||||||
/// Voting threshold of Yes votes in % required to tip the vote (Approval Quorum)
|
/// Voting threshold of Yes votes in % required to tip the vote (Approval Quorum)
|
||||||
/// It's the percentage of tokens out of the entire pool of governance tokens eligible to vote
|
/// It's the percentage of tokens out of the entire pool of governance tokens eligible to vote
|
||||||
|
@ -173,7 +173,7 @@ pub enum VoteThreshold {
|
||||||
/// The type of vote tipping to use on a Proposal.
|
/// The type of vote tipping to use on a Proposal.
|
||||||
///
|
///
|
||||||
/// Vote tipping means that under some conditions voting will complete early.
|
/// Vote tipping means that under some conditions voting will complete early.
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum VoteTipping {
|
pub enum VoteTipping {
|
||||||
/// Tip when there is no way for another option to win and the vote threshold
|
/// Tip when there is no way for another option to win and the vote threshold
|
||||||
/// has been reached. This ignores voters withdrawing their votes.
|
/// has been reached. This ignores voters withdrawing their votes.
|
||||||
|
@ -192,7 +192,7 @@ pub enum VoteTipping {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The status of instruction execution
|
/// The status of instruction execution
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum TransactionExecutionStatus {
|
pub enum TransactionExecutionStatus {
|
||||||
/// Transaction was not executed yet
|
/// Transaction was not executed yet
|
||||||
None,
|
None,
|
||||||
|
@ -205,7 +205,7 @@ pub enum TransactionExecutionStatus {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transaction execution flags defining how instructions are executed for a Proposal
|
/// Transaction execution flags defining how instructions are executed for a Proposal
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum InstructionExecutionFlags {
|
pub enum InstructionExecutionFlags {
|
||||||
/// No execution flags are specified
|
/// No execution flags are specified
|
||||||
/// Instructions can be executed individually, in any order, as soon as they hold_up time expires
|
/// Instructions can be executed individually, in any order, as soon as they hold_up time expires
|
||||||
|
@ -224,7 +224,7 @@ pub enum InstructionExecutionFlags {
|
||||||
|
|
||||||
/// The source of max vote weight used for voting
|
/// The source of max vote weight used for voting
|
||||||
/// Values below 100% mint supply can be used when the governing token is fully minted but not distributed yet
|
/// Values below 100% mint supply can be used when the governing token is fully minted but not distributed yet
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum MintMaxVoteWeightSource {
|
pub enum MintMaxVoteWeightSource {
|
||||||
/// Fraction (10^10 precision) of the governing mint supply is used as max vote weight
|
/// Fraction (10^10 precision) of the governing mint supply is used as max vote weight
|
||||||
/// The default is 100% (10^10) to use all available mint supply for voting
|
/// The default is 100% (10^10) to use all available mint supply for voting
|
||||||
|
|
|
@ -21,7 +21,7 @@ use spl_governance_tools::{
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Governance config
|
/// Governance config
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct GovernanceConfig {
|
pub struct GovernanceConfig {
|
||||||
/// The type of the vote threshold used for community vote
|
/// The type of the vote threshold used for community vote
|
||||||
/// Note: In the current version only YesVotePercentage and Disabled thresholds are supported
|
/// Note: In the current version only YesVotePercentage and Disabled thresholds are supported
|
||||||
|
@ -56,7 +56,7 @@ pub struct GovernanceConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Governance Account
|
/// Governance Account
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct GovernanceV2 {
|
pub struct GovernanceV2 {
|
||||||
/// Account type. It can be Uninitialized, Governance, ProgramGovernance, TokenGovernance or MintGovernance
|
/// Account type. It can be Uninitialized, Governance, ProgramGovernance, TokenGovernance or MintGovernance
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
|
|
@ -18,7 +18,7 @@ use solana_program::{
|
||||||
|
|
||||||
/// Governance Realm Account
|
/// Governance Realm Account
|
||||||
/// Account PDA seeds" ['governance', name]
|
/// Account PDA seeds" ['governance', name]
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct RealmV1 {
|
pub struct RealmV1 {
|
||||||
/// Governance account type
|
/// Governance account type
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
@ -53,7 +53,7 @@ impl IsInitialized for RealmV1 {
|
||||||
|
|
||||||
/// Governance Token Owner Record
|
/// Governance Token Owner Record
|
||||||
/// Account PDA seeds: ['governance', realm, token_mint, token_owner ]
|
/// Account PDA seeds: ['governance', realm, token_mint, token_owner ]
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct TokenOwnerRecordV1 {
|
pub struct TokenOwnerRecordV1 {
|
||||||
/// Governance account type
|
/// Governance account type
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
@ -101,7 +101,7 @@ impl IsInitialized for TokenOwnerRecordV1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Governance Account
|
/// Governance Account
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct GovernanceV1 {
|
pub struct GovernanceV1 {
|
||||||
/// Account type. It can be Uninitialized, Governance, ProgramGovernance, TokenGovernance or MintGovernance
|
/// Account type. It can be Uninitialized, Governance, ProgramGovernance, TokenGovernance or MintGovernance
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
@ -171,7 +171,7 @@ impl IsInitialized for GovernanceV1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Governance Proposal
|
/// Governance Proposal
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct ProposalV1 {
|
pub struct ProposalV1 {
|
||||||
/// Governance account type
|
/// Governance account type
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
@ -260,7 +260,7 @@ impl IsInitialized for ProposalV1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Account PDA seeds: ['governance', proposal, signatory]
|
/// Account PDA seeds: ['governance', proposal, signatory]
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct SignatoryRecordV1 {
|
pub struct SignatoryRecordV1 {
|
||||||
/// Governance account type
|
/// Governance account type
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
@ -282,7 +282,7 @@ impl IsInitialized for SignatoryRecordV1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Proposal instruction V1
|
/// Proposal instruction V1
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct ProposalInstructionV1 {
|
pub struct ProposalInstructionV1 {
|
||||||
/// Governance Account type
|
/// Governance Account type
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
@ -315,7 +315,7 @@ impl IsInitialized for ProposalInstructionV1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Vote with number of votes
|
/// Vote with number of votes
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum VoteWeightV1 {
|
pub enum VoteWeightV1 {
|
||||||
/// Yes vote
|
/// Yes vote
|
||||||
Yes(u64),
|
Yes(u64),
|
||||||
|
@ -325,7 +325,7 @@ pub enum VoteWeightV1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Proposal VoteRecord
|
/// Proposal VoteRecord
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct VoteRecordV1 {
|
pub struct VoteRecordV1 {
|
||||||
/// Governance account type
|
/// Governance account type
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use spl_governance_tools::account::AccountMaxSize;
|
||||||
|
|
||||||
/// Treasury account
|
/// Treasury account
|
||||||
/// The account has no data and can be used as a payer for instruction signed by Governance PDAs or as a native SOL treasury
|
/// The account has no data and can be used as a payer for instruction signed by Governance PDAs or as a native SOL treasury
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct NativeTreasury {}
|
pub struct NativeTreasury {}
|
||||||
|
|
||||||
impl AccountMaxSize for NativeTreasury {
|
impl AccountMaxSize for NativeTreasury {
|
||||||
|
|
|
@ -10,7 +10,7 @@ use spl_governance_tools::account::{get_account_data, AccountMaxSize};
|
||||||
use crate::state::enums::GovernanceAccountType;
|
use crate::state::enums::GovernanceAccountType;
|
||||||
|
|
||||||
/// Program metadata account. It stores information about the particular SPL-Governance program instance
|
/// Program metadata account. It stores information about the particular SPL-Governance program instance
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct ProgramMetadata {
|
pub struct ProgramMetadata {
|
||||||
/// Governance account type
|
/// Governance account type
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
|
|
@ -30,7 +30,6 @@ use crate::{
|
||||||
governance::GovernanceConfig,
|
governance::GovernanceConfig,
|
||||||
proposal_transaction::ProposalTransactionV2,
|
proposal_transaction::ProposalTransactionV2,
|
||||||
realm::RealmV2,
|
realm::RealmV2,
|
||||||
realm_config::get_realm_config_data_for_realm,
|
|
||||||
vote_record::Vote,
|
vote_record::Vote,
|
||||||
vote_record::VoteKind,
|
vote_record::VoteKind,
|
||||||
},
|
},
|
||||||
|
@ -38,8 +37,10 @@ use crate::{
|
||||||
};
|
};
|
||||||
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
|
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
|
||||||
|
|
||||||
|
use crate::state::realm_config::RealmConfigAccount;
|
||||||
|
|
||||||
/// Proposal option vote result
|
/// Proposal option vote result
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum OptionVoteResult {
|
pub enum OptionVoteResult {
|
||||||
/// Vote on the option is not resolved yet
|
/// Vote on the option is not resolved yet
|
||||||
None,
|
None,
|
||||||
|
@ -52,7 +53,7 @@ pub enum OptionVoteResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Proposal Option
|
/// Proposal Option
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct ProposalOption {
|
pub struct ProposalOption {
|
||||||
/// Option label
|
/// Option label
|
||||||
pub label: String,
|
pub label: String,
|
||||||
|
@ -74,7 +75,7 @@ pub struct ProposalOption {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Proposal vote type
|
/// Proposal vote type
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum VoteType {
|
pub enum VoteType {
|
||||||
/// Single choice vote with mutually exclusive choices
|
/// Single choice vote with mutually exclusive choices
|
||||||
/// In the SingeChoice mode there can ever be a single winner
|
/// In the SingeChoice mode there can ever be a single winner
|
||||||
|
@ -103,7 +104,7 @@ pub enum VoteType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Governance Proposal
|
/// Governance Proposal
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct ProposalV2 {
|
pub struct ProposalV2 {
|
||||||
/// Governance account type
|
/// Governance account type
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
@ -472,30 +473,28 @@ impl ProposalV2 {
|
||||||
max_voter_weight.max(total_vote_weight)
|
max_voter_weight.max(total_vote_weight)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolves max voter weight
|
/// Resolves max voter weight using either 1) voting governing_token_mint supply or 2) max voter weight if configured for the token mint
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn resolve_max_voter_weight(
|
pub fn resolve_max_voter_weight(
|
||||||
&mut self,
|
&mut self,
|
||||||
program_id: &Pubkey,
|
|
||||||
realm_config_info: &AccountInfo,
|
|
||||||
vote_governing_token_mint_info: &AccountInfo,
|
|
||||||
account_info_iter: &mut Iter<AccountInfo>,
|
account_info_iter: &mut Iter<AccountInfo>,
|
||||||
realm: &Pubkey,
|
realm: &Pubkey,
|
||||||
realm_data: &RealmV2,
|
realm_data: &RealmV2,
|
||||||
|
realm_config_data: &RealmConfigAccount,
|
||||||
|
vote_governing_token_mint_info: &AccountInfo,
|
||||||
vote_kind: &VoteKind,
|
vote_kind: &VoteKind,
|
||||||
) -> Result<u64, ProgramError> {
|
) -> Result<u64, ProgramError> {
|
||||||
// if the realm uses addin for max community voter weight then use the externally provided max weight
|
// if the Realm is configured to use max voter weight for the given voting governing_token_mint then use the externally provided max_voter_weight
|
||||||
if realm_data.config.use_max_community_voter_weight_addin
|
// instead of the supply based max
|
||||||
&& realm_data.community_mint == *vote_governing_token_mint_info.key
|
if let Some(max_voter_weight_addin) = realm_config_data
|
||||||
|
.get_token_config(realm_data, vote_governing_token_mint_info.key)?
|
||||||
|
.max_voter_weight_addin
|
||||||
{
|
{
|
||||||
let realm_config_data =
|
|
||||||
get_realm_config_data_for_realm(program_id, realm_config_info, realm)?;
|
|
||||||
|
|
||||||
let max_voter_weight_record_info = next_account_info(account_info_iter)?;
|
let max_voter_weight_record_info = next_account_info(account_info_iter)?;
|
||||||
|
|
||||||
let max_voter_weight_record_data =
|
let max_voter_weight_record_data =
|
||||||
get_max_voter_weight_record_data_for_realm_and_governing_token_mint(
|
get_max_voter_weight_record_data_for_realm_and_governing_token_mint(
|
||||||
&realm_config_data.max_community_voter_weight_addin.unwrap(),
|
&max_voter_weight_addin,
|
||||||
max_voter_weight_record_info,
|
max_voter_weight_record_info,
|
||||||
realm,
|
realm,
|
||||||
vote_governing_token_mint_info.key,
|
vote_governing_token_mint_info.key,
|
||||||
|
@ -1166,8 +1165,8 @@ mod test {
|
||||||
config: RealmConfig {
|
config: RealmConfig {
|
||||||
council_mint: Some(Pubkey::new_unique()),
|
council_mint: Some(Pubkey::new_unique()),
|
||||||
reserved: [0; 6],
|
reserved: [0; 6],
|
||||||
use_community_voter_weight_addin: false,
|
legacy1: 0,
|
||||||
use_max_community_voter_weight_addin: false,
|
legacy2: 0,
|
||||||
|
|
||||||
community_mint_max_vote_weight_source:
|
community_mint_max_vote_weight_source:
|
||||||
MintMaxVoteWeightSource::FULL_SUPPLY_FRACTION,
|
MintMaxVoteWeightSource::FULL_SUPPLY_FRACTION,
|
||||||
|
|
|
@ -25,7 +25,7 @@ use solana_program::{
|
||||||
use spl_governance_tools::account::{get_account_data, AccountMaxSize};
|
use spl_governance_tools::account::{get_account_data, AccountMaxSize};
|
||||||
|
|
||||||
/// InstructionData wrapper. It can be removed once Borsh serialization for Instruction is supported in the SDK
|
/// InstructionData wrapper. It can be removed once Borsh serialization for Instruction is supported in the SDK
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct InstructionData {
|
pub struct InstructionData {
|
||||||
/// Pubkey of the instruction processor that executes this instruction
|
/// Pubkey of the instruction processor that executes this instruction
|
||||||
pub program_id: Pubkey,
|
pub program_id: Pubkey,
|
||||||
|
@ -36,7 +36,7 @@ pub struct InstructionData {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Account metadata used to define Instructions
|
/// Account metadata used to define Instructions
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct AccountMetaData {
|
pub struct AccountMetaData {
|
||||||
/// An account's public key
|
/// An account's public key
|
||||||
pub pubkey: Pubkey,
|
pub pubkey: Pubkey,
|
||||||
|
@ -83,7 +83,7 @@ impl From<&InstructionData> for Instruction {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Account for an instruction to be executed for Proposal
|
/// Account for an instruction to be executed for Proposal
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct ProposalTransactionV2 {
|
pub struct ProposalTransactionV2 {
|
||||||
/// Governance Account type
|
/// Governance Account type
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
|
|
@ -21,14 +21,17 @@ use crate::{
|
||||||
state::{
|
state::{
|
||||||
enums::{GovernanceAccountType, MintMaxVoteWeightSource},
|
enums::{GovernanceAccountType, MintMaxVoteWeightSource},
|
||||||
legacy::RealmV1,
|
legacy::RealmV1,
|
||||||
|
realm_config::GoverningTokenType,
|
||||||
token_owner_record::get_token_owner_record_data_for_realm,
|
token_owner_record::get_token_owner_record_data_for_realm,
|
||||||
vote_record::VoteKind,
|
vote_record::VoteKind,
|
||||||
},
|
},
|
||||||
PROGRAM_AUTHORITY_SEED,
|
PROGRAM_AUTHORITY_SEED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::state::realm_config::get_realm_config_data_for_realm;
|
||||||
|
|
||||||
/// Realm Config instruction args
|
/// Realm Config instruction args
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct RealmConfigArgs {
|
pub struct RealmConfigArgs {
|
||||||
/// Indicates whether council_mint should be used
|
/// Indicates whether council_mint should be used
|
||||||
/// If yes then council_mint account must also be passed to the instruction
|
/// If yes then council_mint account must also be passed to the instruction
|
||||||
|
@ -40,17 +43,45 @@ pub struct RealmConfigArgs {
|
||||||
/// The source used for community mint max vote weight source
|
/// The source used for community mint max vote weight source
|
||||||
pub community_mint_max_vote_weight_source: MintMaxVoteWeightSource,
|
pub community_mint_max_vote_weight_source: MintMaxVoteWeightSource,
|
||||||
|
|
||||||
/// Indicates whether an external addin program should be used to provide community voters weights
|
/// Community token config args
|
||||||
/// If yes then the voters weight program account must be passed to the instruction
|
pub community_token_config_args: GoverningTokenConfigArgs,
|
||||||
pub use_community_voter_weight_addin: bool,
|
|
||||||
|
|
||||||
/// Indicates whether an external addin program should be used to provide max voters weight for the community mint
|
/// Council token config args
|
||||||
|
pub council_token_config_args: GoverningTokenConfigArgs,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Realm Config instruction args
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema, Default)]
|
||||||
|
pub struct GoverningTokenConfigArgs {
|
||||||
|
/// Indicates whether an external addin program should be used to provide voters weights
|
||||||
|
/// If yes then the voters weight program account must be passed to the instruction
|
||||||
|
pub use_voter_weight_addin: bool,
|
||||||
|
|
||||||
|
/// Indicates whether an external addin program should be used to provide max voters weight for the token
|
||||||
/// If yes then the max voter weight program account must be passed to the instruction
|
/// If yes then the max voter weight program account must be passed to the instruction
|
||||||
pub use_max_community_voter_weight_addin: bool,
|
pub use_max_voter_weight_addin: bool,
|
||||||
|
|
||||||
|
/// Governing token type defines how the token is used for governance
|
||||||
|
pub token_type: GoverningTokenType,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Realm Config instruction args with account parametres
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema, Default)]
|
||||||
|
pub struct GoverningTokenConfigAccountArgs {
|
||||||
|
/// Specifies an external plugin program which should be used to provide voters weights
|
||||||
|
/// for the given goventing token
|
||||||
|
pub voter_weight_addin: Option<Pubkey>,
|
||||||
|
|
||||||
|
/// Specifies an external an external plugin program should be used to provide max voters weight
|
||||||
|
/// for the given goventing token
|
||||||
|
pub max_voter_weight_addin: Option<Pubkey>,
|
||||||
|
|
||||||
|
/// Governing token type defines how the token is used for governance power
|
||||||
|
pub token_type: GoverningTokenType,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SetRealmAuthority instruction action
|
/// SetRealmAuthority instruction action
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum SetRealmAuthorityAction {
|
pub enum SetRealmAuthorityAction {
|
||||||
/// Sets realm authority without any checks
|
/// Sets realm authority without any checks
|
||||||
/// Uncheck option allows to set the realm authority to non governance accounts
|
/// Uncheck option allows to set the realm authority to non governance accounts
|
||||||
|
@ -66,13 +97,17 @@ pub enum SetRealmAuthorityAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Realm Config defining Realm parameters.
|
/// Realm Config defining Realm parameters.
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct RealmConfig {
|
pub struct RealmConfig {
|
||||||
/// Indicates whether an external addin program should be used to provide voters weights for the community mint
|
/// Legacy field introdcued and used in V2 as use_community_voter_weight_addin: bool
|
||||||
pub use_community_voter_weight_addin: bool,
|
/// If the field is going to be reused in future version it must be taken under consideration
|
||||||
|
/// that for some Realms it might be already set to 1
|
||||||
|
pub legacy1: u8,
|
||||||
|
|
||||||
/// Indicates whether an external addin program should be used to provide max voter weight for the community mint
|
/// Legacy field introdcued and used in V2 as use_max_community_voter_weight_addin: bool
|
||||||
pub use_max_community_voter_weight_addin: bool,
|
/// If the field is going to be reused in future version it must be taken under consideration
|
||||||
|
/// that for some Realms it might be already set to 1
|
||||||
|
pub legacy2: u8,
|
||||||
|
|
||||||
/// Reserved space for future versions
|
/// Reserved space for future versions
|
||||||
pub reserved: [u8; 6],
|
pub reserved: [u8; 6],
|
||||||
|
@ -89,7 +124,7 @@ pub struct RealmConfig {
|
||||||
|
|
||||||
/// Governance Realm Account
|
/// Governance Realm Account
|
||||||
/// Account PDA seeds" ['governance', name]
|
/// Account PDA seeds" ['governance', name]
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct RealmV2 {
|
pub struct RealmV2 {
|
||||||
/// Governance account type
|
/// Governance account type
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
@ -251,13 +286,13 @@ impl RealmV2 {
|
||||||
token_owner_record_data.assert_token_owner_or_delegate_is_signer(create_authority_info)?;
|
token_owner_record_data.assert_token_owner_or_delegate_is_signer(create_authority_info)?;
|
||||||
|
|
||||||
let realm_config_info = next_account_info(account_info_iter)?;
|
let realm_config_info = next_account_info(account_info_iter)?;
|
||||||
|
let realm_config_data =
|
||||||
|
get_realm_config_data_for_realm(program_id, realm_config_info, realm)?;
|
||||||
|
|
||||||
let voter_weight = token_owner_record_data.resolve_voter_weight(
|
let voter_weight = token_owner_record_data.resolve_voter_weight(
|
||||||
program_id,
|
|
||||||
realm_config_info,
|
|
||||||
account_info_iter,
|
account_info_iter,
|
||||||
realm,
|
|
||||||
self,
|
self,
|
||||||
|
&realm_config_data,
|
||||||
VoterWeightAction::CreateGovernance,
|
VoterWeightAction::CreateGovernance,
|
||||||
realm,
|
realm,
|
||||||
)?;
|
)?;
|
||||||
|
@ -399,8 +434,10 @@ pub fn get_governing_token_holding_address(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Asserts given realm config args are correct
|
/// Asserts given realm config args are correct
|
||||||
pub fn assert_valid_realm_config_args(config_args: &RealmConfigArgs) -> Result<(), ProgramError> {
|
pub fn assert_valid_realm_config_args(
|
||||||
match config_args.community_mint_max_vote_weight_source {
|
realm_config_args: &RealmConfigArgs,
|
||||||
|
) -> Result<(), ProgramError> {
|
||||||
|
match realm_config_args.community_mint_max_vote_weight_source {
|
||||||
MintMaxVoteWeightSource::SupplyFraction(fraction) => {
|
MintMaxVoteWeightSource::SupplyFraction(fraction) => {
|
||||||
if !(1..=MintMaxVoteWeightSource::SUPPLY_FRACTION_BASE).contains(&fraction) {
|
if !(1..=MintMaxVoteWeightSource::SUPPLY_FRACTION_BASE).contains(&fraction) {
|
||||||
return Err(GovernanceError::InvalidMaxVoteWeightSupplyFraction.into());
|
return Err(GovernanceError::InvalidMaxVoteWeightSupplyFraction.into());
|
||||||
|
@ -433,8 +470,8 @@ mod test {
|
||||||
name: "test-realm".to_string(),
|
name: "test-realm".to_string(),
|
||||||
config: RealmConfig {
|
config: RealmConfig {
|
||||||
council_mint: Some(Pubkey::new_unique()),
|
council_mint: Some(Pubkey::new_unique()),
|
||||||
use_community_voter_weight_addin: false,
|
legacy1: 0,
|
||||||
use_max_community_voter_weight_addin: false,
|
legacy2: 0,
|
||||||
reserved: [0; 6],
|
reserved: [0; 6],
|
||||||
community_mint_max_vote_weight_source: MintMaxVoteWeightSource::Absolute(100),
|
community_mint_max_vote_weight_source: MintMaxVoteWeightSource::Absolute(100),
|
||||||
min_community_weight_to_create_governance: 10,
|
min_community_weight_to_create_governance: 10,
|
||||||
|
@ -450,7 +487,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Realm Config instruction args
|
/// Realm Config instruction args
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct RealmConfigArgsV1 {
|
pub struct RealmConfigArgsV1 {
|
||||||
/// Indicates whether council_mint should be used
|
/// Indicates whether council_mint should be used
|
||||||
/// If yes then council_mint account must also be passed to the instruction
|
/// If yes then council_mint account must also be passed to the instruction
|
||||||
|
@ -464,7 +501,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instructions supported by the Governance program
|
/// Instructions supported by the Governance program
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum GovernanceInstructionV1 {
|
pub enum GovernanceInstructionV1 {
|
||||||
/// Creates Governance Realm account which aggregates governances for given Community Mint and optional Council Mint
|
/// Creates Governance Realm account which aggregates governances for given Community Mint and optional Council Mint
|
||||||
CreateRealm {
|
CreateRealm {
|
||||||
|
@ -495,8 +532,8 @@ mod test {
|
||||||
min_community_weight_to_create_governance: 100,
|
min_community_weight_to_create_governance: 100,
|
||||||
community_mint_max_vote_weight_source:
|
community_mint_max_vote_weight_source:
|
||||||
MintMaxVoteWeightSource::FULL_SUPPLY_FRACTION,
|
MintMaxVoteWeightSource::FULL_SUPPLY_FRACTION,
|
||||||
use_community_voter_weight_addin: false,
|
community_token_config_args: GoverningTokenConfigArgs::default(),
|
||||||
use_max_community_voter_weight_addin: false,
|
council_token_config_args: GoverningTokenConfigArgs::default(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
//! RealmConfig account
|
//! RealmConfig account
|
||||||
|
use std::slice::Iter;
|
||||||
|
|
||||||
|
use solana_program::account_info::next_account_info;
|
||||||
|
|
||||||
use solana_program::{
|
use solana_program::{
|
||||||
account_info::AccountInfo, program_error::ProgramError, program_pack::IsInitialized,
|
account_info::AccountInfo, program_error::ProgramError, program_pack::IsInitialized,
|
||||||
|
@ -10,9 +13,90 @@ use spl_governance_tools::account::{get_account_data, AccountMaxSize};
|
||||||
|
|
||||||
use crate::{error::GovernanceError, state::enums::GovernanceAccountType};
|
use crate::{error::GovernanceError, state::enums::GovernanceAccountType};
|
||||||
|
|
||||||
|
use crate::state::realm::GoverningTokenConfigArgs;
|
||||||
|
|
||||||
|
use crate::state::realm::{RealmConfigArgs, RealmV2};
|
||||||
|
|
||||||
|
/// The type of the governing token defines:
|
||||||
|
/// 1) Who retains the authority over deposited tokens
|
||||||
|
/// 2) Which token instructions Deposit, Withdraw and Revoke (burn) are allowed
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
|
pub enum GoverningTokenType {
|
||||||
|
/// Liquid token is a token which is fully liquid and the token owner retains full authority over it
|
||||||
|
/// Deposit - Yes
|
||||||
|
/// Withdraw - Yes
|
||||||
|
/// Revoke - No, Realm authority cannot revoke liquid tokens
|
||||||
|
Liquid,
|
||||||
|
|
||||||
|
/// Membership token is a token controlled by Realm authority
|
||||||
|
/// Deposit - Yes, membership tokens can be deposited to gain governance power
|
||||||
|
/// The membership tokens are conventionally minted into the holding account to keep them out of members possesion
|
||||||
|
/// Withdraw - No, after membership tokens are deposited they are no longer transferable and can't be withdrawn
|
||||||
|
/// Revoke - Yes, Realm authority can Revoke (burn) membership tokens
|
||||||
|
Membership,
|
||||||
|
|
||||||
|
/// Dormant token is a token which is only a placeholder and its deposits are not accepted and not used for governance power within the Realm
|
||||||
|
///
|
||||||
|
/// The Dormant token type is used when only a single voting population is operational. For example a Multisig starter DAO uses Council only
|
||||||
|
/// and sets Community as Dormant to indicate its not utilised for any governance power.
|
||||||
|
/// Once the starter DAO decides to decentralise then it can change the Community token to Liquid
|
||||||
|
///
|
||||||
|
/// Note: When an external voter weight plugin which takes deposits of the token is used then the type should be set to Dormant
|
||||||
|
/// to make the intention explicit
|
||||||
|
///
|
||||||
|
/// Deposit - No, dormant tokens can't be deposited into the Realm
|
||||||
|
/// Withdraw - Yes, tokens can still be withdrawn from Realm to support scenario where the config is changed while some tokens are still deposited
|
||||||
|
/// Revoke - No, Realm authority cannot revoke dormant tokens
|
||||||
|
Dormant,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derivable_impls)]
|
||||||
|
impl Default for GoverningTokenType {
|
||||||
|
fn default() -> Self {
|
||||||
|
GoverningTokenType::Liquid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// GoverningTokenConfig specifies configuration for Realm governing token (Community or Council)
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema, Default)]
|
||||||
|
pub struct GoverningTokenConfig {
|
||||||
|
/// Plugin providing voter weights for the governing token
|
||||||
|
pub voter_weight_addin: Option<Pubkey>,
|
||||||
|
|
||||||
|
/// Plugin providing max voter weight for the governing token
|
||||||
|
pub max_voter_weight_addin: Option<Pubkey>,
|
||||||
|
|
||||||
|
/// Governing token type
|
||||||
|
pub token_type: GoverningTokenType,
|
||||||
|
|
||||||
|
/// Reserved space for future versions
|
||||||
|
pub reserved: [u8; 8],
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reserved 110 bytes
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
|
pub struct Reserved110 {
|
||||||
|
/// Reserved 64 bytes
|
||||||
|
pub reserved64: [u8; 64],
|
||||||
|
/// Reserved 32 bytes
|
||||||
|
pub reserved32: [u8; 32],
|
||||||
|
/// Reserved 4 bytes
|
||||||
|
pub reserved14: [u8; 14],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Reserved110 {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
reserved64: [0; 64],
|
||||||
|
reserved32: [0; 32],
|
||||||
|
reserved14: [0; 14],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// RealmConfig account
|
/// RealmConfig account
|
||||||
/// The account is an optional extension to RealmConfig stored on Realm account
|
/// The account is an optional extension to RealmConfig stored on Realm account
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct RealmConfigAccount {
|
pub struct RealmConfigAccount {
|
||||||
/// Governance account type
|
/// Governance account type
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
@ -20,23 +104,14 @@ pub struct RealmConfigAccount {
|
||||||
/// The realm the config belong to
|
/// The realm the config belong to
|
||||||
pub realm: Pubkey,
|
pub realm: Pubkey,
|
||||||
|
|
||||||
/// Addin providing voter weights for community token
|
/// Community token config
|
||||||
pub community_voter_weight_addin: Option<Pubkey>,
|
pub community_token_config: GoverningTokenConfig,
|
||||||
|
|
||||||
/// Addin providing max vote weight for community token
|
/// Council token config
|
||||||
/// Note: This field is not implemented in the current version
|
pub council_token_config: GoverningTokenConfig,
|
||||||
pub max_community_voter_weight_addin: Option<Pubkey>,
|
|
||||||
|
|
||||||
/// Addin providing voter weights for council token
|
|
||||||
/// Note: This field is not implemented in the current version
|
|
||||||
pub council_voter_weight_addin: Option<Pubkey>,
|
|
||||||
|
|
||||||
/// Addin providing max vote weight for council token
|
|
||||||
/// Note: This field is not implemented in the current version
|
|
||||||
pub council_max_vote_weight_addin: Option<Pubkey>,
|
|
||||||
|
|
||||||
/// Reserved
|
/// Reserved
|
||||||
pub reserved: [u8; 128],
|
pub reserved: Reserved110,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccountMaxSize for RealmConfigAccount {
|
impl AccountMaxSize for RealmConfigAccount {
|
||||||
|
@ -51,6 +126,98 @@ impl IsInitialized for RealmConfigAccount {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RealmConfigAccount {
|
||||||
|
/// Returns GoverningTokenConfig for the given governing_token_mint
|
||||||
|
pub fn get_token_config(
|
||||||
|
&self,
|
||||||
|
realm_data: &RealmV2,
|
||||||
|
governing_token_mint: &Pubkey,
|
||||||
|
) -> Result<&GoverningTokenConfig, ProgramError> {
|
||||||
|
let token_config = if *governing_token_mint == realm_data.community_mint {
|
||||||
|
&self.community_token_config
|
||||||
|
} else if Some(*governing_token_mint) == realm_data.config.council_mint {
|
||||||
|
&self.council_token_config
|
||||||
|
} else {
|
||||||
|
return Err(GovernanceError::InvalidGoverningTokenMint.into());
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(token_config)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assertes the given governing token can be revoked
|
||||||
|
pub fn assert_can_revoke_governing_token(
|
||||||
|
&self,
|
||||||
|
realm_data: &RealmV2,
|
||||||
|
governing_token_mint: &Pubkey,
|
||||||
|
) -> Result<(), ProgramError> {
|
||||||
|
let governing_token_type = &self
|
||||||
|
.get_token_config(realm_data, governing_token_mint)?
|
||||||
|
.token_type;
|
||||||
|
|
||||||
|
match governing_token_type {
|
||||||
|
GoverningTokenType::Membership => Ok(()),
|
||||||
|
GoverningTokenType::Liquid | GoverningTokenType::Dormant => {
|
||||||
|
Err(GovernanceError::CannotRevokeGoverningTokens.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assertes the given governing token can be deposited
|
||||||
|
pub fn assert_can_deposit_governing_token(
|
||||||
|
&self,
|
||||||
|
realm_data: &RealmV2,
|
||||||
|
governing_token_mint: &Pubkey,
|
||||||
|
) -> Result<(), ProgramError> {
|
||||||
|
let governing_token_type = &self
|
||||||
|
.get_token_config(realm_data, governing_token_mint)?
|
||||||
|
.token_type;
|
||||||
|
|
||||||
|
match governing_token_type {
|
||||||
|
GoverningTokenType::Membership | GoverningTokenType::Liquid => Ok(()),
|
||||||
|
// Note: Preventing deposits of the Dormant type tokens is not a direct security concern
|
||||||
|
// It only makes the intention of not using deposited tokens as governnace power stronger
|
||||||
|
GoverningTokenType::Dormant => Err(GovernanceError::CannotDepositDormantTokens.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assertes the given governing token can be withdrawn
|
||||||
|
pub fn assert_can_withdraw_governing_token(
|
||||||
|
&self,
|
||||||
|
realm_data: &RealmV2,
|
||||||
|
governing_token_mint: &Pubkey,
|
||||||
|
) -> Result<(), ProgramError> {
|
||||||
|
let governing_token_type = &self
|
||||||
|
.get_token_config(realm_data, governing_token_mint)?
|
||||||
|
.token_type;
|
||||||
|
|
||||||
|
match governing_token_type {
|
||||||
|
GoverningTokenType::Dormant | GoverningTokenType::Liquid => Ok(()),
|
||||||
|
GoverningTokenType::Membership => {
|
||||||
|
Err(GovernanceError::CannotWithdrawMembershipTokens.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Asserts the given RealmConfigArgs represent a valid Realm configuraiton change
|
||||||
|
pub fn assert_can_change_config(
|
||||||
|
&self,
|
||||||
|
realm_config_args: &RealmConfigArgs,
|
||||||
|
) -> Result<(), ProgramError> {
|
||||||
|
// Existing community token type can't be changed to Membership because it would
|
||||||
|
// give the Realm authority the right to burn members tokens which should not be the case because the tokens belong to the members
|
||||||
|
// On the other had for the Council token it's acceptable and in fact desired change becuase council tokens denote memebership
|
||||||
|
// which should be controled by the Realm
|
||||||
|
if self.community_token_config.token_type != GoverningTokenType::Membership
|
||||||
|
&& realm_config_args.community_token_config_args.token_type
|
||||||
|
== GoverningTokenType::Membership
|
||||||
|
{
|
||||||
|
return Err(GovernanceError::CannotChangeCommunityTokenTypeToMemebership.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Deserializes RealmConfig account and checks owner program
|
/// Deserializes RealmConfig account and checks owner program
|
||||||
pub fn get_realm_config_data(
|
pub fn get_realm_config_data(
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
|
@ -59,18 +226,40 @@ pub fn get_realm_config_data(
|
||||||
get_account_data::<RealmConfigAccount>(program_id, realm_config_info)
|
get_account_data::<RealmConfigAccount>(program_id, realm_config_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserializes RealmConfig account and checks the owner program and the Realm it belongs to
|
/// If the account exists then desrialises it into RealmConfigAccount struct and checks the owner program and the Realm it belongs to
|
||||||
|
/// If the accoutn doesn't exist then it checks its address is derived from the given owner program and Realm and returns default RealmConfigAccount
|
||||||
pub fn get_realm_config_data_for_realm(
|
pub fn get_realm_config_data_for_realm(
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
realm_config_info: &AccountInfo,
|
realm_config_info: &AccountInfo,
|
||||||
realm: &Pubkey,
|
realm: &Pubkey,
|
||||||
) -> Result<RealmConfigAccount, ProgramError> {
|
) -> Result<RealmConfigAccount, ProgramError> {
|
||||||
|
let realm_config_data = if realm_config_info.data_is_empty() {
|
||||||
|
// If RealmConfigAccount doesn't exist yet then validate its PDA
|
||||||
|
// PDA validation is required because RealmConfigAccount might not exist for legacy Realms
|
||||||
|
// and then its absense is used as default RealmConfigAccount value with no plugins and Liquid governance tokens
|
||||||
|
let realm_config_address = get_realm_config_address(program_id, realm);
|
||||||
|
|
||||||
|
if realm_config_address != *realm_config_info.key {
|
||||||
|
return Err(GovernanceError::InvalidRealmConfigAddress.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
RealmConfigAccount {
|
||||||
|
account_type: GovernanceAccountType::RealmConfig,
|
||||||
|
realm: *realm,
|
||||||
|
community_token_config: GoverningTokenConfig::default(),
|
||||||
|
council_token_config: GoverningTokenConfig::default(),
|
||||||
|
reserved: Reserved110::default(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
let realm_config_data = get_realm_config_data(program_id, realm_config_info)?;
|
let realm_config_data = get_realm_config_data(program_id, realm_config_info)?;
|
||||||
|
|
||||||
if realm_config_data.realm != *realm {
|
if realm_config_data.realm != *realm {
|
||||||
return Err(GovernanceError::InvalidRealmConfigForRealm.into());
|
return Err(GovernanceError::InvalidRealmConfigForRealm.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
realm_config_data
|
||||||
|
};
|
||||||
|
|
||||||
Ok(realm_config_data)
|
Ok(realm_config_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +272,32 @@ pub fn get_realm_config_address_seeds(realm: &Pubkey) -> [&[u8]; 2] {
|
||||||
pub fn get_realm_config_address(program_id: &Pubkey, realm: &Pubkey) -> Pubkey {
|
pub fn get_realm_config_address(program_id: &Pubkey, realm: &Pubkey) -> Pubkey {
|
||||||
Pubkey::find_program_address(&get_realm_config_address_seeds(realm), program_id).0
|
Pubkey::find_program_address(&get_realm_config_address_seeds(realm), program_id).0
|
||||||
}
|
}
|
||||||
|
/// Resolves GoverningTokenConfig from GoverningTokenConfigArgs and instruction accounts
|
||||||
|
pub fn resolve_governing_token_config(
|
||||||
|
account_info_iter: &mut Iter<AccountInfo>,
|
||||||
|
governing_token_config_args: &GoverningTokenConfigArgs,
|
||||||
|
) -> Result<GoverningTokenConfig, ProgramError> {
|
||||||
|
let voter_weight_addin = if governing_token_config_args.use_voter_weight_addin {
|
||||||
|
let voter_weight_addin_info = next_account_info(account_info_iter)?;
|
||||||
|
Some(*voter_weight_addin_info.key)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let max_voter_weight_addin = if governing_token_config_args.use_max_voter_weight_addin {
|
||||||
|
let max_voter_weight_addin_info = next_account_info(account_info_iter)?;
|
||||||
|
Some(*max_voter_weight_addin_info.key)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(GoverningTokenConfig {
|
||||||
|
voter_weight_addin,
|
||||||
|
max_voter_weight_addin,
|
||||||
|
token_type: governing_token_config_args.token_type.clone(),
|
||||||
|
reserved: [0; 8],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
@ -94,11 +309,19 @@ mod test {
|
||||||
let realm_config = RealmConfigAccount {
|
let realm_config = RealmConfigAccount {
|
||||||
account_type: GovernanceAccountType::RealmV2,
|
account_type: GovernanceAccountType::RealmV2,
|
||||||
realm: Pubkey::new_unique(),
|
realm: Pubkey::new_unique(),
|
||||||
community_voter_weight_addin: Some(Pubkey::new_unique()),
|
community_token_config: GoverningTokenConfig {
|
||||||
max_community_voter_weight_addin: Some(Pubkey::new_unique()),
|
voter_weight_addin: Some(Pubkey::new_unique()),
|
||||||
council_voter_weight_addin: Some(Pubkey::new_unique()),
|
max_voter_weight_addin: Some(Pubkey::new_unique()),
|
||||||
council_max_vote_weight_addin: Some(Pubkey::new_unique()),
|
token_type: GoverningTokenType::Liquid,
|
||||||
reserved: [0; 128],
|
reserved: [0; 8],
|
||||||
|
},
|
||||||
|
council_token_config: GoverningTokenConfig {
|
||||||
|
voter_weight_addin: Some(Pubkey::new_unique()),
|
||||||
|
max_voter_weight_addin: Some(Pubkey::new_unique()),
|
||||||
|
token_type: GoverningTokenType::Liquid,
|
||||||
|
reserved: [0; 8],
|
||||||
|
},
|
||||||
|
reserved: Reserved110::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let size = realm_config.try_to_vec().unwrap().len();
|
let size = realm_config.try_to_vec().unwrap().len();
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::{error::GovernanceError, PROGRAM_AUTHORITY_SEED};
|
||||||
use crate::state::{enums::GovernanceAccountType, legacy::SignatoryRecordV1};
|
use crate::state::{enums::GovernanceAccountType, legacy::SignatoryRecordV1};
|
||||||
|
|
||||||
/// Account PDA seeds: ['governance', proposal, signatory]
|
/// Account PDA seeds: ['governance', proposal, signatory]
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct SignatoryRecordV2 {
|
pub struct SignatoryRecordV2 {
|
||||||
/// Governance account type
|
/// Governance account type
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
||||||
error::GovernanceError,
|
error::GovernanceError,
|
||||||
state::{
|
state::{
|
||||||
enums::GovernanceAccountType, governance::GovernanceConfig, legacy::TokenOwnerRecordV1,
|
enums::GovernanceAccountType, governance::GovernanceConfig, legacy::TokenOwnerRecordV1,
|
||||||
realm::RealmV2, realm_config::get_realm_config_data_for_realm,
|
realm::RealmV2,
|
||||||
},
|
},
|
||||||
PROGRAM_AUTHORITY_SEED,
|
PROGRAM_AUTHORITY_SEED,
|
||||||
};
|
};
|
||||||
|
@ -26,9 +26,11 @@ use solana_program::{
|
||||||
use spl_governance_addin_api::voter_weight::VoterWeightAction;
|
use spl_governance_addin_api::voter_weight::VoterWeightAction;
|
||||||
use spl_governance_tools::account::{get_account_data, AccountMaxSize};
|
use spl_governance_tools::account::{get_account_data, AccountMaxSize};
|
||||||
|
|
||||||
|
use crate::state::realm_config::RealmConfigAccount;
|
||||||
|
|
||||||
/// Governance Token Owner Record
|
/// Governance Token Owner Record
|
||||||
/// Account PDA seeds: ['governance', realm, token_mint, token_owner ]
|
/// Account PDA seeds: ['governance', realm, token_mint, token_owner ]
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct TokenOwnerRecordV2 {
|
pub struct TokenOwnerRecordV2 {
|
||||||
/// Governance account type
|
/// Governance account type
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
@ -189,25 +191,22 @@ impl TokenOwnerRecordV2 {
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn resolve_voter_weight(
|
pub fn resolve_voter_weight(
|
||||||
&self,
|
&self,
|
||||||
program_id: &Pubkey,
|
|
||||||
realm_config_info: &AccountInfo,
|
|
||||||
account_info_iter: &mut Iter<AccountInfo>,
|
account_info_iter: &mut Iter<AccountInfo>,
|
||||||
realm: &Pubkey,
|
|
||||||
realm_data: &RealmV2,
|
realm_data: &RealmV2,
|
||||||
|
realm_config_data: &RealmConfigAccount,
|
||||||
weight_action: VoterWeightAction,
|
weight_action: VoterWeightAction,
|
||||||
weight_action_target: &Pubkey,
|
weight_action_target: &Pubkey,
|
||||||
) -> Result<u64, ProgramError> {
|
) -> Result<u64, ProgramError> {
|
||||||
// if the realm uses addin for community voter weight then use the externally provided weight
|
// if the Realm is configured to use voter weight plugin for our governing_token_mint then use the externally provided voter_weight
|
||||||
if realm_data.config.use_community_voter_weight_addin
|
// instead of governing_token_deposit_amount
|
||||||
&& realm_data.community_mint == self.governing_token_mint
|
if let Some(voter_weight_addin) = realm_config_data
|
||||||
|
.get_token_config(realm_data, &self.governing_token_mint)?
|
||||||
|
.voter_weight_addin
|
||||||
{
|
{
|
||||||
let voter_weight_record_info = next_account_info(account_info_iter)?;
|
let voter_weight_record_info = next_account_info(account_info_iter)?;
|
||||||
|
|
||||||
let realm_config_data =
|
|
||||||
get_realm_config_data_for_realm(program_id, realm_config_info, realm)?;
|
|
||||||
|
|
||||||
let voter_weight_record_data = get_voter_weight_record_data_for_token_owner_record(
|
let voter_weight_record_data = get_voter_weight_record_data_for_token_owner_record(
|
||||||
&realm_config_data.community_voter_weight_addin.unwrap(),
|
&voter_weight_addin,
|
||||||
voter_weight_record_info,
|
voter_weight_record_info,
|
||||||
self,
|
self,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -25,10 +25,10 @@ use crate::state::{
|
||||||
/// Voter choice for a proposal option
|
/// Voter choice for a proposal option
|
||||||
/// In the current version only 1) Single choice and 2) Multiple choices proposals are supported
|
/// In the current version only 1) Single choice and 2) Multiple choices proposals are supported
|
||||||
/// In the future versions we can add support for 1) Quadratic voting, 2) Ranked choice voting and 3) Weighted voting
|
/// In the future versions we can add support for 1) Quadratic voting, 2) Ranked choice voting and 3) Weighted voting
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct VoteChoice {
|
pub struct VoteChoice {
|
||||||
/// The rank given to the choice by voter
|
/// The rank given to the choice by voter
|
||||||
/// Note: The filed is not used in the current version
|
/// Note: The field is not used in the current version
|
||||||
pub rank: u8,
|
pub rank: u8,
|
||||||
|
|
||||||
/// The voter's weight percentage given by the voter to the choice
|
/// The voter's weight percentage given by the voter to the choice
|
||||||
|
@ -47,7 +47,7 @@ impl VoteChoice {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// User's vote
|
/// User's vote
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum Vote {
|
pub enum Vote {
|
||||||
/// Vote approving choices
|
/// Vote approving choices
|
||||||
Approve(Vec<VoteChoice>),
|
Approve(Vec<VoteChoice>),
|
||||||
|
@ -64,7 +64,7 @@ pub enum Vote {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// VoteKind defines the type of the vote being cast
|
/// VoteKind defines the type of the vote being cast
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub enum VoteKind {
|
pub enum VoteKind {
|
||||||
/// Electorate vote is cast by the voting population identified by governing_token_mint
|
/// Electorate vote is cast by the voting population identified by governing_token_mint
|
||||||
/// Approve, Deny and Abstain votes are Electorate votes
|
/// Approve, Deny and Abstain votes are Electorate votes
|
||||||
|
@ -83,7 +83,7 @@ pub fn get_vote_kind(vote: &Vote) -> VoteKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Proposal VoteRecord
|
/// Proposal VoteRecord
|
||||||
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
|
||||||
pub struct VoteRecordV2 {
|
pub struct VoteRecordV2 {
|
||||||
/// Governance account type
|
/// Governance account type
|
||||||
pub account_type: GovernanceAccountType,
|
pub account_type: GovernanceAccountType,
|
||||||
|
|
|
@ -121,6 +121,37 @@ pub fn transfer_spl_tokens<'a>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mint SPL Tokens
|
||||||
|
pub fn mint_spl_tokens_to<'a>(
|
||||||
|
mint_info: &AccountInfo<'a>,
|
||||||
|
destination_info: &AccountInfo<'a>,
|
||||||
|
mint_authority_info: &AccountInfo<'a>,
|
||||||
|
amount: u64,
|
||||||
|
spl_token_info: &AccountInfo<'a>,
|
||||||
|
) -> ProgramResult {
|
||||||
|
let mint_to_ix = spl_token::instruction::mint_to(
|
||||||
|
&spl_token::id(),
|
||||||
|
mint_info.key,
|
||||||
|
destination_info.key,
|
||||||
|
mint_authority_info.key,
|
||||||
|
&[],
|
||||||
|
amount,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
invoke(
|
||||||
|
&mint_to_ix,
|
||||||
|
&[
|
||||||
|
spl_token_info.clone(),
|
||||||
|
mint_authority_info.clone(),
|
||||||
|
mint_info.clone(),
|
||||||
|
destination_info.clone(),
|
||||||
|
],
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Transfers SPL Tokens from a token account owned by the provided PDA authority with seeds
|
/// Transfers SPL Tokens from a token account owned by the provided PDA authority with seeds
|
||||||
pub fn transfer_spl_tokens_signed<'a>(
|
pub fn transfer_spl_tokens_signed<'a>(
|
||||||
source_info: &AccountInfo<'a>,
|
source_info: &AccountInfo<'a>,
|
||||||
|
@ -170,6 +201,55 @@ pub fn transfer_spl_tokens_signed<'a>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Burns SPL Tokens from a token account owned by the provided PDA authority with seeds
|
||||||
|
pub fn burn_spl_tokens_signed<'a>(
|
||||||
|
token_account_info: &AccountInfo<'a>,
|
||||||
|
token_mint_info: &AccountInfo<'a>,
|
||||||
|
authority_info: &AccountInfo<'a>,
|
||||||
|
authority_seeds: &[&[u8]],
|
||||||
|
program_id: &Pubkey,
|
||||||
|
amount: u64,
|
||||||
|
spl_token_info: &AccountInfo<'a>,
|
||||||
|
) -> ProgramResult {
|
||||||
|
let (authority_address, bump_seed) = Pubkey::find_program_address(authority_seeds, program_id);
|
||||||
|
|
||||||
|
if authority_address != *authority_info.key {
|
||||||
|
msg!(
|
||||||
|
"Burn SPL Token with Authority PDA: {:?} was requested while PDA: {:?} was expected",
|
||||||
|
authority_info.key,
|
||||||
|
authority_address
|
||||||
|
);
|
||||||
|
return Err(ProgramError::InvalidSeeds);
|
||||||
|
}
|
||||||
|
|
||||||
|
let burn_ix = spl_token::instruction::burn(
|
||||||
|
&spl_token::id(),
|
||||||
|
token_account_info.key,
|
||||||
|
token_mint_info.key,
|
||||||
|
authority_info.key,
|
||||||
|
&[],
|
||||||
|
amount,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut signers_seeds = authority_seeds.to_vec();
|
||||||
|
let bump = &[bump_seed];
|
||||||
|
signers_seeds.push(bump);
|
||||||
|
|
||||||
|
invoke_signed(
|
||||||
|
&burn_ix,
|
||||||
|
&[
|
||||||
|
spl_token_info.clone(),
|
||||||
|
token_account_info.clone(),
|
||||||
|
token_mint_info.clone(),
|
||||||
|
authority_info.clone(),
|
||||||
|
],
|
||||||
|
&[&signers_seeds[..]],
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Asserts the given account_info represents a valid SPL Token account which is initialized and belongs to spl_token program
|
/// Asserts the given account_info represents a valid SPL Token account which is initialized and belongs to spl_token program
|
||||||
pub fn assert_is_valid_spl_token_account(account_info: &AccountInfo) -> Result<(), ProgramError> {
|
pub fn assert_is_valid_spl_token_account(account_info: &AccountInfo) -> Result<(), ProgramError> {
|
||||||
if account_info.data_is_empty() {
|
if account_info.data_is_empty() {
|
||||||
|
@ -195,6 +275,11 @@ pub fn assert_is_valid_spl_token_account(account_info: &AccountInfo) -> Result<(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if the given account_info is spl-token token account
|
||||||
|
pub fn is_spl_token_account(account_info: &AccountInfo) -> bool {
|
||||||
|
assert_is_valid_spl_token_account(account_info).is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
/// Asserts the given mint_info represents a valid SPL Token Mint account which is initialized and belongs to spl_token program
|
/// Asserts the given mint_info represents a valid SPL Token Mint account which is initialized and belongs to spl_token program
|
||||||
pub fn assert_is_valid_spl_token_mint(mint_info: &AccountInfo) -> Result<(), ProgramError> {
|
pub fn assert_is_valid_spl_token_mint(mint_info: &AccountInfo) -> Result<(), ProgramError> {
|
||||||
if mint_info.data_is_empty() {
|
if mint_info.data_is_empty() {
|
||||||
|
@ -210,7 +295,7 @@ pub fn assert_is_valid_spl_token_mint(mint_info: &AccountInfo) -> Result<(), Pro
|
||||||
}
|
}
|
||||||
|
|
||||||
// In token program [36, 8, 1, is_initialized(1), 36] is the layout
|
// In token program [36, 8, 1, is_initialized(1), 36] is the layout
|
||||||
let data = mint_info.try_borrow_data().unwrap();
|
let data = mint_info.try_borrow_data()?;
|
||||||
let is_initialized = array_ref![data, 45, 1];
|
let is_initialized = array_ref![data, 45, 1];
|
||||||
|
|
||||||
if is_initialized == &[0] {
|
if is_initialized == &[0] {
|
||||||
|
@ -220,6 +305,11 @@ pub fn assert_is_valid_spl_token_mint(mint_info: &AccountInfo) -> Result<(), Pro
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if the given account_info is be spl-token mint account
|
||||||
|
pub fn is_spl_token_mint(mint_info: &AccountInfo) -> bool {
|
||||||
|
assert_is_valid_spl_token_mint(mint_info).is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
/// Computationally cheap method to get mint from a token account
|
/// Computationally cheap method to get mint from a token account
|
||||||
/// It reads mint without deserializing full account data
|
/// It reads mint without deserializing full account data
|
||||||
pub fn get_spl_token_mint(token_account_info: &AccountInfo) -> Result<Pubkey, ProgramError> {
|
pub fn get_spl_token_mint(token_account_info: &AccountInfo) -> Result<Pubkey, ProgramError> {
|
||||||
|
|
|
@ -8,7 +8,10 @@ use solana_program_test::tokio;
|
||||||
use program_test::*;
|
use program_test::*;
|
||||||
use spl_governance::{
|
use spl_governance::{
|
||||||
error::GovernanceError,
|
error::GovernanceError,
|
||||||
state::enums::{ProposalState, VoteThreshold, VoteTipping},
|
state::{
|
||||||
|
enums::{ProposalState, VoteThreshold, VoteTipping},
|
||||||
|
vote_record::Vote,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -1243,3 +1246,52 @@ async fn test_cast_council_vote() {
|
||||||
proposal_account.vote_threshold
|
proposal_account.vote_threshold
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_cast_vote_with_invalid_realm_config_account_address_error() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test.with_realm().await;
|
||||||
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_community_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut governance_cookie = governance_test
|
||||||
|
.with_governance(
|
||||||
|
&realm_cookie,
|
||||||
|
&governed_account_cookie,
|
||||||
|
&token_owner_record_cookie,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let proposal_cookie = governance_test
|
||||||
|
.with_signed_off_proposal(&token_owner_record_cookie, &mut governance_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Try bypass config check by using none existing config account
|
||||||
|
let realm_config_address = Pubkey::new_unique();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let err = governance_test
|
||||||
|
.with_cast_vote_using_instruction(
|
||||||
|
&proposal_cookie,
|
||||||
|
&token_owner_record_cookie,
|
||||||
|
Vote::Deny,
|
||||||
|
|i| {
|
||||||
|
i.accounts[10].pubkey = realm_config_address; // realm_config_address
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assert_eq!(err, GovernanceError::InvalidRealmConfigAddress.into());
|
||||||
|
}
|
||||||
|
|
|
@ -542,3 +542,41 @@ async fn test_create_proposal_with_disabled_community_vote_error() {
|
||||||
GovernanceError::GoverningTokenMintNotAllowedToVote.into()
|
GovernanceError::GoverningTokenMintNotAllowedToVote.into()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_create_proposal_with_invalid_realm_config_account_address_error() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test.with_realm().await;
|
||||||
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_community_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut governance_cookie = governance_test
|
||||||
|
.with_governance(
|
||||||
|
&realm_cookie,
|
||||||
|
&governed_account_cookie,
|
||||||
|
&token_owner_record_cookie,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Try bypass config check by using none existing config account
|
||||||
|
let realm_config_address = Pubkey::new_unique();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let err = governance_test
|
||||||
|
.with_proposal_using_instruction(&token_owner_record_cookie, &mut governance_cookie, |i| {
|
||||||
|
i.accounts[8].pubkey = realm_config_address;
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assert_eq!(err, GovernanceError::InvalidRealmConfigAddress.into());
|
||||||
|
}
|
||||||
|
|
|
@ -5,12 +5,9 @@ use solana_program_test::*;
|
||||||
mod program_test;
|
mod program_test;
|
||||||
|
|
||||||
use program_test::*;
|
use program_test::*;
|
||||||
use spl_governance::state::{
|
use spl_governance::state::{enums::MintMaxVoteWeightSource, realm::get_realm_address};
|
||||||
enums::MintMaxVoteWeightSource,
|
|
||||||
realm::{get_realm_address, RealmConfigArgs},
|
|
||||||
};
|
|
||||||
|
|
||||||
use self::args::SetRealmConfigArgs;
|
use crate::program_test::args::RealmSetupArgs;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_create_realm() {
|
async fn test_create_realm() {
|
||||||
|
@ -33,23 +30,16 @@ async fn test_create_realm_with_non_default_config() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_new().await;
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
let realm_config_args = RealmConfigArgs {
|
let realm_setup_args = RealmSetupArgs {
|
||||||
use_council_mint: false,
|
use_council_mint: false,
|
||||||
community_mint_max_vote_weight_source: MintMaxVoteWeightSource::SupplyFraction(1),
|
community_mint_max_vote_weight_source: MintMaxVoteWeightSource::SupplyFraction(1),
|
||||||
min_community_weight_to_create_governance: 10,
|
min_community_weight_to_create_governance: 1,
|
||||||
use_community_voter_weight_addin: false,
|
..Default::default()
|
||||||
use_max_community_voter_weight_addin: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let set_realm_config_args = SetRealmConfigArgs {
|
|
||||||
realm_config_args,
|
|
||||||
community_voter_weight_addin: None,
|
|
||||||
max_community_voter_weight_addin: None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
let realm_cookie = governance_test
|
let realm_cookie = governance_test
|
||||||
.with_realm_using_config_args(&set_realm_config_args)
|
.with_realm_using_args(&realm_setup_args)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
|
@ -7,7 +7,12 @@ mod program_test;
|
||||||
|
|
||||||
use program_test::*;
|
use program_test::*;
|
||||||
use solana_sdk::signature::{Keypair, Signer};
|
use solana_sdk::signature::{Keypair, Signer};
|
||||||
use spl_governance::{error::GovernanceError, instruction::deposit_governing_tokens};
|
use spl_governance::{
|
||||||
|
error::GovernanceError, instruction::deposit_governing_tokens,
|
||||||
|
state::realm_config::GoverningTokenType,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::program_test::args::*;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_deposit_initial_community_tokens() {
|
async fn test_deposit_initial_community_tokens() {
|
||||||
|
@ -235,55 +240,6 @@ async fn test_deposit_initial_community_tokens_with_owner_must_sign_error() {
|
||||||
// Assert
|
// Assert
|
||||||
assert_eq!(error, GovernanceError::GoverningTokenOwnerMustSign.into());
|
assert_eq!(error, GovernanceError::GoverningTokenOwnerMustSign.into());
|
||||||
}
|
}
|
||||||
#[tokio::test]
|
|
||||||
async fn test_deposit_initial_community_tokens_with_invalid_owner_error() {
|
|
||||||
// Arrange
|
|
||||||
let mut governance_test = GovernanceProgramTest::start_new().await;
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
|
||||||
|
|
||||||
let token_owner = Keypair::new();
|
|
||||||
let transfer_authority = Keypair::new();
|
|
||||||
let token_source = Keypair::new();
|
|
||||||
|
|
||||||
let invalid_owner = Keypair::new();
|
|
||||||
|
|
||||||
let amount = 10;
|
|
||||||
|
|
||||||
governance_test
|
|
||||||
.bench
|
|
||||||
.create_token_account_with_transfer_authority(
|
|
||||||
&token_source,
|
|
||||||
&realm_cookie.account.community_mint,
|
|
||||||
&realm_cookie.community_mint_authority,
|
|
||||||
amount,
|
|
||||||
&token_owner,
|
|
||||||
&transfer_authority.pubkey(),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let deposit_ix = deposit_governing_tokens(
|
|
||||||
&governance_test.program_id,
|
|
||||||
&realm_cookie.address,
|
|
||||||
&token_source.pubkey(),
|
|
||||||
&invalid_owner.pubkey(),
|
|
||||||
&transfer_authority.pubkey(),
|
|
||||||
&governance_test.bench.context.payer.pubkey(),
|
|
||||||
amount,
|
|
||||||
&realm_cookie.account.community_mint,
|
|
||||||
);
|
|
||||||
|
|
||||||
// // Act
|
|
||||||
|
|
||||||
let error = governance_test
|
|
||||||
.bench
|
|
||||||
.process_transaction(&[deposit_ix], Some(&[&transfer_authority, &invalid_owner]))
|
|
||||||
.await
|
|
||||||
.err()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
assert_eq!(error, GovernanceError::GoverningTokenOwnerMustSign.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_deposit_community_tokens_with_malicious_holding_account_error() {
|
async fn test_deposit_community_tokens_with_malicious_holding_account_error() {
|
||||||
|
@ -340,3 +296,62 @@ async fn test_deposit_community_tokens_with_malicious_holding_account_error() {
|
||||||
GovernanceError::InvalidGoverningTokenHoldingAccount.into()
|
GovernanceError::InvalidGoverningTokenHoldingAccount.into()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_deposit_community_tokens_using_mint() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
let realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_initial_governing_token_deposit_using_mint(
|
||||||
|
&realm_cookie.address,
|
||||||
|
&realm_cookie.account.community_mint,
|
||||||
|
&realm_cookie.community_mint_authority,
|
||||||
|
10,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
let token_owner_record = governance_test
|
||||||
|
.get_token_owner_record_account(&token_owner_record_cookie.address)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(token_owner_record_cookie.account, token_owner_record);
|
||||||
|
|
||||||
|
let holding_account = governance_test
|
||||||
|
.get_token_account(&realm_cookie.community_token_holding_account)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
token_owner_record.governing_token_deposit_amount,
|
||||||
|
holding_account.amount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_deposit_comunity_tokens_with_cannot_deposit_dormant_tokens_error() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_config_args = RealmSetupArgs::default();
|
||||||
|
realm_config_args.council_token_config_args.token_type = GoverningTokenType::Dormant;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_args(&realm_config_args)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let err = governance_test
|
||||||
|
.with_council_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assert_eq!(err, GovernanceError::CannotDepositDormantTokens.into());
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,468 @@
|
||||||
|
#![cfg(feature = "test-bpf")]
|
||||||
|
|
||||||
|
use solana_program::pubkey::Pubkey;
|
||||||
|
use solana_program_test::*;
|
||||||
|
|
||||||
|
mod program_test;
|
||||||
|
|
||||||
|
use program_test::*;
|
||||||
|
|
||||||
|
use spl_governance::{
|
||||||
|
error::GovernanceError,
|
||||||
|
state::{realm::get_governing_token_holding_address, realm_config::GoverningTokenType},
|
||||||
|
};
|
||||||
|
use spl_governance_test_sdk::tools::NopOverride;
|
||||||
|
|
||||||
|
use crate::program_test::args::RealmSetupArgs;
|
||||||
|
use solana_sdk::signature::{Keypair, Signer};
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_revoke_community_tokens() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_config_args = RealmSetupArgs::default();
|
||||||
|
realm_config_args.community_token_config_args.token_type = GoverningTokenType::Membership;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_args(&realm_config_args)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_community_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
governance_test
|
||||||
|
.revoke_community_tokens(&realm_cookie, &token_owner_record_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
let token_owner_record = governance_test
|
||||||
|
.get_token_owner_record_account(&token_owner_record_cookie.address)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(token_owner_record.governing_token_deposit_amount, 0);
|
||||||
|
|
||||||
|
let holding_account = governance_test
|
||||||
|
.get_token_account(&realm_cookie.community_token_holding_account)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(holding_account.amount, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_revoke_council_tokens() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_config_args = RealmSetupArgs::default();
|
||||||
|
realm_config_args.council_token_config_args.token_type = GoverningTokenType::Membership;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_args(&realm_config_args)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_council_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
governance_test
|
||||||
|
.revoke_council_tokens(&realm_cookie, &token_owner_record_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
let token_owner_record = governance_test
|
||||||
|
.get_token_owner_record_account(&token_owner_record_cookie.address)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(token_owner_record.governing_token_deposit_amount, 0);
|
||||||
|
|
||||||
|
let holding_account = governance_test
|
||||||
|
.get_token_account(&realm_cookie.council_token_holding_account.unwrap())
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(holding_account.amount, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_revoke_community_tokens_with_cannot_revoke_liquid_token_error() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_community_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let err = governance_test
|
||||||
|
.revoke_community_tokens(&realm_cookie, &token_owner_record_cookie)
|
||||||
|
.await
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
assert_eq!(err, GovernanceError::CannotRevokeGoverningTokens.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_revoke_community_tokens_with_cannot_revoke_dormant_token_error() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_community_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut realm_config_args = RealmSetupArgs::default();
|
||||||
|
realm_config_args.community_token_config_args.token_type = GoverningTokenType::Dormant;
|
||||||
|
|
||||||
|
governance_test
|
||||||
|
.set_realm_config(&mut realm_cookie, &realm_config_args)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let err = governance_test
|
||||||
|
.revoke_community_tokens(&realm_cookie, &token_owner_record_cookie)
|
||||||
|
.await
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
assert_eq!(err, GovernanceError::CannotRevokeGoverningTokens.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_revoke_council_tokens_with_realm_authority_must_sign_error() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_config_args = RealmSetupArgs::default();
|
||||||
|
realm_config_args.council_token_config_args.token_type = GoverningTokenType::Membership;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_args(&realm_config_args)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_council_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let err = governance_test
|
||||||
|
.revoke_governing_tokens_using_instruction(
|
||||||
|
&realm_cookie,
|
||||||
|
&token_owner_record_cookie,
|
||||||
|
&realm_cookie.account.config.council_mint.unwrap(),
|
||||||
|
1,
|
||||||
|
|i| i.accounts[1].is_signer = false, // realm_authority
|
||||||
|
Some(&[]),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
assert_eq!(err, GovernanceError::RealmAuthorityMustSign.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_revoke_council_tokens_with_invalid_realm_authority_error() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_config_args = RealmSetupArgs::default();
|
||||||
|
realm_config_args.council_token_config_args.token_type = GoverningTokenType::Membership;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_args(&realm_config_args)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_council_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Try to use fake auhtority
|
||||||
|
let realm_authority = Keypair::new();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let err = governance_test
|
||||||
|
.revoke_governing_tokens_using_instruction(
|
||||||
|
&realm_cookie,
|
||||||
|
&token_owner_record_cookie,
|
||||||
|
&realm_cookie.account.config.council_mint.unwrap(),
|
||||||
|
1,
|
||||||
|
|i| i.accounts[1].pubkey = realm_authority.pubkey(), // realm_authority
|
||||||
|
Some(&[&realm_authority]),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
assert_eq!(err, GovernanceError::InvalidAuthorityForRealm.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_revoke_council_tokens_with_invalid_token_holding_error() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_config_args = RealmSetupArgs::default();
|
||||||
|
realm_config_args.council_token_config_args.token_type = GoverningTokenType::Membership;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_args(&realm_config_args)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_council_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Try to revoke from the community holding account
|
||||||
|
let governing_token_holding_address = get_governing_token_holding_address(
|
||||||
|
&governance_test.program_id,
|
||||||
|
&realm_cookie.address,
|
||||||
|
&realm_cookie.account.community_mint,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let err = governance_test
|
||||||
|
.revoke_governing_tokens_using_instruction(
|
||||||
|
&realm_cookie,
|
||||||
|
&token_owner_record_cookie,
|
||||||
|
&realm_cookie.account.config.council_mint.unwrap(),
|
||||||
|
1,
|
||||||
|
|i| i.accounts[2].pubkey = governing_token_holding_address, // governing_token_holding_address
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
err,
|
||||||
|
GovernanceError::InvalidGoverningTokenHoldingAccount.into()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_revoke_council_tokens_with_other_realm_config_account_error() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_config_args = RealmSetupArgs::default();
|
||||||
|
realm_config_args.council_token_config_args.token_type = GoverningTokenType::Membership;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_args(&realm_config_args)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_council_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Try use other Realm config
|
||||||
|
let realm_cookie2 = governance_test.with_realm().await;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let err = governance_test
|
||||||
|
.revoke_governing_tokens_using_instruction(
|
||||||
|
&realm_cookie,
|
||||||
|
&token_owner_record_cookie,
|
||||||
|
&realm_cookie.account.config.council_mint.unwrap(),
|
||||||
|
1,
|
||||||
|
|i| i.accounts[5].pubkey = realm_cookie2.realm_config.address, //realm_config_address
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
assert_eq!(err, GovernanceError::InvalidRealmConfigForRealm.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_revoke_council_tokens_with_invalid_realm_config_account_address_error() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_config_args = RealmSetupArgs::default();
|
||||||
|
realm_config_args.council_token_config_args.token_type = GoverningTokenType::Membership;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_args(&realm_config_args)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_council_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Try bypass config check by using none existing config account
|
||||||
|
let realm_config_address = Pubkey::new_unique();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let err = governance_test
|
||||||
|
.revoke_governing_tokens_using_instruction(
|
||||||
|
&realm_cookie,
|
||||||
|
&token_owner_record_cookie,
|
||||||
|
&realm_cookie.account.config.council_mint.unwrap(),
|
||||||
|
1,
|
||||||
|
|i| i.accounts[5].pubkey = realm_config_address, // realm_config_address
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
assert_eq!(err, GovernanceError::InvalidRealmConfigAddress.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_revoke_council_tokens_with_token_owner_record_for_different_mint_error() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_config_args = RealmSetupArgs::default();
|
||||||
|
realm_config_args.council_token_config_args.token_type = GoverningTokenType::Membership;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_args(&realm_config_args)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_council_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Try to revoke from the community token owner record
|
||||||
|
let token_owner_record_cookie2 = governance_test
|
||||||
|
.with_community_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let err = governance_test
|
||||||
|
.revoke_governing_tokens_using_instruction(
|
||||||
|
&realm_cookie,
|
||||||
|
&token_owner_record_cookie,
|
||||||
|
&realm_cookie.account.config.council_mint.unwrap(),
|
||||||
|
1,
|
||||||
|
|i| i.accounts[3].pubkey = token_owner_record_cookie2.address, // token_owner_record_address
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
err,
|
||||||
|
GovernanceError::InvalidGoverningMintForTokenOwnerRecord.into()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_revoke_council_tokens_with_too_large_amount_error() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_config_args = RealmSetupArgs::default();
|
||||||
|
realm_config_args.council_token_config_args.token_type = GoverningTokenType::Membership;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_args(&realm_config_args)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_council_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let err = governance_test
|
||||||
|
.revoke_governing_tokens_using_instruction(
|
||||||
|
&realm_cookie,
|
||||||
|
&token_owner_record_cookie,
|
||||||
|
&realm_cookie.account.config.council_mint.unwrap(),
|
||||||
|
200,
|
||||||
|
NopOverride,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
assert_eq!(err, GovernanceError::InvalidRevokeAmount.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_revoke_council_tokens_with_partial_revoke_amount() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_config_args = RealmSetupArgs::default();
|
||||||
|
realm_config_args.council_token_config_args.token_type = GoverningTokenType::Membership;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_args(&realm_config_args)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_council_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
governance_test
|
||||||
|
.revoke_governing_tokens_using_instruction(
|
||||||
|
&realm_cookie,
|
||||||
|
&token_owner_record_cookie,
|
||||||
|
&realm_cookie.account.config.council_mint.unwrap(),
|
||||||
|
5,
|
||||||
|
NopOverride,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
let token_owner_record = governance_test
|
||||||
|
.get_token_owner_record_account(&token_owner_record_cookie.address)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(token_owner_record.governing_token_deposit_amount, 95);
|
||||||
|
}
|
|
@ -8,10 +8,10 @@ mod program_test;
|
||||||
use program_test::*;
|
use program_test::*;
|
||||||
use spl_governance::{
|
use spl_governance::{
|
||||||
error::GovernanceError,
|
error::GovernanceError,
|
||||||
state::{enums::MintMaxVoteWeightSource, realm::RealmConfigArgs},
|
state::{realm::GoverningTokenConfigAccountArgs, realm_config::GoverningTokenType},
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::args::SetRealmConfigArgs;
|
use crate::program_test::args::RealmSetupArgs;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_set_realm_config() {
|
async fn test_set_realm_config() {
|
||||||
|
@ -20,25 +20,12 @@ async fn test_set_realm_config() {
|
||||||
|
|
||||||
let mut realm_cookie = governance_test.with_realm().await;
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
let realm_config_args = RealmConfigArgs {
|
let realm_setup_args = RealmSetupArgs::default();
|
||||||
use_council_mint: true,
|
|
||||||
|
|
||||||
community_mint_max_vote_weight_source: MintMaxVoteWeightSource::SupplyFraction(100),
|
|
||||||
min_community_weight_to_create_governance: 10,
|
|
||||||
use_community_voter_weight_addin: false,
|
|
||||||
use_max_community_voter_weight_addin: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let set_realm_config_args = SetRealmConfigArgs {
|
|
||||||
realm_config_args,
|
|
||||||
community_voter_weight_addin: None,
|
|
||||||
max_community_voter_weight_addin: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -57,27 +44,14 @@ async fn test_set_realm_config_with_authority_must_sign_error() {
|
||||||
|
|
||||||
let mut realm_cookie = governance_test.with_realm().await;
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
let realm_config_args = RealmConfigArgs {
|
let realm_setup_args = RealmSetupArgs::default();
|
||||||
use_council_mint: true,
|
|
||||||
|
|
||||||
community_mint_max_vote_weight_source: MintMaxVoteWeightSource::SupplyFraction(100),
|
|
||||||
min_community_weight_to_create_governance: 10,
|
|
||||||
use_community_voter_weight_addin: false,
|
|
||||||
use_max_community_voter_weight_addin: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let set_realm_config_args = SetRealmConfigArgs {
|
|
||||||
realm_config_args,
|
|
||||||
community_voter_weight_addin: None,
|
|
||||||
max_community_voter_weight_addin: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
let err = governance_test
|
let err = governance_test
|
||||||
.set_realm_config_using_instruction(
|
.set_realm_config_using_instruction(
|
||||||
&mut realm_cookie,
|
&mut realm_cookie,
|
||||||
&set_realm_config_args,
|
&realm_setup_args,
|
||||||
|i| i.accounts[1].is_signer = false,
|
|i| i.accounts[1].is_signer = false,
|
||||||
Some(&[]),
|
Some(&[]),
|
||||||
)
|
)
|
||||||
|
@ -96,20 +70,7 @@ async fn test_set_realm_config_with_no_authority_error() {
|
||||||
|
|
||||||
let mut realm_cookie = governance_test.with_realm().await;
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
let realm_config_args = RealmConfigArgs {
|
let realm_setup_args = RealmSetupArgs::default();
|
||||||
use_council_mint: true,
|
|
||||||
|
|
||||||
community_mint_max_vote_weight_source: MintMaxVoteWeightSource::SupplyFraction(100),
|
|
||||||
min_community_weight_to_create_governance: 10,
|
|
||||||
use_community_voter_weight_addin: false,
|
|
||||||
use_max_community_voter_weight_addin: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let set_realm_config_args = SetRealmConfigArgs {
|
|
||||||
realm_config_args,
|
|
||||||
community_voter_weight_addin: None,
|
|
||||||
max_community_voter_weight_addin: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_authority(&realm_cookie, None)
|
.set_realm_authority(&realm_cookie, None)
|
||||||
|
@ -121,7 +82,7 @@ async fn test_set_realm_config_with_no_authority_error() {
|
||||||
let err = governance_test
|
let err = governance_test
|
||||||
.set_realm_config_using_instruction(
|
.set_realm_config_using_instruction(
|
||||||
&mut realm_cookie,
|
&mut realm_cookie,
|
||||||
&set_realm_config_args,
|
&realm_setup_args,
|
||||||
|i| i.accounts[1].is_signer = false,
|
|i| i.accounts[1].is_signer = false,
|
||||||
Some(&[]),
|
Some(&[]),
|
||||||
)
|
)
|
||||||
|
@ -140,20 +101,7 @@ async fn test_set_realm_config_with_invalid_authority_error() {
|
||||||
|
|
||||||
let mut realm_cookie = governance_test.with_realm().await;
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
let realm_config_args = RealmConfigArgs {
|
let realm_setup_args = RealmSetupArgs::default();
|
||||||
use_council_mint: true,
|
|
||||||
|
|
||||||
community_mint_max_vote_weight_source: MintMaxVoteWeightSource::SupplyFraction(100),
|
|
||||||
min_community_weight_to_create_governance: 10,
|
|
||||||
use_community_voter_weight_addin: false,
|
|
||||||
use_max_community_voter_weight_addin: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let set_realm_config_args = SetRealmConfigArgs {
|
|
||||||
realm_config_args,
|
|
||||||
community_voter_weight_addin: None,
|
|
||||||
max_community_voter_weight_addin: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let realm_cookie2 = governance_test.with_realm().await;
|
let realm_cookie2 = governance_test.with_realm().await;
|
||||||
|
|
||||||
|
@ -163,7 +111,7 @@ async fn test_set_realm_config_with_invalid_authority_error() {
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
let err = governance_test
|
let err = governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.err()
|
.err()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -179,24 +127,12 @@ async fn test_set_realm_config_with_remove_council() {
|
||||||
|
|
||||||
let mut realm_cookie = governance_test.with_realm().await;
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
let realm_config_args = RealmConfigArgs {
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
use_council_mint: false,
|
realm_setup_args.use_council_mint = false;
|
||||||
|
|
||||||
community_mint_max_vote_weight_source: MintMaxVoteWeightSource::SupplyFraction(100),
|
|
||||||
min_community_weight_to_create_governance: 10,
|
|
||||||
use_community_voter_weight_addin: false,
|
|
||||||
use_max_community_voter_weight_addin: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let set_realm_config_args = SetRealmConfigArgs {
|
|
||||||
realm_config_args,
|
|
||||||
community_voter_weight_addin: None,
|
|
||||||
max_community_voter_weight_addin: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -216,27 +152,14 @@ async fn test_set_realm_config_with_council_change_error() {
|
||||||
|
|
||||||
let mut realm_cookie = governance_test.with_realm().await;
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
let realm_config_args = RealmConfigArgs {
|
let realm_setup_args = RealmSetupArgs::default();
|
||||||
use_council_mint: true,
|
|
||||||
|
|
||||||
community_mint_max_vote_weight_source: MintMaxVoteWeightSource::SupplyFraction(100),
|
|
||||||
min_community_weight_to_create_governance: 10,
|
|
||||||
use_community_voter_weight_addin: false,
|
|
||||||
use_max_community_voter_weight_addin: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let set_realm_config_args = SetRealmConfigArgs {
|
|
||||||
realm_config_args,
|
|
||||||
community_voter_weight_addin: None,
|
|
||||||
max_community_voter_weight_addin: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Try to replace council mint
|
// Try to replace council mint
|
||||||
realm_cookie.account.config.council_mint = serde::__private::Some(Pubkey::new_unique());
|
realm_cookie.account.config.council_mint = serde::__private::Some(Pubkey::new_unique());
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
let err = governance_test
|
let err = governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.err()
|
.err()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -255,33 +178,21 @@ async fn test_set_realm_config_with_council_restore_error() {
|
||||||
|
|
||||||
let mut realm_cookie = governance_test.with_realm().await;
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
let realm_config_args = RealmConfigArgs {
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
use_council_mint: false,
|
realm_setup_args.use_council_mint = false;
|
||||||
|
|
||||||
community_mint_max_vote_weight_source: MintMaxVoteWeightSource::SupplyFraction(100),
|
|
||||||
min_community_weight_to_create_governance: 10,
|
|
||||||
use_community_voter_weight_addin: false,
|
|
||||||
use_max_community_voter_weight_addin: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut set_realm_config_args = SetRealmConfigArgs {
|
|
||||||
realm_config_args,
|
|
||||||
community_voter_weight_addin: None,
|
|
||||||
max_community_voter_weight_addin: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Try to restore council mint after removing it
|
// Try to restore council mint after removing it
|
||||||
set_realm_config_args.realm_config_args.use_council_mint = true;
|
realm_setup_args.use_council_mint = true;
|
||||||
realm_cookie.account.config.council_mint = serde::__private::Some(Pubkey::new_unique());
|
realm_cookie.account.config.council_mint = serde::__private::Some(Pubkey::new_unique());
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
let err = governance_test
|
let err = governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.err()
|
.err()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -292,3 +203,134 @@ async fn test_set_realm_config_with_council_restore_error() {
|
||||||
GovernanceError::RealmCouncilMintChangeIsNotSupported.into()
|
GovernanceError::RealmCouncilMintChangeIsNotSupported.into()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_set_realm_config_with_liquid_community_token_cannot_be_changed_to_memebership_error()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
|
// Try to change Community token type to Membership
|
||||||
|
realm_setup_args.community_token_config_args.token_type = GoverningTokenType::Membership;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let err = governance_test
|
||||||
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
|
.await
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assert_eq!(
|
||||||
|
err,
|
||||||
|
GovernanceError::CannotChangeCommunityTokenTypeToMemebership.into()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_set_realm_config_for_community_token_config() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
|
// Change Community token type to Dormant and set plugins
|
||||||
|
realm_setup_args.community_token_config_args = GoverningTokenConfigAccountArgs {
|
||||||
|
voter_weight_addin: Some(Pubkey::new_unique()),
|
||||||
|
max_voter_weight_addin: Some(Pubkey::new_unique()),
|
||||||
|
token_type: GoverningTokenType::Dormant,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
|
||||||
|
governance_test
|
||||||
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
let realm_config_account = governance_test
|
||||||
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
realm_config_account.community_token_config.token_type,
|
||||||
|
GoverningTokenType::Dormant
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
realm_config_account
|
||||||
|
.community_token_config
|
||||||
|
.voter_weight_addin,
|
||||||
|
realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.voter_weight_addin
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
realm_config_account
|
||||||
|
.community_token_config
|
||||||
|
.max_voter_weight_addin,
|
||||||
|
realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.max_voter_weight_addin
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_set_realm_config_for_council_token_config() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
|
// Change Council token type to Membership and set plugins
|
||||||
|
realm_setup_args.council_token_config_args = GoverningTokenConfigAccountArgs {
|
||||||
|
voter_weight_addin: Some(Pubkey::new_unique()),
|
||||||
|
max_voter_weight_addin: Some(Pubkey::new_unique()),
|
||||||
|
token_type: GoverningTokenType::Membership,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
|
||||||
|
governance_test
|
||||||
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
let realm_config_account = governance_test
|
||||||
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
realm_config_account.council_token_config.token_type,
|
||||||
|
GoverningTokenType::Membership
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
realm_config_account.council_token_config.voter_weight_addin,
|
||||||
|
realm_setup_args
|
||||||
|
.council_token_config_args
|
||||||
|
.voter_weight_addin
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
realm_config_account
|
||||||
|
.council_token_config
|
||||||
|
.max_voter_weight_addin,
|
||||||
|
realm_setup_args
|
||||||
|
.council_token_config_args
|
||||||
|
.max_voter_weight_addin
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -9,10 +9,13 @@ use program_test::*;
|
||||||
use solana_sdk::signature::Signer;
|
use solana_sdk::signature::Signer;
|
||||||
|
|
||||||
use spl_governance::{
|
use spl_governance::{
|
||||||
error::GovernanceError, instruction::withdraw_governing_tokens,
|
error::GovernanceError,
|
||||||
state::token_owner_record::get_token_owner_record_address,
|
instruction::withdraw_governing_tokens,
|
||||||
|
state::{realm_config::GoverningTokenType, token_owner_record::get_token_owner_record_address},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::program_test::args::RealmSetupArgs;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_withdraw_community_tokens() {
|
async fn test_withdraw_community_tokens() {
|
||||||
// Arrange
|
// Arrange
|
||||||
|
@ -420,3 +423,65 @@ async fn test_withdraw_governing_tokens_after_proposal_cancelled() {
|
||||||
source_account.amount
|
source_account.amount
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_withdraw_council_tokens_with_cannot_withdraw_membership_tokens_error() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_config_args = RealmSetupArgs::default();
|
||||||
|
realm_config_args.council_token_config_args.token_type = GoverningTokenType::Membership;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_args(&realm_config_args)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_council_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let err = governance_test
|
||||||
|
.withdraw_council_tokens(&realm_cookie, &token_owner_record_cookie)
|
||||||
|
.await
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assert_eq!(err, GovernanceError::CannotWithdrawMembershipTokens.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_withdraw_dormant_community_tokens() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_new().await;
|
||||||
|
|
||||||
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
|
let token_owner_record_cookie = governance_test
|
||||||
|
.with_community_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
realm_setup_args.community_token_config_args.token_type = GoverningTokenType::Dormant;
|
||||||
|
|
||||||
|
governance_test
|
||||||
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
governance_test
|
||||||
|
.withdraw_community_tokens(&realm_cookie, &token_owner_record_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
let token_owner_record = governance_test
|
||||||
|
.get_token_owner_record_account(&token_owner_record_cookie.address)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(0, token_owner_record.governing_token_deposit_amount);
|
||||||
|
}
|
||||||
|
|
|
@ -1,28 +1,70 @@
|
||||||
use solana_program::pubkey::Pubkey;
|
use spl_governance::state::{
|
||||||
use spl_governance::state::{enums::MintMaxVoteWeightSource, realm::RealmConfigArgs};
|
enums::MintMaxVoteWeightSource, realm::GoverningTokenConfigAccountArgs,
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
|
||||||
pub struct SetRealmConfigArgs {
|
|
||||||
pub realm_config_args: RealmConfigArgs,
|
|
||||||
pub community_voter_weight_addin: Option<Pubkey>,
|
|
||||||
pub max_community_voter_weight_addin: Option<Pubkey>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for SetRealmConfigArgs {
|
|
||||||
fn default() -> Self {
|
|
||||||
let realm_config_args = RealmConfigArgs {
|
|
||||||
use_council_mint: true,
|
|
||||||
|
|
||||||
community_mint_max_vote_weight_source: MintMaxVoteWeightSource::SupplyFraction(100),
|
|
||||||
min_community_weight_to_create_governance: 10,
|
|
||||||
use_community_voter_weight_addin: false,
|
|
||||||
use_max_community_voter_weight_addin: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct RealmSetupArgs {
|
||||||
|
pub use_council_mint: bool,
|
||||||
|
pub min_community_weight_to_create_governance: u64,
|
||||||
|
pub community_mint_max_vote_weight_source: MintMaxVoteWeightSource,
|
||||||
|
pub community_token_config_args: GoverningTokenConfigAccountArgs,
|
||||||
|
pub council_token_config_args: GoverningTokenConfigAccountArgs,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RealmSetupArgs {
|
||||||
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
realm_config_args,
|
use_council_mint: true,
|
||||||
community_voter_weight_addin: None,
|
community_token_config_args: GoverningTokenConfigAccountArgs::default(),
|
||||||
max_community_voter_weight_addin: None,
|
council_token_config_args: GoverningTokenConfigAccountArgs::default(),
|
||||||
|
min_community_weight_to_create_governance: 10,
|
||||||
|
community_mint_max_vote_weight_source: MintMaxVoteWeightSource::FULL_SUPPLY_FRACTION,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct PluginSetupArgs {
|
||||||
|
pub use_community_voter_weight_addin: bool,
|
||||||
|
pub use_max_community_voter_weight_addin: bool,
|
||||||
|
pub use_council_voter_weight_addin: bool,
|
||||||
|
pub use_max_council_voter_weight_addin: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PluginSetupArgs {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub const COMMUNITY_VOTER_WEIGHT: PluginSetupArgs = PluginSetupArgs {
|
||||||
|
use_community_voter_weight_addin: true,
|
||||||
|
use_max_community_voter_weight_addin: false,
|
||||||
|
use_council_voter_weight_addin: false,
|
||||||
|
use_max_council_voter_weight_addin: false,
|
||||||
|
};
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub const COMMUNITY_MAX_VOTER_WEIGHT: PluginSetupArgs = PluginSetupArgs {
|
||||||
|
use_community_voter_weight_addin: false,
|
||||||
|
use_max_community_voter_weight_addin: true,
|
||||||
|
use_council_voter_weight_addin: false,
|
||||||
|
use_max_council_voter_weight_addin: false,
|
||||||
|
};
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub const COUNCIL_VOTER_WEIGHT: PluginSetupArgs = PluginSetupArgs {
|
||||||
|
use_community_voter_weight_addin: false,
|
||||||
|
use_max_community_voter_weight_addin: false,
|
||||||
|
use_council_voter_weight_addin: true,
|
||||||
|
use_max_council_voter_weight_addin: false,
|
||||||
|
};
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub const COUNCIL_MAX_VOTER_WEIGHT: PluginSetupArgs = PluginSetupArgs {
|
||||||
|
use_community_voter_weight_addin: false,
|
||||||
|
use_max_community_voter_weight_addin: false,
|
||||||
|
use_council_voter_weight_addin: false,
|
||||||
|
use_max_council_voter_weight_addin: true,
|
||||||
|
};
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub const ALL: PluginSetupArgs = PluginSetupArgs {
|
||||||
|
use_community_voter_weight_addin: true,
|
||||||
|
use_max_community_voter_weight_addin: true,
|
||||||
|
use_council_voter_weight_addin: true,
|
||||||
|
use_max_council_voter_weight_addin: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ pub struct RealmCookie {
|
||||||
|
|
||||||
pub realm_authority: Option<Keypair>,
|
pub realm_authority: Option<Keypair>,
|
||||||
|
|
||||||
pub realm_config: Option<RealmConfigCookie>,
|
pub realm_config: RealmConfigCookie,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -20,9 +20,9 @@ use spl_governance::{
|
||||||
create_native_treasury, create_program_governance, create_proposal, create_realm,
|
create_native_treasury, create_program_governance, create_proposal, create_realm,
|
||||||
create_token_governance, create_token_owner_record, deposit_governing_tokens,
|
create_token_governance, create_token_owner_record, deposit_governing_tokens,
|
||||||
execute_transaction, finalize_vote, flag_transaction_error, insert_transaction,
|
execute_transaction, finalize_vote, flag_transaction_error, insert_transaction,
|
||||||
relinquish_vote, remove_signatory, remove_transaction, set_governance_config,
|
relinquish_vote, remove_signatory, remove_transaction, revoke_governing_tokens,
|
||||||
set_governance_delegate, set_realm_authority, set_realm_config, sign_off_proposal,
|
set_governance_config, set_governance_delegate, set_realm_authority, set_realm_config,
|
||||||
upgrade_program_metadata, withdraw_governing_tokens,
|
sign_off_proposal, upgrade_program_metadata, withdraw_governing_tokens,
|
||||||
},
|
},
|
||||||
processor::process_instruction,
|
processor::process_instruction,
|
||||||
state::{
|
state::{
|
||||||
|
@ -41,10 +41,12 @@ use spl_governance::{
|
||||||
get_proposal_transaction_address, InstructionData, ProposalTransactionV2,
|
get_proposal_transaction_address, InstructionData, ProposalTransactionV2,
|
||||||
},
|
},
|
||||||
realm::{
|
realm::{
|
||||||
get_governing_token_holding_address, get_realm_address, RealmConfig, RealmConfigArgs,
|
get_governing_token_holding_address, get_realm_address,
|
||||||
RealmV2, SetRealmAuthorityAction,
|
GoverningTokenConfigAccountArgs, RealmConfig, RealmV2, SetRealmAuthorityAction,
|
||||||
|
},
|
||||||
|
realm_config::{
|
||||||
|
get_realm_config_address, GoverningTokenConfig, RealmConfigAccount, Reserved110,
|
||||||
},
|
},
|
||||||
realm_config::{get_realm_config_address, RealmConfigAccount},
|
|
||||||
signatory_record::{get_signatory_record_address, SignatoryRecordV2},
|
signatory_record::{get_signatory_record_address, SignatoryRecordV2},
|
||||||
token_owner_record::{get_token_owner_record_address, TokenOwnerRecordV2},
|
token_owner_record::{get_token_owner_record_address, TokenOwnerRecordV2},
|
||||||
vote_record::{get_vote_record_address, Vote, VoteChoice, VoteRecordV2},
|
vote_record::{get_vote_record_address, Vote, VoteChoice, VoteRecordV2},
|
||||||
|
@ -73,8 +75,8 @@ use spl_governance_test_sdk::{
|
||||||
ProgramTestBench,
|
ProgramTestBench,
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::{
|
use crate::{
|
||||||
args::SetRealmConfigArgs,
|
args::{PluginSetupArgs, RealmSetupArgs},
|
||||||
cookies::{
|
cookies::{
|
||||||
GovernanceCookie, GovernedAccountCookie, GovernedMintCookie, GovernedProgramCookie,
|
GovernanceCookie, GovernedAccountCookie, GovernedMintCookie, GovernedProgramCookie,
|
||||||
GovernedTokenCookie, MaxVoterWeightRecordCookie, NativeTreasuryCookie,
|
GovernedTokenCookie, MaxVoterWeightRecordCookie, NativeTreasuryCookie,
|
||||||
|
@ -178,47 +180,52 @@ impl GovernanceProgramTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn get_default_set_realm_config_args(&mut self) -> SetRealmConfigArgs {
|
|
||||||
let realm_config_args = RealmConfigArgs {
|
|
||||||
use_council_mint: true,
|
|
||||||
community_mint_max_vote_weight_source: MintMaxVoteWeightSource::FULL_SUPPLY_FRACTION,
|
|
||||||
min_community_weight_to_create_governance: 10,
|
|
||||||
use_community_voter_weight_addin: self.voter_weight_addin_id.is_some(),
|
|
||||||
use_max_community_voter_weight_addin: self.max_voter_weight_addin_id.is_some(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let community_voter_weight_addin = if realm_config_args.use_community_voter_weight_addin {
|
|
||||||
self.voter_weight_addin_id
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let max_community_voter_weight_addin =
|
|
||||||
if realm_config_args.use_max_community_voter_weight_addin {
|
|
||||||
self.max_voter_weight_addin_id
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
SetRealmConfigArgs {
|
|
||||||
realm_config_args,
|
|
||||||
community_voter_weight_addin,
|
|
||||||
max_community_voter_weight_addin,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn with_realm(&mut self) -> RealmCookie {
|
pub async fn with_realm(&mut self) -> RealmCookie {
|
||||||
let set_realm_config_args = self.get_default_set_realm_config_args();
|
let realm_setup_args = RealmSetupArgs::default();
|
||||||
self.with_realm_using_config_args(&set_realm_config_args)
|
self.with_realm_using_args(&realm_setup_args).await
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn with_realm_using_config_args(
|
pub async fn with_realm_using_addins(
|
||||||
&mut self,
|
&mut self,
|
||||||
set_realm_config_args: &SetRealmConfigArgs,
|
plugin_setup_args: PluginSetupArgs,
|
||||||
|
) -> RealmCookie {
|
||||||
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
|
if plugin_setup_args.use_community_voter_weight_addin {
|
||||||
|
realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.voter_weight_addin = self.voter_weight_addin_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if plugin_setup_args.use_max_community_voter_weight_addin {
|
||||||
|
realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.max_voter_weight_addin = self.max_voter_weight_addin_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if plugin_setup_args.use_council_voter_weight_addin {
|
||||||
|
realm_setup_args
|
||||||
|
.council_token_config_args
|
||||||
|
.voter_weight_addin = self.voter_weight_addin_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if plugin_setup_args.use_max_council_voter_weight_addin {
|
||||||
|
realm_setup_args
|
||||||
|
.council_token_config_args
|
||||||
|
.max_voter_weight_addin = self.max_voter_weight_addin_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
let realm_cookie = self.with_realm_using_args(&realm_setup_args).await;
|
||||||
|
|
||||||
|
realm_cookie
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub async fn with_realm_using_args(
|
||||||
|
&mut self,
|
||||||
|
realm_setup_args: &RealmSetupArgs,
|
||||||
) -> RealmCookie {
|
) -> RealmCookie {
|
||||||
let name = format!("Realm #{}", self.next_realm_id).to_string();
|
let name = format!("Realm #{}", self.next_realm_id).to_string();
|
||||||
self.next_realm_id += 1;
|
self.next_realm_id += 1;
|
||||||
|
@ -246,7 +253,7 @@ impl GovernanceProgramTest {
|
||||||
council_token_mint_pubkey,
|
council_token_mint_pubkey,
|
||||||
council_token_holding_address,
|
council_token_holding_address,
|
||||||
council_token_mint_authority,
|
council_token_mint_authority,
|
||||||
) = if set_realm_config_args.realm_config_args.use_council_mint {
|
) = if realm_setup_args.use_council_mint {
|
||||||
let council_token_mint_keypair = Keypair::new();
|
let council_token_mint_keypair = Keypair::new();
|
||||||
let council_token_mint_authority = Keypair::new();
|
let council_token_mint_authority = Keypair::new();
|
||||||
|
|
||||||
|
@ -275,20 +282,43 @@ impl GovernanceProgramTest {
|
||||||
|
|
||||||
let realm_authority = Keypair::new();
|
let realm_authority = Keypair::new();
|
||||||
|
|
||||||
|
let community_token_args = GoverningTokenConfigAccountArgs {
|
||||||
|
voter_weight_addin: realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.voter_weight_addin,
|
||||||
|
max_voter_weight_addin: realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.max_voter_weight_addin,
|
||||||
|
token_type: realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.token_type
|
||||||
|
.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let council_token_args = GoverningTokenConfigAccountArgs {
|
||||||
|
voter_weight_addin: realm_setup_args
|
||||||
|
.council_token_config_args
|
||||||
|
.voter_weight_addin,
|
||||||
|
max_voter_weight_addin: realm_setup_args
|
||||||
|
.council_token_config_args
|
||||||
|
.max_voter_weight_addin,
|
||||||
|
token_type: realm_setup_args
|
||||||
|
.council_token_config_args
|
||||||
|
.token_type
|
||||||
|
.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
let create_realm_ix = create_realm(
|
let create_realm_ix = create_realm(
|
||||||
&self.program_id,
|
&self.program_id,
|
||||||
&realm_authority.pubkey(),
|
&realm_authority.pubkey(),
|
||||||
&community_token_mint_keypair.pubkey(),
|
&community_token_mint_keypair.pubkey(),
|
||||||
&self.bench.payer.pubkey(),
|
&self.bench.payer.pubkey(),
|
||||||
council_token_mint_pubkey,
|
council_token_mint_pubkey,
|
||||||
set_realm_config_args.community_voter_weight_addin,
|
Some(community_token_args),
|
||||||
set_realm_config_args.max_community_voter_weight_addin,
|
Some(council_token_args),
|
||||||
name.clone(),
|
name.clone(),
|
||||||
set_realm_config_args
|
realm_setup_args.min_community_weight_to_create_governance,
|
||||||
.realm_config_args
|
realm_setup_args
|
||||||
.min_community_weight_to_create_governance,
|
|
||||||
set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.community_mint_max_vote_weight_source
|
.community_mint_max_vote_weight_source
|
||||||
.clone(),
|
.clone(),
|
||||||
);
|
);
|
||||||
|
@ -309,41 +339,51 @@ impl GovernanceProgramTest {
|
||||||
council_mint: council_token_mint_pubkey,
|
council_mint: council_token_mint_pubkey,
|
||||||
reserved: [0; 6],
|
reserved: [0; 6],
|
||||||
|
|
||||||
min_community_weight_to_create_governance: set_realm_config_args
|
min_community_weight_to_create_governance: realm_setup_args
|
||||||
.realm_config_args
|
|
||||||
.min_community_weight_to_create_governance,
|
.min_community_weight_to_create_governance,
|
||||||
community_mint_max_vote_weight_source: set_realm_config_args
|
community_mint_max_vote_weight_source: realm_setup_args
|
||||||
.realm_config_args
|
|
||||||
.community_mint_max_vote_weight_source
|
.community_mint_max_vote_weight_source
|
||||||
.clone(),
|
.clone(),
|
||||||
use_community_voter_weight_addin: false,
|
legacy1: 0,
|
||||||
use_max_community_voter_weight_addin: false,
|
legacy2: 0,
|
||||||
},
|
},
|
||||||
voting_proposal_count: 0,
|
voting_proposal_count: 0,
|
||||||
reserved_v2: [0; 128],
|
reserved_v2: [0; 128],
|
||||||
};
|
};
|
||||||
|
|
||||||
let realm_config_cookie = if set_realm_config_args.community_voter_weight_addin.is_some()
|
let realm_config_cookie = RealmConfigCookie {
|
||||||
|| set_realm_config_args
|
|
||||||
.max_community_voter_weight_addin
|
|
||||||
.is_some()
|
|
||||||
{
|
|
||||||
Some(RealmConfigCookie {
|
|
||||||
address: get_realm_config_address(&self.program_id, &realm_address),
|
address: get_realm_config_address(&self.program_id, &realm_address),
|
||||||
account: RealmConfigAccount {
|
account: RealmConfigAccount {
|
||||||
account_type: GovernanceAccountType::RealmConfig,
|
account_type: GovernanceAccountType::RealmConfig,
|
||||||
realm: realm_address,
|
realm: realm_address,
|
||||||
community_voter_weight_addin: set_realm_config_args
|
reserved: Reserved110::default(),
|
||||||
.community_voter_weight_addin,
|
community_token_config: GoverningTokenConfig {
|
||||||
max_community_voter_weight_addin: set_realm_config_args
|
voter_weight_addin: realm_setup_args
|
||||||
.max_community_voter_weight_addin,
|
.community_token_config_args
|
||||||
council_voter_weight_addin: None,
|
.voter_weight_addin,
|
||||||
council_max_vote_weight_addin: None,
|
max_voter_weight_addin: realm_setup_args
|
||||||
reserved: [0; 128],
|
.community_token_config_args
|
||||||
|
.max_voter_weight_addin,
|
||||||
|
token_type: realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.token_type
|
||||||
|
.clone(),
|
||||||
|
reserved: [0; 8],
|
||||||
|
},
|
||||||
|
council_token_config: GoverningTokenConfig {
|
||||||
|
voter_weight_addin: realm_setup_args
|
||||||
|
.council_token_config_args
|
||||||
|
.voter_weight_addin,
|
||||||
|
max_voter_weight_addin: realm_setup_args
|
||||||
|
.council_token_config_args
|
||||||
|
.max_voter_weight_addin,
|
||||||
|
token_type: realm_setup_args
|
||||||
|
.council_token_config_args
|
||||||
|
.token_type
|
||||||
|
.clone(),
|
||||||
|
reserved: [0; 8],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RealmCookie {
|
RealmCookie {
|
||||||
|
@ -405,8 +445,8 @@ impl GovernanceProgramTest {
|
||||||
community_mint_max_vote_weight_source:
|
community_mint_max_vote_weight_source:
|
||||||
MintMaxVoteWeightSource::FULL_SUPPLY_FRACTION,
|
MintMaxVoteWeightSource::FULL_SUPPLY_FRACTION,
|
||||||
min_community_weight_to_create_governance,
|
min_community_weight_to_create_governance,
|
||||||
use_community_voter_weight_addin: false,
|
legacy1: 0,
|
||||||
use_max_community_voter_weight_addin: false,
|
legacy2: 0,
|
||||||
},
|
},
|
||||||
voting_proposal_count: 0,
|
voting_proposal_count: 0,
|
||||||
reserved_v2: [0; 128],
|
reserved_v2: [0; 128],
|
||||||
|
@ -421,6 +461,17 @@ impl GovernanceProgramTest {
|
||||||
let council_token_holding_address =
|
let council_token_holding_address =
|
||||||
get_governing_token_holding_address(&self.program_id, &realm_address, &council_mint);
|
get_governing_token_holding_address(&self.program_id, &realm_address, &council_mint);
|
||||||
|
|
||||||
|
let realm_config_cookie = RealmConfigCookie {
|
||||||
|
address: get_realm_config_address(&self.program_id, &realm_address),
|
||||||
|
account: RealmConfigAccount {
|
||||||
|
account_type: GovernanceAccountType::RealmConfig,
|
||||||
|
realm: realm_address,
|
||||||
|
council_token_config: GoverningTokenConfig::default(),
|
||||||
|
reserved: Reserved110::default(),
|
||||||
|
community_token_config: GoverningTokenConfig::default(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
RealmCookie {
|
RealmCookie {
|
||||||
address: realm_address,
|
address: realm_address,
|
||||||
account,
|
account,
|
||||||
|
@ -433,7 +484,7 @@ impl GovernanceProgramTest {
|
||||||
realm_cookie.council_mint_authority.as_ref().unwrap(),
|
realm_cookie.council_mint_authority.as_ref().unwrap(),
|
||||||
)),
|
)),
|
||||||
realm_authority: Some(realm_authority),
|
realm_authority: Some(realm_authority),
|
||||||
realm_config: None,
|
realm_config: realm_config_cookie,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,6 +508,28 @@ impl GovernanceProgramTest {
|
||||||
pub async fn with_community_token_owner_record(
|
pub async fn with_community_token_owner_record(
|
||||||
&mut self,
|
&mut self,
|
||||||
realm_cookie: &RealmCookie,
|
realm_cookie: &RealmCookie,
|
||||||
|
) -> TokenOwnerRecordCookie {
|
||||||
|
self.with_token_owner_record(realm_cookie, &realm_cookie.account.community_mint)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub async fn with_council_token_owner_record(
|
||||||
|
&mut self,
|
||||||
|
realm_cookie: &RealmCookie,
|
||||||
|
) -> TokenOwnerRecordCookie {
|
||||||
|
self.with_token_owner_record(
|
||||||
|
realm_cookie,
|
||||||
|
&realm_cookie.account.config.council_mint.unwrap(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub async fn with_token_owner_record(
|
||||||
|
&mut self,
|
||||||
|
realm_cookie: &RealmCookie,
|
||||||
|
governing_token_mint: &Pubkey,
|
||||||
) -> TokenOwnerRecordCookie {
|
) -> TokenOwnerRecordCookie {
|
||||||
let token_owner = Keypair::new();
|
let token_owner = Keypair::new();
|
||||||
|
|
||||||
|
@ -464,7 +537,7 @@ impl GovernanceProgramTest {
|
||||||
&self.program_id,
|
&self.program_id,
|
||||||
&realm_cookie.address,
|
&realm_cookie.address,
|
||||||
&token_owner.pubkey(),
|
&token_owner.pubkey(),
|
||||||
&realm_cookie.account.community_mint,
|
governing_token_mint,
|
||||||
&self.bench.payer.pubkey(),
|
&self.bench.payer.pubkey(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -476,7 +549,7 @@ impl GovernanceProgramTest {
|
||||||
let account = TokenOwnerRecordV2 {
|
let account = TokenOwnerRecordV2 {
|
||||||
account_type: GovernanceAccountType::TokenOwnerRecordV2,
|
account_type: GovernanceAccountType::TokenOwnerRecordV2,
|
||||||
realm: realm_cookie.address,
|
realm: realm_cookie.address,
|
||||||
governing_token_mint: realm_cookie.account.community_mint,
|
governing_token_mint: *governing_token_mint,
|
||||||
governing_token_owner: token_owner.pubkey(),
|
governing_token_owner: token_owner.pubkey(),
|
||||||
governing_token_deposit_amount: 0,
|
governing_token_deposit_amount: 0,
|
||||||
governance_delegate: None,
|
governance_delegate: None,
|
||||||
|
@ -490,7 +563,7 @@ impl GovernanceProgramTest {
|
||||||
let token_owner_record_address = get_token_owner_record_address(
|
let token_owner_record_address = get_token_owner_record_address(
|
||||||
&self.program_id,
|
&self.program_id,
|
||||||
&realm_cookie.address,
|
&realm_cookie.address,
|
||||||
&realm_cookie.account.community_mint,
|
governing_token_mint,
|
||||||
&token_owner.pubkey(),
|
&token_owner.pubkey(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -741,6 +814,73 @@ impl GovernanceProgramTest {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub async fn with_initial_governing_token_deposit_using_mint(
|
||||||
|
&mut self,
|
||||||
|
realm_address: &Pubkey,
|
||||||
|
governing_mint: &Pubkey,
|
||||||
|
governing_mint_authority: &Keypair,
|
||||||
|
amount: u64,
|
||||||
|
token_owner: Option<Keypair>,
|
||||||
|
) -> Result<TokenOwnerRecordCookie, ProgramError> {
|
||||||
|
let token_owner = token_owner.unwrap_or(Keypair::new());
|
||||||
|
let token_source = Keypair::new();
|
||||||
|
|
||||||
|
let deposit_governing_tokens_ix = deposit_governing_tokens(
|
||||||
|
&self.program_id,
|
||||||
|
realm_address,
|
||||||
|
governing_mint,
|
||||||
|
&token_owner.pubkey(),
|
||||||
|
&governing_mint_authority.pubkey(),
|
||||||
|
&self.bench.payer.pubkey(),
|
||||||
|
amount,
|
||||||
|
governing_mint,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.bench
|
||||||
|
.process_transaction(
|
||||||
|
&[deposit_governing_tokens_ix],
|
||||||
|
Some(&[&token_owner, &governing_mint_authority]),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let token_owner_record_address = get_token_owner_record_address(
|
||||||
|
&self.program_id,
|
||||||
|
realm_address,
|
||||||
|
governing_mint,
|
||||||
|
&token_owner.pubkey(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let account = TokenOwnerRecordV2 {
|
||||||
|
account_type: GovernanceAccountType::TokenOwnerRecordV2,
|
||||||
|
realm: *realm_address,
|
||||||
|
governing_token_mint: *governing_mint,
|
||||||
|
governing_token_owner: token_owner.pubkey(),
|
||||||
|
governing_token_deposit_amount: amount,
|
||||||
|
governance_delegate: None,
|
||||||
|
unrelinquished_votes_count: 0,
|
||||||
|
total_votes_count: 0,
|
||||||
|
outstanding_proposal_count: 0,
|
||||||
|
reserved: [0; 7],
|
||||||
|
reserved_v2: [0; 128],
|
||||||
|
};
|
||||||
|
|
||||||
|
let governance_delegate = Keypair::from_base58_string(&token_owner.to_base58_string());
|
||||||
|
|
||||||
|
Ok(TokenOwnerRecordCookie {
|
||||||
|
address: token_owner_record_address,
|
||||||
|
account,
|
||||||
|
|
||||||
|
token_source_amount: amount,
|
||||||
|
token_source: token_source.pubkey(),
|
||||||
|
token_owner,
|
||||||
|
governance_authority: None,
|
||||||
|
governance_delegate,
|
||||||
|
voter_weight_record: None,
|
||||||
|
max_voter_weight_record: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn mint_community_tokens(&mut self, realm_cookie: &RealmCookie, amount: u64) {
|
pub async fn mint_community_tokens(&mut self, realm_cookie: &RealmCookie, amount: u64) {
|
||||||
let token_account_keypair = Keypair::new();
|
let token_account_keypair = Keypair::new();
|
||||||
|
@ -974,14 +1114,9 @@ impl GovernanceProgramTest {
|
||||||
pub async fn set_realm_config(
|
pub async fn set_realm_config(
|
||||||
&mut self,
|
&mut self,
|
||||||
realm_cookie: &mut RealmCookie,
|
realm_cookie: &mut RealmCookie,
|
||||||
set_realm_config_args: &SetRealmConfigArgs,
|
realm_setup_args: &RealmSetupArgs,
|
||||||
) -> Result<(), ProgramError> {
|
) -> Result<(), ProgramError> {
|
||||||
self.set_realm_config_using_instruction(
|
self.set_realm_config_using_instruction(realm_cookie, realm_setup_args, NopOverride, None)
|
||||||
realm_cookie,
|
|
||||||
set_realm_config_args,
|
|
||||||
NopOverride,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -989,47 +1124,26 @@ impl GovernanceProgramTest {
|
||||||
pub async fn set_realm_config_using_instruction<F: Fn(&mut Instruction)>(
|
pub async fn set_realm_config_using_instruction<F: Fn(&mut Instruction)>(
|
||||||
&mut self,
|
&mut self,
|
||||||
realm_cookie: &mut RealmCookie,
|
realm_cookie: &mut RealmCookie,
|
||||||
set_realm_config_args: &SetRealmConfigArgs,
|
realm_setup_args: &RealmSetupArgs,
|
||||||
instruction_override: F,
|
instruction_override: F,
|
||||||
signers_override: Option<&[&Keypair]>,
|
signers_override: Option<&[&Keypair]>,
|
||||||
) -> Result<(), ProgramError> {
|
) -> Result<(), ProgramError> {
|
||||||
let council_token_mint = if set_realm_config_args.realm_config_args.use_council_mint {
|
let council_token_mint = if realm_setup_args.use_council_mint {
|
||||||
realm_cookie.account.config.council_mint
|
realm_cookie.account.config.council_mint
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let community_voter_weight_addin = if set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_community_voter_weight_addin
|
|
||||||
{
|
|
||||||
set_realm_config_args.community_voter_weight_addin
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let max_community_voter_weight_addin = if set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_max_community_voter_weight_addin
|
|
||||||
{
|
|
||||||
set_realm_config_args.max_community_voter_weight_addin
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut set_realm_config_ix = set_realm_config(
|
let mut set_realm_config_ix = set_realm_config(
|
||||||
&self.program_id,
|
&self.program_id,
|
||||||
&realm_cookie.address,
|
&realm_cookie.address,
|
||||||
&realm_cookie.realm_authority.as_ref().unwrap().pubkey(),
|
&realm_cookie.realm_authority.as_ref().unwrap().pubkey(),
|
||||||
council_token_mint,
|
council_token_mint,
|
||||||
&self.bench.payer.pubkey(),
|
&self.bench.payer.pubkey(),
|
||||||
community_voter_weight_addin,
|
Some(realm_setup_args.community_token_config_args.clone()),
|
||||||
max_community_voter_weight_addin,
|
Some(realm_setup_args.council_token_config_args.clone()),
|
||||||
set_realm_config_args
|
realm_setup_args.min_community_weight_to_create_governance,
|
||||||
.realm_config_args
|
realm_setup_args
|
||||||
.min_community_weight_to_create_governance,
|
|
||||||
set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.community_mint_max_vote_weight_source
|
.community_mint_max_vote_weight_source
|
||||||
.clone(),
|
.clone(),
|
||||||
);
|
);
|
||||||
|
@ -1043,32 +1157,44 @@ impl GovernanceProgramTest {
|
||||||
realm_cookie
|
realm_cookie
|
||||||
.account
|
.account
|
||||||
.config
|
.config
|
||||||
.community_mint_max_vote_weight_source = set_realm_config_args
|
.community_mint_max_vote_weight_source = realm_setup_args
|
||||||
.realm_config_args
|
|
||||||
.community_mint_max_vote_weight_source
|
.community_mint_max_vote_weight_source
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
if set_realm_config_args
|
realm_cookie.realm_config = RealmConfigCookie {
|
||||||
.realm_config_args
|
|
||||||
.use_community_voter_weight_addin
|
|
||||||
|| set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_max_community_voter_weight_addin
|
|
||||||
{
|
|
||||||
realm_cookie.realm_config = Some(RealmConfigCookie {
|
|
||||||
address: get_realm_config_address(&self.program_id, &realm_cookie.address),
|
address: get_realm_config_address(&self.program_id, &realm_cookie.address),
|
||||||
account: RealmConfigAccount {
|
account: RealmConfigAccount {
|
||||||
account_type: GovernanceAccountType::RealmConfig,
|
account_type: GovernanceAccountType::RealmConfig,
|
||||||
realm: realm_cookie.address,
|
realm: realm_cookie.address,
|
||||||
community_voter_weight_addin,
|
reserved: Reserved110::default(),
|
||||||
max_community_voter_weight_addin,
|
community_token_config: GoverningTokenConfig {
|
||||||
council_voter_weight_addin: None,
|
voter_weight_addin: realm_setup_args
|
||||||
council_max_vote_weight_addin: None,
|
.community_token_config_args
|
||||||
reserved: [0; 128],
|
.voter_weight_addin,
|
||||||
|
max_voter_weight_addin: realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.max_voter_weight_addin,
|
||||||
|
token_type: realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.token_type
|
||||||
|
.clone(),
|
||||||
|
reserved: [0; 8],
|
||||||
},
|
},
|
||||||
})
|
council_token_config: GoverningTokenConfig {
|
||||||
}
|
voter_weight_addin: realm_setup_args
|
||||||
|
.council_token_config_args
|
||||||
|
.voter_weight_addin,
|
||||||
|
max_voter_weight_addin: realm_setup_args
|
||||||
|
.council_token_config_args
|
||||||
|
.max_voter_weight_addin,
|
||||||
|
token_type: realm_setup_args
|
||||||
|
.council_token_config_args
|
||||||
|
.token_type
|
||||||
|
.clone(),
|
||||||
|
reserved: [0; 8],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
self.bench
|
self.bench
|
||||||
.process_transaction(&[set_realm_config_ix], Some(signers))
|
.process_transaction(&[set_realm_config_ix], Some(signers))
|
||||||
.await
|
.await
|
||||||
|
@ -1129,6 +1255,73 @@ impl GovernanceProgramTest {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub async fn revoke_community_tokens(
|
||||||
|
&mut self,
|
||||||
|
realm_cookie: &RealmCookie,
|
||||||
|
token_owner_record_cookie: &TokenOwnerRecordCookie,
|
||||||
|
) -> Result<(), ProgramError> {
|
||||||
|
self.revoke_governing_tokens_using_instruction(
|
||||||
|
realm_cookie,
|
||||||
|
token_owner_record_cookie,
|
||||||
|
&realm_cookie.account.community_mint,
|
||||||
|
token_owner_record_cookie
|
||||||
|
.account
|
||||||
|
.governing_token_deposit_amount,
|
||||||
|
NopOverride,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub async fn revoke_council_tokens(
|
||||||
|
&mut self,
|
||||||
|
realm_cookie: &RealmCookie,
|
||||||
|
token_owner_record_cookie: &TokenOwnerRecordCookie,
|
||||||
|
) -> Result<(), ProgramError> {
|
||||||
|
self.revoke_governing_tokens_using_instruction(
|
||||||
|
realm_cookie,
|
||||||
|
token_owner_record_cookie,
|
||||||
|
&realm_cookie.account.config.council_mint.unwrap(),
|
||||||
|
token_owner_record_cookie
|
||||||
|
.account
|
||||||
|
.governing_token_deposit_amount,
|
||||||
|
NopOverride,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub async fn revoke_governing_tokens_using_instruction<F: Fn(&mut Instruction)>(
|
||||||
|
&mut self,
|
||||||
|
realm_cookie: &RealmCookie,
|
||||||
|
token_owner_record_cookie: &TokenOwnerRecordCookie,
|
||||||
|
governing_token_mint: &Pubkey,
|
||||||
|
amount: u64,
|
||||||
|
instruction_override: F,
|
||||||
|
signers_override: Option<&[&Keypair]>,
|
||||||
|
) -> Result<(), ProgramError> {
|
||||||
|
let mut revoke_governing_tokens_ix = revoke_governing_tokens(
|
||||||
|
&self.program_id,
|
||||||
|
&realm_cookie.address,
|
||||||
|
&realm_cookie.account.authority.unwrap(),
|
||||||
|
&token_owner_record_cookie.account.governing_token_owner,
|
||||||
|
governing_token_mint,
|
||||||
|
amount,
|
||||||
|
);
|
||||||
|
|
||||||
|
instruction_override(&mut revoke_governing_tokens_ix);
|
||||||
|
|
||||||
|
let default_signers = &[realm_cookie.realm_authority.as_ref().unwrap()];
|
||||||
|
let signers = signers_override.unwrap_or(default_signers);
|
||||||
|
|
||||||
|
self.bench
|
||||||
|
.process_transaction(&[revoke_governing_tokens_ix], Some(signers))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn with_governed_account(&mut self) -> GovernedAccountCookie {
|
pub async fn with_governed_account(&mut self) -> GovernedAccountCookie {
|
||||||
GovernedAccountCookie {
|
GovernedAccountCookie {
|
||||||
|
@ -2157,13 +2350,31 @@ impl GovernanceProgramTest {
|
||||||
self.with_cast_vote(proposal_cookie, token_owner_record_cookie, vote)
|
self.with_cast_vote(proposal_cookie, token_owner_record_cookie, vote)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn with_cast_vote(
|
pub async fn with_cast_vote(
|
||||||
&mut self,
|
&mut self,
|
||||||
proposal_cookie: &ProposalCookie,
|
proposal_cookie: &ProposalCookie,
|
||||||
token_owner_record_cookie: &TokenOwnerRecordCookie,
|
token_owner_record_cookie: &TokenOwnerRecordCookie,
|
||||||
vote: Vote,
|
vote: Vote,
|
||||||
|
) -> Result<VoteRecordCookie, ProgramError> {
|
||||||
|
self.with_cast_vote_using_instruction(
|
||||||
|
proposal_cookie,
|
||||||
|
token_owner_record_cookie,
|
||||||
|
vote,
|
||||||
|
NopOverride,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub async fn with_cast_vote_using_instruction<F: Fn(&mut Instruction)>(
|
||||||
|
&mut self,
|
||||||
|
proposal_cookie: &ProposalCookie,
|
||||||
|
token_owner_record_cookie: &TokenOwnerRecordCookie,
|
||||||
|
vote: Vote,
|
||||||
|
instruction_override: F,
|
||||||
|
signers_override: Option<&[&Keypair]>,
|
||||||
) -> Result<VoteRecordCookie, ProgramError> {
|
) -> Result<VoteRecordCookie, ProgramError> {
|
||||||
let voter_weight_record =
|
let voter_weight_record =
|
||||||
if let Some(voter_weight_record) = &token_owner_record_cookie.voter_weight_record {
|
if let Some(voter_weight_record) = &token_owner_record_cookie.voter_weight_record {
|
||||||
|
@ -2180,7 +2391,7 @@ impl GovernanceProgramTest {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let cast_vote_ix = cast_vote(
|
let mut cast_vote_ix = cast_vote(
|
||||||
&self.program_id,
|
&self.program_id,
|
||||||
&token_owner_record_cookie.account.realm,
|
&token_owner_record_cookie.account.realm,
|
||||||
&proposal_cookie.account.governance,
|
&proposal_cookie.account.governance,
|
||||||
|
@ -2195,11 +2406,13 @@ impl GovernanceProgramTest {
|
||||||
vote.clone(),
|
vote.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
instruction_override(&mut cast_vote_ix);
|
||||||
|
|
||||||
|
let default_signers = &[&token_owner_record_cookie.token_owner];
|
||||||
|
let signers = signers_override.unwrap_or(default_signers);
|
||||||
|
|
||||||
self.bench
|
self.bench
|
||||||
.process_transaction(
|
.process_transaction(&[cast_vote_ix], Some(signers))
|
||||||
&[cast_vote_ix],
|
|
||||||
Some(&[&token_owner_record_cookie.token_owner]),
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let vote_amount = token_owner_record_cookie
|
let vote_amount = token_owner_record_cookie
|
||||||
|
@ -2628,7 +2841,7 @@ impl GovernanceProgramTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn get_realm_config_data(
|
pub async fn get_realm_config_account(
|
||||||
&mut self,
|
&mut self,
|
||||||
realm_config_address: &Pubkey,
|
realm_config_address: &Pubkey,
|
||||||
) -> RealmConfigAccount {
|
) -> RealmConfigAccount {
|
||||||
|
|
|
@ -7,36 +7,46 @@ mod program_test;
|
||||||
|
|
||||||
use program_test::*;
|
use program_test::*;
|
||||||
|
|
||||||
|
use crate::program_test::args::RealmSetupArgs;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_create_realm_with_all_addins() {
|
async fn test_create_realm_with_all_addins() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
||||||
|
|
||||||
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
|
realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.voter_weight_addin = governance_test.voter_weight_addin_id;
|
||||||
|
|
||||||
|
realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.max_voter_weight_addin = governance_test.max_voter_weight_addin_id;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_args(&realm_setup_args)
|
||||||
|
.await;
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
|
||||||
.get_realm_account(&realm_cookie.address)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(realm_account_data.config.use_community_voter_weight_addin);
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
realm_account_data
|
|
||||||
.config
|
|
||||||
.use_max_community_voter_weight_addin
|
|
||||||
);
|
|
||||||
|
|
||||||
let realm_config_cookie = realm_cookie.realm_config.unwrap();
|
|
||||||
|
|
||||||
let realm_config_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_config_data(&realm_config_cookie.address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert_eq!(realm_config_cookie.account, realm_config_data);
|
assert_eq!(realm_cookie.realm_config.account, realm_config_data);
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.voter_weight_addin
|
||||||
|
.is_some());
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.max_voter_weight_addin
|
||||||
|
.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -44,56 +54,44 @@ async fn test_set_all_addins_for_realm_without_addins() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
||||||
|
|
||||||
let mut set_realm_config_args = governance_test.get_default_set_realm_config_args();
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_max_community_voter_weight_addin = false;
|
|
||||||
|
|
||||||
set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_community_voter_weight_addin = false;
|
|
||||||
|
|
||||||
let mut realm_cookie = governance_test
|
let mut realm_cookie = governance_test
|
||||||
.with_realm_using_config_args(&set_realm_config_args)
|
.with_realm_using_args(&realm_setup_args)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_community_voter_weight_addin = true;
|
.voter_weight_addin = governance_test.voter_weight_addin_id;
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_max_community_voter_weight_addin = true;
|
.max_voter_weight_addin = governance_test.max_voter_weight_addin_id;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
|
||||||
.get_realm_account(&realm_cookie.address)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
realm_account_data
|
|
||||||
.config
|
|
||||||
.use_max_community_voter_weight_addin
|
|
||||||
);
|
|
||||||
|
|
||||||
assert!(realm_account_data.config.use_community_voter_weight_addin);
|
|
||||||
|
|
||||||
let realm_config_cookie = realm_cookie.realm_config.unwrap();
|
|
||||||
|
|
||||||
let realm_config_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_config_data(&realm_config_cookie.address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert_eq!(realm_config_cookie.account, realm_config_data);
|
assert_eq!(realm_cookie.realm_config.account, realm_config_data);
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.voter_weight_addin
|
||||||
|
.is_some());
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.max_voter_weight_addin
|
||||||
|
.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -101,58 +99,46 @@ async fn test_set_all_addin_for_realm_without_council_and_addins() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
||||||
|
|
||||||
let mut set_realm_config_args = governance_test.get_default_set_realm_config_args();
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args.use_council_mint = false;
|
||||||
.realm_config_args
|
|
||||||
.use_community_voter_weight_addin = false;
|
|
||||||
|
|
||||||
set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_max_community_voter_weight_addin = false;
|
|
||||||
|
|
||||||
set_realm_config_args.realm_config_args.use_council_mint = false;
|
|
||||||
|
|
||||||
let mut realm_cookie = governance_test
|
let mut realm_cookie = governance_test
|
||||||
.with_realm_using_config_args(&set_realm_config_args)
|
.with_realm_using_args(&realm_setup_args)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_max_community_voter_weight_addin = true;
|
.voter_weight_addin = governance_test.voter_weight_addin_id;
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_community_voter_weight_addin = true;
|
.max_voter_weight_addin = governance_test.max_voter_weight_addin_id;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
|
||||||
.get_realm_account(&realm_cookie.address)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
realm_account_data
|
|
||||||
.config
|
|
||||||
.use_max_community_voter_weight_addin
|
|
||||||
);
|
|
||||||
|
|
||||||
assert!(realm_account_data.config.use_community_voter_weight_addin);
|
|
||||||
|
|
||||||
let realm_config_cookie = realm_cookie.realm_config.unwrap();
|
|
||||||
|
|
||||||
let realm_config_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_config_data(&realm_config_cookie.address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert_eq!(realm_config_cookie.account, realm_config_data);
|
assert_eq!(realm_cookie.realm_config.account, realm_config_data);
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.voter_weight_addin
|
||||||
|
.is_some());
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.max_voter_weight_addin
|
||||||
|
.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -162,60 +148,61 @@ async fn test_set_all_realm_addins_for_realm_with_all_addins() {
|
||||||
|
|
||||||
let mut realm_cookie = governance_test.with_realm().await;
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
let mut set_realm_config_args = governance_test.get_default_set_realm_config_args();
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_max_community_voter_weight_addin = true;
|
.voter_weight_addin = governance_test.voter_weight_addin_id;
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_community_voter_weight_addin = true;
|
.max_voter_weight_addin = governance_test.max_voter_weight_addin_id;
|
||||||
|
|
||||||
let max_community_voter_weight_addin_address = Pubkey::new_unique();
|
let max_community_voter_weight_addin_address = Pubkey::new_unique();
|
||||||
|
|
||||||
set_realm_config_args.max_community_voter_weight_addin =
|
realm_setup_args
|
||||||
Some(max_community_voter_weight_addin_address);
|
.community_token_config_args
|
||||||
|
.max_voter_weight_addin = Some(max_community_voter_weight_addin_address);
|
||||||
|
|
||||||
let community_voter_weight_addin_address = Pubkey::new_unique();
|
let community_voter_weight_addin_address = Pubkey::new_unique();
|
||||||
set_realm_config_args.community_voter_weight_addin = Some(community_voter_weight_addin_address);
|
realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.voter_weight_addin = Some(community_voter_weight_addin_address);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
|
||||||
.get_realm_account(&realm_cookie.address)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
realm_account_data
|
|
||||||
.config
|
|
||||||
.use_max_community_voter_weight_addin
|
|
||||||
);
|
|
||||||
|
|
||||||
assert!(realm_account_data.config.use_community_voter_weight_addin);
|
|
||||||
|
|
||||||
let realm_config_cookie = realm_cookie.realm_config.unwrap();
|
|
||||||
|
|
||||||
let realm_config_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_config_data(&realm_config_cookie.address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert_eq!(realm_config_cookie.account, realm_config_data);
|
assert_eq!(realm_cookie.realm_config.account, realm_config_data);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
realm_config_data.max_community_voter_weight_addin,
|
realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.max_voter_weight_addin,
|
||||||
Some(max_community_voter_weight_addin_address)
|
Some(max_community_voter_weight_addin_address)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
realm_config_data.community_voter_weight_addin,
|
realm_config_data.community_token_config.voter_weight_addin,
|
||||||
Some(community_voter_weight_addin_address)
|
Some(community_voter_weight_addin_address)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.voter_weight_addin
|
||||||
|
.is_some());
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.max_voter_weight_addin
|
||||||
|
.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -223,48 +210,42 @@ async fn test_set_realm_config_without_addins_for_realm_without_addins() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
||||||
|
|
||||||
let mut set_realm_config_args = governance_test.get_default_set_realm_config_args();
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_max_community_voter_weight_addin = false;
|
|
||||||
|
|
||||||
set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_community_voter_weight_addin = false;
|
|
||||||
|
|
||||||
let mut realm_cookie = governance_test
|
let mut realm_cookie = governance_test
|
||||||
.with_realm_using_config_args(&set_realm_config_args)
|
.with_realm_using_args(&realm_setup_args)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_max_community_voter_weight_addin = false;
|
.max_voter_weight_addin = None;
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_community_voter_weight_addin = false;
|
.voter_weight_addin = None;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_account(&realm_cookie.address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert!(
|
assert!(realm_config_data
|
||||||
!realm_account_data
|
.community_token_config
|
||||||
.config
|
.voter_weight_addin
|
||||||
.use_max_community_voter_weight_addin
|
.is_none());
|
||||||
);
|
|
||||||
|
|
||||||
assert!(!realm_account_data.config.use_community_voter_weight_addin);
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.max_voter_weight_addin
|
||||||
|
.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -273,35 +254,28 @@ async fn test_set_realm_config_without_any_addins_for_realm_with_existing_addins
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
||||||
let mut realm_cookie = governance_test.with_realm().await;
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
let mut set_realm_config_args = governance_test.get_default_set_realm_config_args();
|
let realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_max_community_voter_weight_addin = false;
|
|
||||||
|
|
||||||
set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_community_voter_weight_addin = false;
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
|
||||||
.get_realm_account(&realm_cookie.address)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(!realm_account_data.config.use_community_voter_weight_addin);
|
|
||||||
|
|
||||||
let realm_config_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_config_data(&realm_cookie.realm_config.unwrap().address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert!(realm_config_data.max_community_voter_weight_addin.is_none());
|
assert!(realm_config_data
|
||||||
assert!(realm_config_data.community_voter_weight_addin.is_none());
|
.community_token_config
|
||||||
|
.max_voter_weight_addin
|
||||||
|
.is_none());
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.voter_weight_addin
|
||||||
|
.is_none());
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,34 +7,37 @@ mod program_test;
|
||||||
|
|
||||||
use program_test::*;
|
use program_test::*;
|
||||||
|
|
||||||
|
use crate::program_test::args::RealmSetupArgs;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_create_realm_with_max_voter_weight_addin() {
|
async fn test_create_realm_with_max_voter_weight_addin() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
||||||
|
|
||||||
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
|
realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.max_voter_weight_addin = governance_test.max_voter_weight_addin_id;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_args(&realm_setup_args)
|
||||||
|
.await;
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
|
||||||
.get_realm_account(&realm_cookie.address)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
realm_account_data
|
|
||||||
.config
|
|
||||||
.use_max_community_voter_weight_addin
|
|
||||||
);
|
|
||||||
|
|
||||||
let realm_config_cookie = realm_cookie.realm_config.unwrap();
|
|
||||||
|
|
||||||
let realm_config_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_config_data(&realm_config_cookie.address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert_eq!(realm_config_cookie.account, realm_config_data);
|
assert_eq!(realm_cookie.realm_config.account, realm_config_data);
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.max_voter_weight_addin
|
||||||
|
.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -42,50 +45,35 @@ async fn test_set_realm_max_voter_weight_addin_for_realm_without_addins() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
||||||
|
|
||||||
let mut set_realm_config_args = governance_test.get_default_set_realm_config_args();
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_max_community_voter_weight_addin = false;
|
|
||||||
|
|
||||||
set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_community_voter_weight_addin = false;
|
|
||||||
|
|
||||||
let mut realm_cookie = governance_test
|
let mut realm_cookie = governance_test
|
||||||
.with_realm_using_config_args(&set_realm_config_args)
|
.with_realm_using_args(&realm_setup_args)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_max_community_voter_weight_addin = true;
|
.max_voter_weight_addin = governance_test.max_voter_weight_addin_id;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
|
||||||
.get_realm_account(&realm_cookie.address)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
realm_account_data
|
|
||||||
.config
|
|
||||||
.use_max_community_voter_weight_addin
|
|
||||||
);
|
|
||||||
|
|
||||||
let realm_config_cookie = realm_cookie.realm_config.unwrap();
|
|
||||||
|
|
||||||
let realm_config_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_config_data(&realm_config_cookie.address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert_eq!(realm_config_cookie.account, realm_config_data);
|
assert_eq!(realm_cookie.realm_config.account, realm_config_data);
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.max_voter_weight_addin
|
||||||
|
.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -93,52 +81,37 @@ async fn test_set_realm_max_voter_weight_addin_for_realm_without_council_and_add
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
||||||
|
|
||||||
let mut set_realm_config_args = governance_test.get_default_set_realm_config_args();
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args.use_council_mint = false;
|
||||||
.realm_config_args
|
|
||||||
.use_community_voter_weight_addin = false;
|
|
||||||
|
|
||||||
set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_max_community_voter_weight_addin = false;
|
|
||||||
|
|
||||||
set_realm_config_args.realm_config_args.use_council_mint = false;
|
|
||||||
|
|
||||||
let mut realm_cookie = governance_test
|
let mut realm_cookie = governance_test
|
||||||
.with_realm_using_config_args(&set_realm_config_args)
|
.with_realm_using_args(&realm_setup_args)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_max_community_voter_weight_addin = true;
|
.max_voter_weight_addin = governance_test.max_voter_weight_addin_id;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
|
||||||
.get_realm_account(&realm_cookie.address)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
realm_account_data
|
|
||||||
.config
|
|
||||||
.use_max_community_voter_weight_addin
|
|
||||||
);
|
|
||||||
|
|
||||||
let realm_config_cookie = realm_cookie.realm_config.unwrap();
|
|
||||||
|
|
||||||
let realm_config_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_config_data(&realm_config_cookie.address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert_eq!(realm_config_cookie.account, realm_config_data);
|
assert_eq!(realm_cookie.realm_config.account, realm_config_data);
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.max_voter_weight_addin
|
||||||
|
.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -148,46 +121,42 @@ async fn test_set_realm_max_voter_weight_addin_for_realm_with_existing_voter_wei
|
||||||
|
|
||||||
let mut realm_cookie = governance_test.with_realm().await;
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
let mut set_realm_config_args = governance_test.get_default_set_realm_config_args();
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_max_community_voter_weight_addin = true;
|
.max_voter_weight_addin = governance_test.max_voter_weight_addin_id;
|
||||||
|
|
||||||
let max_community_voter_weight_addin_address = Pubkey::new_unique();
|
let max_community_voter_weight_addin_address = Pubkey::new_unique();
|
||||||
set_realm_config_args.max_community_voter_weight_addin =
|
realm_setup_args
|
||||||
Some(max_community_voter_weight_addin_address);
|
.community_token_config_args
|
||||||
|
.max_voter_weight_addin = Some(max_community_voter_weight_addin_address);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
|
||||||
.get_realm_account(&realm_cookie.address)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
realm_account_data
|
|
||||||
.config
|
|
||||||
.use_max_community_voter_weight_addin
|
|
||||||
);
|
|
||||||
|
|
||||||
let realm_config_cookie = realm_cookie.realm_config.unwrap();
|
|
||||||
|
|
||||||
let realm_config_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_config_data(&realm_config_cookie.address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert_eq!(realm_config_cookie.account, realm_config_data);
|
assert_eq!(realm_cookie.realm_config.account, realm_config_data);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
realm_config_data.max_community_voter_weight_addin,
|
realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.max_voter_weight_addin,
|
||||||
Some(max_community_voter_weight_addin_address)
|
Some(max_community_voter_weight_addin_address)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.max_voter_weight_addin
|
||||||
|
.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -195,38 +164,33 @@ async fn test_set_realm_config_with_no_max_voter_weight_addin_for_realm_without_
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
||||||
|
|
||||||
let mut set_realm_config_args = governance_test.get_default_set_realm_config_args();
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_max_community_voter_weight_addin = false;
|
|
||||||
|
|
||||||
let mut realm_cookie = governance_test
|
let mut realm_cookie = governance_test
|
||||||
.with_realm_using_config_args(&set_realm_config_args)
|
.with_realm_using_args(&realm_setup_args)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_max_community_voter_weight_addin = false;
|
.max_voter_weight_addin = None;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_account(&realm_cookie.address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert!(
|
assert!(realm_config_data
|
||||||
!realm_account_data
|
.community_token_config
|
||||||
.config
|
.max_voter_weight_addin
|
||||||
.use_max_community_voter_weight_addin
|
.is_none());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -235,30 +199,28 @@ async fn test_set_realm_config_with_no_max_voter_weight_addin_for_realm_with_exi
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
||||||
let mut realm_cookie = governance_test.with_realm().await;
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
let mut set_realm_config_args = governance_test.get_default_set_realm_config_args();
|
let realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
set_realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_max_community_voter_weight_addin = false;
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
|
||||||
.get_realm_account(&realm_cookie.address)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(!realm_account_data.config.use_community_voter_weight_addin);
|
|
||||||
|
|
||||||
let realm_config_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_config_data(&realm_cookie.realm_config.unwrap().address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert!(realm_config_data.max_community_voter_weight_addin.is_none());
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.max_voter_weight_addin
|
||||||
|
.is_none());
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.voter_weight_addin
|
||||||
|
.is_none());
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ use solana_program_test::*;
|
||||||
|
|
||||||
mod program_test;
|
mod program_test;
|
||||||
|
|
||||||
|
use crate::program_test::args::RealmSetupArgs;
|
||||||
use program_test::*;
|
use program_test::*;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -12,25 +13,30 @@ async fn test_create_realm_with_voter_weight_addin() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
|
|
||||||
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
|
realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.voter_weight_addin = governance_test.voter_weight_addin_id;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_args(&realm_setup_args)
|
||||||
|
.await;
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
|
||||||
.get_realm_account(&realm_cookie.address)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(realm_account_data.config.use_community_voter_weight_addin);
|
|
||||||
|
|
||||||
let realm_config_cookie = realm_cookie.realm_config.unwrap();
|
|
||||||
|
|
||||||
let realm_config_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_config_data(&realm_config_cookie.address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert_eq!(realm_config_cookie.account, realm_config_data);
|
assert_eq!(realm_cookie.realm_config.account, realm_config_data);
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.voter_weight_addin
|
||||||
|
.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -38,41 +44,38 @@ async fn test_set_realm_voter_weight_addin_for_realm_without_addins() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
|
|
||||||
let mut set_realm_config_args = governance_test.get_default_set_realm_config_args();
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
set_realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_community_voter_weight_addin = false;
|
.voter_weight_addin = None;
|
||||||
|
|
||||||
let mut realm_cookie = governance_test
|
let mut realm_cookie = governance_test
|
||||||
.with_realm_using_config_args(&set_realm_config_args)
|
.with_realm_using_args(&realm_setup_args)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_community_voter_weight_addin = true;
|
.voter_weight_addin = governance_test.voter_weight_addin_id;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
|
||||||
.get_realm_account(&realm_cookie.address)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(realm_account_data.config.use_community_voter_weight_addin);
|
|
||||||
|
|
||||||
let realm_config_cookie = realm_cookie.realm_config.unwrap();
|
|
||||||
|
|
||||||
let realm_config_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_config_data(&realm_config_cookie.address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert_eq!(realm_config_cookie.account, realm_config_data);
|
assert_eq!(realm_cookie.realm_config.account, realm_config_data);
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.voter_weight_addin
|
||||||
|
.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -80,42 +83,37 @@ async fn test_set_realm_voter_weight_addin_for_realm_without_council_and_addins(
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
|
|
||||||
let mut set_realm_config_args = governance_test.get_default_set_realm_config_args();
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
set_realm_config_args
|
|
||||||
.realm_config_args
|
realm_setup_args.use_council_mint = false;
|
||||||
.use_community_voter_weight_addin = false;
|
|
||||||
set_realm_config_args.realm_config_args.use_council_mint = false;
|
|
||||||
|
|
||||||
let mut realm_cookie = governance_test
|
let mut realm_cookie = governance_test
|
||||||
.with_realm_using_config_args(&set_realm_config_args)
|
.with_realm_using_args(&realm_setup_args)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
set_realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_community_voter_weight_addin = true;
|
.voter_weight_addin = governance_test.voter_weight_addin_id;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
|
||||||
.get_realm_account(&realm_cookie.address)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(realm_account_data.config.use_community_voter_weight_addin);
|
|
||||||
|
|
||||||
let realm_config_cookie = realm_cookie.realm_config.unwrap();
|
|
||||||
|
|
||||||
let realm_config_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_config_data(&realm_config_cookie.address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert_eq!(realm_config_cookie.account, realm_config_data);
|
assert_eq!(realm_cookie.realm_config.account, realm_config_data);
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.voter_weight_addin
|
||||||
|
.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -123,43 +121,44 @@ async fn test_set_realm_voter_weight_addin_for_realm_with_existing_voter_weight_
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
|
|
||||||
let mut realm_cookie = governance_test.with_realm().await;
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
|
|
||||||
let mut set_realm_config_args = governance_test.get_default_set_realm_config_args();
|
realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.voter_weight_addin = governance_test.voter_weight_addin_id;
|
||||||
|
|
||||||
set_realm_config_args
|
let mut realm_cookie = governance_test
|
||||||
.realm_config_args
|
.with_realm_using_args(&realm_setup_args)
|
||||||
.use_community_voter_weight_addin = true;
|
.await;
|
||||||
|
|
||||||
let community_voter_weight_addin_address = Pubkey::new_unique();
|
let community_voter_weight_addin_address = Pubkey::new_unique();
|
||||||
set_realm_config_args.community_voter_weight_addin = Some(community_voter_weight_addin_address);
|
realm_setup_args
|
||||||
|
.community_token_config_args
|
||||||
|
.voter_weight_addin = Some(community_voter_weight_addin_address);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
|
||||||
.get_realm_account(&realm_cookie.address)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(realm_account_data.config.use_community_voter_weight_addin);
|
|
||||||
|
|
||||||
let realm_config_cookie = realm_cookie.realm_config.unwrap();
|
|
||||||
|
|
||||||
let realm_config_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_config_data(&realm_config_cookie.address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert_eq!(realm_config_cookie.account, realm_config_data);
|
assert_eq!(realm_cookie.realm_config.account, realm_config_data);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
realm_config_data.community_voter_weight_addin,
|
realm_config_data.community_token_config.voter_weight_addin,
|
||||||
Some(community_voter_weight_addin_address)
|
Some(community_voter_weight_addin_address)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.voter_weight_addin
|
||||||
|
.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -167,33 +166,37 @@ async fn test_set_realm_config_with_no_voter_weight_addin_for_realm_without_addi
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
|
|
||||||
let mut realm_config_args = governance_test.get_default_set_realm_config_args();
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
realm_config_args
|
|
||||||
.realm_config_args
|
realm_setup_args
|
||||||
.use_community_voter_weight_addin = false;
|
.community_token_config_args
|
||||||
|
.voter_weight_addin = None;
|
||||||
|
|
||||||
let mut realm_cookie = governance_test
|
let mut realm_cookie = governance_test
|
||||||
.with_realm_using_config_args(&realm_config_args)
|
.with_realm_using_args(&realm_setup_args)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
realm_config_args
|
realm_setup_args
|
||||||
.realm_config_args
|
.community_token_config_args
|
||||||
.use_community_voter_weight_addin = false;
|
.voter_weight_addin = None;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_account(&realm_cookie.address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert!(!realm_account_data.config.use_community_voter_weight_addin);
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.voter_weight_addin
|
||||||
|
.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -202,29 +205,23 @@ async fn test_set_realm_config_with_no_voter_weight_addin_for_realm_with_existin
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
let mut realm_cookie = governance_test.with_realm().await;
|
let mut realm_cookie = governance_test.with_realm().await;
|
||||||
|
|
||||||
let mut realm_config_args = governance_test.get_default_set_realm_config_args();
|
let realm_setup_args = RealmSetupArgs::default();
|
||||||
realm_config_args
|
|
||||||
.realm_config_args
|
|
||||||
.use_community_voter_weight_addin = false;
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
let realm_account_data = governance_test
|
|
||||||
.get_realm_account(&realm_cookie.address)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(!realm_account_data.config.use_community_voter_weight_addin);
|
|
||||||
|
|
||||||
let realm_config_data = governance_test
|
let realm_config_data = governance_test
|
||||||
.get_realm_config_data(&realm_cookie.realm_config.unwrap().address)
|
.get_realm_config_account(&realm_cookie.realm_config.address)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert!(realm_config_data.community_voter_weight_addin.is_none());
|
assert!(realm_config_data
|
||||||
|
.community_token_config
|
||||||
|
.voter_weight_addin
|
||||||
|
.is_none());
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,15 +4,18 @@ use solana_program_test::*;
|
||||||
|
|
||||||
mod program_test;
|
mod program_test;
|
||||||
|
|
||||||
|
use program_test::args::*;
|
||||||
use program_test::*;
|
use program_test::*;
|
||||||
use spl_governance::state::enums::ProposalState;
|
use spl_governance::state::enums::ProposalState;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_cast_vote_with_all_addin() {
|
async fn test_cast_community_vote_with_all_addin() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::ALL)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
.with_community_token_owner_record(&realm_cookie)
|
.with_community_token_owner_record(&realm_cookie)
|
||||||
|
@ -67,12 +70,76 @@ async fn test_cast_vote_with_all_addin() {
|
||||||
assert_eq!(proposal_account.state, ProposalState::Voting)
|
assert_eq!(proposal_account.state, ProposalState::Voting)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_cast_council_vote_with_all_addin() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::ALL)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let mut token_owner_record_cookie = governance_test
|
||||||
|
.with_council_token_owner_record(&realm_cookie)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// voter weight 120
|
||||||
|
governance_test
|
||||||
|
.with_voter_weight_addin_record(&mut token_owner_record_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// max voter weight 250
|
||||||
|
governance_test
|
||||||
|
.with_max_voter_weight_addin_record_impl(&mut token_owner_record_cookie, 250, None)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
|
let mut governance_cookie = governance_test
|
||||||
|
.with_governance(
|
||||||
|
&realm_cookie,
|
||||||
|
&governed_account_cookie,
|
||||||
|
&token_owner_record_cookie,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let proposal_cookie = governance_test
|
||||||
|
.with_signed_off_proposal(&token_owner_record_cookie, &mut governance_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
|
||||||
|
let vote_record_cookie = governance_test
|
||||||
|
.with_cast_yes_no_vote(&proposal_cookie, &token_owner_record_cookie, YesNoVote::Yes)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
let vote_record_account = governance_test
|
||||||
|
.get_vote_record_account(&vote_record_cookie.address)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(120, vote_record_account.voter_weight);
|
||||||
|
|
||||||
|
let proposal_account = governance_test
|
||||||
|
.get_proposal_account(&proposal_cookie.address)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(proposal_account.state, ProposalState::Voting)
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_tip_vote_with_all_addin() {
|
async fn test_tip_vote_with_all_addin() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::ALL)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
.with_community_token_owner_record(&realm_cookie)
|
.with_community_token_owner_record(&realm_cookie)
|
||||||
|
@ -132,7 +199,9 @@ async fn test_finalize_vote_with_all_addin() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
let mut governance_test = GovernanceProgramTest::start_with_all_addins().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::ALL)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
.with_community_token_owner_record(&realm_cookie)
|
.with_community_token_owner_record(&realm_cookie)
|
||||||
|
|
|
@ -4,16 +4,19 @@ use solana_program_test::*;
|
||||||
|
|
||||||
mod program_test;
|
mod program_test;
|
||||||
|
|
||||||
|
use program_test::args::*;
|
||||||
use program_test::*;
|
use program_test::*;
|
||||||
use spl_governance::{error::GovernanceError, state::enums::ProposalState};
|
use spl_governance::{error::GovernanceError, state::enums::ProposalState};
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_cast_vote_with_max_voter_weight_addin() {
|
async fn test_cast_vote_with_community_max_voter_weight_addin() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
||||||
let governed_account_cookie = governance_test.with_governed_account().await;
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_MAX_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
// TokenOwnerRecord with voting power of 100
|
// TokenOwnerRecord with voting power of 100
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
|
@ -56,13 +59,66 @@ async fn test_cast_vote_with_max_voter_weight_addin() {
|
||||||
assert_eq!(proposal_account.state, ProposalState::Voting)
|
assert_eq!(proposal_account.state, ProposalState::Voting)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_cast_vote_with_council_max_voter_weight_addin() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
||||||
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COUNCIL_MAX_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// TokenOwnerRecord with voting power of 100
|
||||||
|
let mut token_owner_record_cookie = governance_test
|
||||||
|
.with_council_token_deposit(&realm_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Bump MaxVoterWeight to 200
|
||||||
|
governance_test
|
||||||
|
.with_max_voter_weight_addin_record(&mut token_owner_record_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut governance_cookie = governance_test
|
||||||
|
.with_governance(
|
||||||
|
&realm_cookie,
|
||||||
|
&governed_account_cookie,
|
||||||
|
&token_owner_record_cookie,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let proposal_cookie = governance_test
|
||||||
|
.with_signed_off_proposal(&token_owner_record_cookie, &mut governance_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
governance_test
|
||||||
|
.with_cast_yes_no_vote(&proposal_cookie, &token_owner_record_cookie, YesNoVote::Yes)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
let proposal_account = governance_test
|
||||||
|
.get_proposal_account(&proposal_cookie.address)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(proposal_account.state, ProposalState::Voting)
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_tip_vote_with_max_voter_weight_addin() {
|
async fn test_tip_vote_with_max_voter_weight_addin() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
||||||
let governed_account_cookie = governance_test.with_governed_account().await;
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_MAX_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
// TokenOwnerRecord with voting power of 180
|
// TokenOwnerRecord with voting power of 180
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
|
@ -112,7 +168,9 @@ async fn test_tip_vote_with_max_voter_weight_addin_and_max_below_total_cast_vote
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
||||||
let governed_account_cookie = governance_test.with_governed_account().await;
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_MAX_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
// TokenOwnerRecord with voting power of 100
|
// TokenOwnerRecord with voting power of 100
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
|
@ -162,7 +220,9 @@ async fn test_finalize_vote_with_max_voter_weight_addin() {
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
||||||
let governed_account_cookie = governance_test.with_governed_account().await;
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_MAX_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
// TokenOwnerRecord with voting power of 100
|
// TokenOwnerRecord with voting power of 100
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
|
@ -233,7 +293,9 @@ async fn test_finalize_vote_with_max_voter_weight_addin_and_max_below_total_cast
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
||||||
let governed_account_cookie = governance_test.with_governed_account().await;
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_MAX_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
// TokenOwnerRecord with voting power of 100
|
// TokenOwnerRecord with voting power of 100
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
|
@ -304,7 +366,9 @@ async fn test_cast_vote_with_max_voter_weight_addin_and_expired_record_error() {
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_max_voter_weight_addin().await;
|
||||||
let governed_account_cookie = governance_test.with_governed_account().await;
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_MAX_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
// TokenOwnerRecord with voting power of 100
|
// TokenOwnerRecord with voting power of 100
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
|
|
|
@ -5,7 +5,9 @@ use solana_program_test::*;
|
||||||
|
|
||||||
mod program_test;
|
mod program_test;
|
||||||
|
|
||||||
|
use program_test::args::*;
|
||||||
use program_test::*;
|
use program_test::*;
|
||||||
|
|
||||||
use spl_governance::{
|
use spl_governance::{
|
||||||
error::GovernanceError,
|
error::GovernanceError,
|
||||||
state::vote_record::{Vote, VoteChoice},
|
state::vote_record::{Vote, VoteChoice},
|
||||||
|
@ -13,12 +15,14 @@ use spl_governance::{
|
||||||
use spl_governance_addin_api::voter_weight::VoterWeightAction;
|
use spl_governance_addin_api::voter_weight::VoterWeightAction;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_create_governance_with_voter_weight_addin() {
|
async fn test_create_governance_with_community_voter_weight_addin() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
let governed_account_cookie = governance_test.with_governed_account().await;
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
.with_community_token_owner_record(&realm_cookie)
|
.with_community_token_owner_record(&realm_cookie)
|
||||||
|
@ -47,13 +51,52 @@ async fn test_create_governance_with_voter_weight_addin() {
|
||||||
assert_eq!(governance_cookie.account, governance_account);
|
assert_eq!(governance_cookie.account, governance_account);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_create_governance_with_council_voter_weight_addin() {
|
||||||
|
// Arrange
|
||||||
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COUNCIL_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let mut token_owner_record_cookie = governance_test
|
||||||
|
.with_council_token_owner_record(&realm_cookie)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
governance_test
|
||||||
|
.with_voter_weight_addin_record(&mut token_owner_record_cookie)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
let governance_cookie = governance_test
|
||||||
|
.with_governance(
|
||||||
|
&realm_cookie,
|
||||||
|
&governed_account_cookie,
|
||||||
|
&token_owner_record_cookie,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// // Assert
|
||||||
|
let governance_account = governance_test
|
||||||
|
.get_governance_account(&governance_cookie.address)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_eq!(governance_cookie.account, governance_account);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_create_proposal_with_voter_weight_addin() {
|
async fn test_create_proposal_with_voter_weight_addin() {
|
||||||
// Arrange
|
// Arrange
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
let governed_account_cookie = governance_test.with_governed_account().await;
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
.with_community_token_owner_record(&realm_cookie)
|
.with_community_token_owner_record(&realm_cookie)
|
||||||
|
@ -93,7 +136,9 @@ async fn test_cast_vote_with_voter_weight_addin() {
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
let governed_account_cookie = governance_test.with_governed_account().await;
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
.with_community_token_owner_record(&realm_cookie)
|
.with_community_token_owner_record(&realm_cookie)
|
||||||
|
@ -152,7 +197,9 @@ async fn test_create_token_governance_with_voter_weight_addin() {
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
let governed_token_cookie = governance_test.with_governed_token().await;
|
let governed_token_cookie = governance_test.with_governed_token().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
.with_community_token_owner_record(&realm_cookie)
|
.with_community_token_owner_record(&realm_cookie)
|
||||||
|
@ -187,7 +234,9 @@ async fn test_create_mint_governance_with_voter_weight_addin() {
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
let governed_mint_cookie = governance_test.with_governed_mint().await;
|
let governed_mint_cookie = governance_test.with_governed_mint().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
.with_community_token_owner_record(&realm_cookie)
|
.with_community_token_owner_record(&realm_cookie)
|
||||||
|
@ -222,7 +271,9 @@ async fn test_create_program_governance_with_voter_weight_addin() {
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
let governed_program_cookie = governance_test.with_governed_program().await;
|
let governed_program_cookie = governance_test.with_governed_program().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
.with_community_token_owner_record(&realm_cookie)
|
.with_community_token_owner_record(&realm_cookie)
|
||||||
|
@ -260,7 +311,9 @@ async fn test_create_governance_with_voter_weight_action_error() {
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
let governed_account_cookie = governance_test.with_governed_account().await;
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
.with_community_token_owner_record(&realm_cookie)
|
.with_community_token_owner_record(&realm_cookie)
|
||||||
|
@ -298,7 +351,9 @@ async fn test_create_governance_with_voter_weight_expiry_error() {
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
let governed_account_cookie = governance_test.with_governed_account().await;
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
.with_community_token_owner_record(&realm_cookie)
|
.with_community_token_owner_record(&realm_cookie)
|
||||||
|
@ -338,7 +393,9 @@ async fn test_cast_vote_with_voter_weight_action_error() {
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
let governed_account_cookie = governance_test.with_governed_account().await;
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
.with_community_token_owner_record(&realm_cookie)
|
.with_community_token_owner_record(&realm_cookie)
|
||||||
|
@ -394,7 +451,9 @@ async fn test_create_governance_with_voter_weight_action_target_error() {
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
let governed_account_cookie = governance_test.with_governed_account().await;
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
.with_community_token_owner_record(&realm_cookie)
|
.with_community_token_owner_record(&realm_cookie)
|
||||||
|
@ -437,7 +496,9 @@ async fn test_create_proposal_with_voter_weight_action_error() {
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
let governed_account_cookie = governance_test.with_governed_account().await;
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
.with_community_token_owner_record(&realm_cookie)
|
.with_community_token_owner_record(&realm_cookie)
|
||||||
|
@ -481,7 +542,9 @@ async fn test_create_governance_with_voter_weight_record() {
|
||||||
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
let mut governance_test = GovernanceProgramTest::start_with_voter_weight_addin().await;
|
||||||
let governed_account_cookie = governance_test.with_governed_account().await;
|
let governed_account_cookie = governance_test.with_governed_account().await;
|
||||||
|
|
||||||
let realm_cookie = governance_test.with_realm().await;
|
let realm_cookie = governance_test
|
||||||
|
.with_realm_using_addins(PluginSetupArgs::COMMUNITY_VOTER_WEIGHT)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut token_owner_record_cookie = governance_test
|
let mut token_owner_record_cookie = governance_test
|
||||||
.with_community_token_owner_record(&realm_cookie)
|
.with_community_token_owner_record(&realm_cookie)
|
||||||
|
|
|
@ -15,7 +15,7 @@ use spl_governance::{
|
||||||
};
|
};
|
||||||
use spl_governance_test_sdk::tools::clone_keypair;
|
use spl_governance_test_sdk::tools::clone_keypair;
|
||||||
|
|
||||||
use self::args::SetRealmConfigArgs;
|
use crate::program_test::args::RealmSetupArgs;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_cast_veto_vote() {
|
async fn test_cast_veto_vote() {
|
||||||
|
@ -431,11 +431,11 @@ async fn test_cast_veto_vote_with_no_council_error() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Remove Council
|
// Remove Council
|
||||||
let mut set_realm_config_args = SetRealmConfigArgs::default();
|
let mut realm_setup_args = RealmSetupArgs::default();
|
||||||
set_realm_config_args.realm_config_args.use_council_mint = false;
|
realm_setup_args.use_council_mint = false;
|
||||||
|
|
||||||
governance_test
|
governance_test
|
||||||
.set_realm_config(&mut realm_cookie, &set_realm_config_args)
|
.set_realm_config(&mut realm_cookie, &realm_setup_args)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue