From decdd1230c71bcadc363c7e4f0f82a7fdc8d0b83 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Thu, 9 Dec 2021 08:22:22 +0100 Subject: [PATCH] Address unaligned references, add padding - Make Registrar zero-copy. While it was using borsh for serialization, the array of voting mint configs couldn't be serialized without unaligned references. - Reorganize all zero_copy fields such that switching to repr(C) would not make a difference. (just for safety in case that happens) - Add static asserts on the sizes of all account structs, so any changes are visible very early. - Add padding to structs that didn't have it yet. --- Cargo.lock | 1 + programs/voter-stake-registry/Cargo.toml | 1 + .../src/instructions/clawback.rs | 4 ++-- .../src/instructions/configure_voting_mint.rs | 5 ++-- .../src/instructions/create_deposit_entry.rs | 4 ++-- .../src/instructions/create_registrar.rs | 4 ++-- .../src/instructions/create_voter.rs | 4 ++-- .../src/instructions/deposit.rs | 10 ++++---- .../src/instructions/grant.rs | 10 ++++---- .../src/instructions/reset_lockup.rs | 4 ++-- .../src/instructions/set_time_offset.rs | 4 ++-- .../instructions/update_max_vote_weight.rs | 4 ++-- .../update_voter_weight_record.rs | 8 +++---- .../src/instructions/withdraw.rs | 14 ++++++----- programs/voter-stake-registry/src/lib.rs | 3 +++ .../src/state/deposit_entry.rs | 18 ++++++++------ .../voter-stake-registry/src/state/lockup.rs | 24 +++++++++++-------- .../src/state/registrar.rs | 6 +++-- .../voter-stake-registry/src/state/voter.rs | 4 +++- .../src/state/voting_mint_config.rs | 14 +++++++---- 20 files changed, 87 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a0ee481..249447f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3223,6 +3223,7 @@ dependencies = [ "spl-associated-token-account", "spl-governance", "spl-token 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions", ] [[package]] diff --git a/programs/voter-stake-registry/Cargo.toml b/programs/voter-stake-registry/Cargo.toml index ef8e718..af6466e 100644 --- a/programs/voter-stake-registry/Cargo.toml +++ b/programs/voter-stake-registry/Cargo.toml @@ -27,6 +27,7 @@ anchor-spl = { git = "https://github.com/microwavedcola1/anchor.git", branch = " # programs/voter-stake-registry/tests/fixtures/spl_governance.so is built from. spl-governance = { git = "https://github.com/solana-labs/solana-program-library", rev = "75ddd9bb229396427977fb679a0763630e83bce6", features = ["no-entrypoint"] } solana-program = "^1.8.1" +static_assertions = "1.1" [dev-dependencies] solana-sdk = "^1.8.1" diff --git a/programs/voter-stake-registry/src/instructions/clawback.rs b/programs/voter-stake-registry/src/instructions/clawback.rs index 3b8ef29..293733b 100644 --- a/programs/voter-stake-registry/src/instructions/clawback.rs +++ b/programs/voter-stake-registry/src/instructions/clawback.rs @@ -7,7 +7,7 @@ use anchor_spl::token::{Token, TokenAccount}; #[derive(Accounts)] pub struct Clawback<'info> { #[account(has_one = clawback_authority)] - pub registrar: Box>, + pub registrar: AccountLoader<'info, Registrar>, pub clawback_authority: Signer<'info>, // checking the PDA address it just an extra precaution, @@ -65,7 +65,7 @@ impl<'info> Clawback<'info> { /// that have already vested in place. pub fn clawback(ctx: Context, deposit_entry_index: u8) -> Result<()> { // Load the accounts. - let registrar = &ctx.accounts.registrar; + let registrar = &ctx.accounts.registrar.load()?; let voter = &mut ctx.accounts.voter.load_mut()?; let deposit_entry = voter.active_deposit_mut(deposit_entry_index)?; require!( diff --git a/programs/voter-stake-registry/src/instructions/configure_voting_mint.rs b/programs/voter-stake-registry/src/instructions/configure_voting_mint.rs index 1198833..5d0c295 100644 --- a/programs/voter-stake-registry/src/instructions/configure_voting_mint.rs +++ b/programs/voter-stake-registry/src/instructions/configure_voting_mint.rs @@ -9,7 +9,7 @@ use anchor_spl::token::{Mint, Token, TokenAccount}; #[derive(Accounts)] pub struct ConfigureVotingMint<'info> { #[account(mut, has_one = realm_authority)] - pub registrar: Box>, + pub registrar: AccountLoader<'info, Registrar>, pub realm_authority: Signer<'info>, /// Token account that all funds for this mint will be stored in @@ -91,7 +91,7 @@ pub fn configure_voting_mint( grant_authority: Option, ) -> Result<()> { require!(lockup_saturation_secs > 0, LockupSaturationMustBePositive); - let registrar = &mut ctx.accounts.registrar; + let registrar = &mut ctx.accounts.registrar.load_mut()?; require!( (idx as usize) < registrar.voting_mints.len(), OutOfBoundsVotingMintConfigIndex @@ -107,6 +107,7 @@ pub fn configure_voting_mint( lockup_scaled_factor, lockup_saturation_secs, grant_authority: grant_authority.unwrap_or(Pubkey::new_from_array([0; 32])), + padding: [0; 31], }; // Check for overflow in vote weight diff --git a/programs/voter-stake-registry/src/instructions/create_deposit_entry.rs b/programs/voter-stake-registry/src/instructions/create_deposit_entry.rs index 83b057a..deaf375 100644 --- a/programs/voter-stake-registry/src/instructions/create_deposit_entry.rs +++ b/programs/voter-stake-registry/src/instructions/create_deposit_entry.rs @@ -5,7 +5,7 @@ use anchor_spl::token::Mint; #[derive(Accounts)] pub struct CreateDepositEntry<'info> { - pub registrar: Box>, + pub registrar: AccountLoader<'info, Registrar>, // checking the PDA address it just an extra precaution, // the other constraints must be exhaustive @@ -39,7 +39,7 @@ pub fn create_deposit_entry( allow_clawback: bool, ) -> Result<()> { // Load accounts. - let registrar = &ctx.accounts.registrar; + let registrar = &ctx.accounts.registrar.load()?; let voter = &mut ctx.accounts.voter.load_mut()?; // Get the exchange rate entry associated with this deposit. diff --git a/programs/voter-stake-registry/src/instructions/create_registrar.rs b/programs/voter-stake-registry/src/instructions/create_registrar.rs index aeea833..93efbae 100644 --- a/programs/voter-stake-registry/src/instructions/create_registrar.rs +++ b/programs/voter-stake-registry/src/instructions/create_registrar.rs @@ -17,7 +17,7 @@ pub struct CreateRegistrar<'info> { payer = payer, space = 8 + size_of::() )] - pub registrar: Box>, + pub registrar: AccountLoader<'info, Registrar>, /// An spl-governance realm /// @@ -52,7 +52,7 @@ pub struct CreateRegistrar<'info> { /// To use the registrar, call ConfigVotingMint to register token mints that may be /// used for voting. pub fn create_registrar(ctx: Context, registrar_bump: u8) -> Result<()> { - let registrar = &mut ctx.accounts.registrar; + let registrar = &mut ctx.accounts.registrar.load_init()?; registrar.bump = registrar_bump; registrar.governance_program_id = ctx.accounts.governance_program_id.key(); registrar.realm = ctx.accounts.realm.key(); diff --git a/programs/voter-stake-registry/src/instructions/create_voter.rs b/programs/voter-stake-registry/src/instructions/create_voter.rs index 427bc60..48e3f26 100644 --- a/programs/voter-stake-registry/src/instructions/create_voter.rs +++ b/programs/voter-stake-registry/src/instructions/create_voter.rs @@ -8,7 +8,7 @@ use std::mem::size_of; #[derive(Accounts)] #[instruction(voter_bump: u8, voter_weight_record_bump: u8)] pub struct CreateVoter<'info> { - pub registrar: Box>, + pub registrar: AccountLoader<'info, Registrar>, #[account( init_if_needed, @@ -78,7 +78,7 @@ pub fn create_voter( } // Load accounts. - let registrar = &ctx.accounts.registrar; + let registrar = &ctx.accounts.registrar.load()?; let voter_authority = ctx.accounts.voter_authority.key(); // Init the voter if is hasn't been already. diff --git a/programs/voter-stake-registry/src/instructions/deposit.rs b/programs/voter-stake-registry/src/instructions/deposit.rs index d12024b..519de8f 100644 --- a/programs/voter-stake-registry/src/instructions/deposit.rs +++ b/programs/voter-stake-registry/src/instructions/deposit.rs @@ -6,7 +6,7 @@ use std::convert::TryFrom; #[derive(Accounts)] pub struct Deposit<'info> { - pub registrar: Box>, + pub registrar: AccountLoader<'info, Registrar>, // checking the PDA address it just an extra precaution, // the other constraints must be exhaustive @@ -59,7 +59,7 @@ pub fn deposit(ctx: Context, deposit_entry_index: u8, amount: u64) -> R return Ok(()); } - let registrar = &ctx.accounts.registrar; + let registrar = &ctx.accounts.registrar.load()?; let voter = &mut ctx.accounts.voter.load_mut()?; let d_entry = voter.active_deposit_mut(deposit_entry_index)?; @@ -101,13 +101,15 @@ pub fn deposit(ctx: Context, deposit_entry_index: u8, amount: u64) -> R d_entry.amount_deposited_native += amount; d_entry.amount_initially_locked_native += amount; + let start_ts = d_entry.lockup.start_ts; + let end_ts = d_entry.lockup.end_ts; msg!( "Deposited amount {} at deposit index {} with lockup kind {:?}, and start ts {}, end ts {}", amount, deposit_entry_index, d_entry.lockup.kind, - d_entry.lockup.start_ts, - d_entry.lockup.end_ts, + start_ts, + end_ts, ); Ok(()) diff --git a/programs/voter-stake-registry/src/instructions/grant.rs b/programs/voter-stake-registry/src/instructions/grant.rs index 9089644..10e17a2 100644 --- a/programs/voter-stake-registry/src/instructions/grant.rs +++ b/programs/voter-stake-registry/src/instructions/grant.rs @@ -16,7 +16,7 @@ use std::mem::size_of; amount: u64, )] pub struct Grant<'info> { - pub registrar: Box>, + pub registrar: AccountLoader<'info, Registrar>, #[account( init_if_needed, @@ -89,7 +89,7 @@ pub fn grant( amount: u64, ) -> Result<()> { // Load accounts. - let registrar = &ctx.accounts.registrar; + let registrar = &ctx.accounts.registrar.load()?; let voter_authority = ctx.accounts.voter_authority.key(); // Get the exchange rate entry associated with this deposit. @@ -145,13 +145,15 @@ pub fn grant( d_entry.amount_deposited_native = amount; d_entry.amount_initially_locked_native = amount; + let start_ts = d_entry.lockup.start_ts; + let end_ts = d_entry.lockup.end_ts; msg!( "Granted amount {} at deposit index {} with lockup kind {:?}, and start ts {}, end ts {}", amount, free_entry_idx, d_entry.lockup.kind, - d_entry.lockup.start_ts, - d_entry.lockup.end_ts, + start_ts, + end_ts, ); Ok(()) diff --git a/programs/voter-stake-registry/src/instructions/reset_lockup.rs b/programs/voter-stake-registry/src/instructions/reset_lockup.rs index af2f364..00d9309 100644 --- a/programs/voter-stake-registry/src/instructions/reset_lockup.rs +++ b/programs/voter-stake-registry/src/instructions/reset_lockup.rs @@ -6,7 +6,7 @@ use anchor_lang::prelude::*; pub struct ResetLockup<'info> { // checking the PDA address it just an extra precaution, // the other constraints must be exhaustive - pub registrar: Box>, + pub registrar: AccountLoader<'info, Registrar>, #[account( mut, seeds = [registrar.key().as_ref(), b"voter".as_ref(), voter_authority.key().as_ref()], @@ -25,7 +25,7 @@ pub fn reset_lockup( deposit_entry_index: u8, periods: u32, ) -> Result<()> { - let registrar = &ctx.accounts.registrar; + let registrar = &ctx.accounts.registrar.load()?; let voter = &mut ctx.accounts.voter.load_mut()?; let d = voter.active_deposit_mut(deposit_entry_index)?; diff --git a/programs/voter-stake-registry/src/instructions/set_time_offset.rs b/programs/voter-stake-registry/src/instructions/set_time_offset.rs index 951f9fd..5259a42 100644 --- a/programs/voter-stake-registry/src/instructions/set_time_offset.rs +++ b/programs/voter-stake-registry/src/instructions/set_time_offset.rs @@ -7,14 +7,14 @@ use std::str::FromStr; #[instruction(time_offset: i64)] pub struct SetTimeOffset<'info> { #[account(mut, has_one = realm_authority)] - pub registrar: Box>, + pub registrar: AccountLoader<'info, Registrar>, pub realm_authority: Signer<'info>, } /// A debug-only instruction that advances the time. pub fn set_time_offset(ctx: Context, time_offset: i64) -> Result<()> { let allowed_program = Pubkey::from_str("GovernanceProgram11111111111111111111111111").unwrap(); - let registrar = &mut ctx.accounts.registrar; + let registrar = &mut ctx.accounts.registrar.load_mut()?; require!( registrar.governance_program_id == allowed_program, ErrorCode::DebugInstruction diff --git a/programs/voter-stake-registry/src/instructions/update_max_vote_weight.rs b/programs/voter-stake-registry/src/instructions/update_max_vote_weight.rs index c5ac98c..b5ebb6e 100644 --- a/programs/voter-stake-registry/src/instructions/update_max_vote_weight.rs +++ b/programs/voter-stake-registry/src/instructions/update_max_vote_weight.rs @@ -6,7 +6,7 @@ use anchor_lang::prelude::*; // exchange rates. #[derive(Accounts)] pub struct UpdateMaxVoteWeight<'info> { - pub registrar: Box>, + pub registrar: AccountLoader<'info, Registrar>, // TODO: SPL governance has not yet implemented this. pub max_vote_weight_record: UncheckedAccount<'info>, } @@ -19,7 +19,7 @@ pub struct UpdateMaxVoteWeight<'info> { /// all tokens fits into a u64 *after* converting into common decimals, as /// defined by the registrar's `rate_decimal` field. pub fn update_max_vote_weight<'info>(ctx: Context) -> Result<()> { - let registrar = &ctx.accounts.registrar; + let registrar = &ctx.accounts.registrar.load()?; let _max_vote_weight = registrar.max_vote_weight(ctx.remaining_accounts)?; // TODO: SPL governance has not yet implemented this feature. // When it has, probably need to write the result into an account, diff --git a/programs/voter-stake-registry/src/instructions/update_voter_weight_record.rs b/programs/voter-stake-registry/src/instructions/update_voter_weight_record.rs index fd060c4..71c4d13 100644 --- a/programs/voter-stake-registry/src/instructions/update_voter_weight_record.rs +++ b/programs/voter-stake-registry/src/instructions/update_voter_weight_record.rs @@ -4,7 +4,7 @@ use anchor_lang::prelude::*; #[derive(Accounts)] pub struct UpdateVoterWeightRecord<'info> { - pub registrar: Box>, + pub registrar: AccountLoader<'info, Registrar>, // checking the PDA address it just an extra precaution, // the other constraints must be exhaustive @@ -18,9 +18,9 @@ pub struct UpdateVoterWeightRecord<'info> { mut, seeds = [registrar.key().as_ref(), b"voter-weight-record".as_ref(), voter.load()?.voter_authority.key().as_ref()], bump = voter.load()?.voter_weight_record_bump, - constraint = voter_weight_record.realm == registrar.realm, + constraint = voter_weight_record.realm == registrar.load()?.realm, constraint = voter_weight_record.governing_token_owner == voter.load()?.voter_authority, - constraint = voter_weight_record.governing_token_mint == registrar.realm_governing_token_mint, + constraint = voter_weight_record.governing_token_mint == registrar.load()?.realm_governing_token_mint, )] pub voter_weight_record: Account<'info, VoterWeightRecord>, @@ -34,7 +34,7 @@ pub struct UpdateVoterWeightRecord<'info> { /// This "revise" instruction must be called immediately before voting, in /// the same transaction. pub fn update_voter_weight_record(ctx: Context) -> Result<()> { - let registrar = &ctx.accounts.registrar; + let registrar = &ctx.accounts.registrar.load()?; let voter = ctx.accounts.voter.load()?; let record = &mut ctx.accounts.voter_weight_record; record.voter_weight = voter.weight(®istrar)?; diff --git a/programs/voter-stake-registry/src/instructions/withdraw.rs b/programs/voter-stake-registry/src/instructions/withdraw.rs index 53658b6..00bda62 100644 --- a/programs/voter-stake-registry/src/instructions/withdraw.rs +++ b/programs/voter-stake-registry/src/instructions/withdraw.rs @@ -5,7 +5,7 @@ use anchor_spl::token::{self, Token, TokenAccount}; #[derive(Accounts)] pub struct Withdraw<'info> { - pub registrar: Box>, + pub registrar: AccountLoader<'info, Registrar>, // checking the PDA address it just an extra precaution, // the other constraints must be exhaustive @@ -36,9 +36,9 @@ pub struct Withdraw<'info> { mut, seeds = [registrar.key().as_ref(), b"voter-weight-record".as_ref(), voter_authority.key().as_ref()], bump = voter.load()?.voter_weight_record_bump, - constraint = voter_weight_record.realm == registrar.realm, + constraint = voter_weight_record.realm == registrar.load()?.realm, constraint = voter_weight_record.governing_token_owner == voter.load()?.voter_authority, - constraint = voter_weight_record.governing_token_mint == registrar.realm_governing_token_mint, + constraint = voter_weight_record.governing_token_mint == registrar.load()?.realm_governing_token_mint, )] pub voter_weight_record: Account<'info, VoterWeightRecord>, @@ -74,7 +74,7 @@ impl<'info> Withdraw<'info> { /// `amount` is in units of the native currency being withdrawn. pub fn withdraw(ctx: Context, deposit_entry_index: u8, amount: u64) -> Result<()> { // Load the accounts. - let registrar = &ctx.accounts.registrar; + let registrar = &ctx.accounts.registrar.load()?; let voter = &mut ctx.accounts.voter.load_mut()?; // Governance may forbid withdraws, for example when engaged in a vote. @@ -110,13 +110,15 @@ pub fn withdraw(ctx: Context, deposit_entry_index: u8, amount: u64) -> amount, )?; + let start_ts = deposit_entry.lockup.start_ts; + let end_ts = deposit_entry.lockup.end_ts; msg!( "Withdrew amount {} at deposit index {} with lockup kind {:?}, and start ts {}, end ts {}", amount, deposit_entry_index, deposit_entry.lockup.kind, - deposit_entry.lockup.start_ts, - deposit_entry.lockup.end_ts, + start_ts, + end_ts, ); // Update the voter weight record diff --git a/programs/voter-stake-registry/src/lib.rs b/programs/voter-stake-registry/src/lib.rs index 500ce68..8048359 100644 --- a/programs/voter-stake-registry/src/lib.rs +++ b/programs/voter-stake-registry/src/lib.rs @@ -7,6 +7,9 @@ mod error; mod instructions; pub mod state; +#[macro_use] +extern crate static_assertions; + // The program address. declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"); diff --git a/programs/voter-stake-registry/src/state/deposit_entry.rs b/programs/voter-stake-registry/src/state/deposit_entry.rs index d627dc2..bd2ff86 100644 --- a/programs/voter-stake-registry/src/state/deposit_entry.rs +++ b/programs/voter-stake-registry/src/state/deposit_entry.rs @@ -9,11 +9,8 @@ use std::convert::TryFrom; #[zero_copy] #[derive(Default)] pub struct DepositEntry { - // True if the deposit entry is being used. - pub is_used: bool, - - // Points to the VotingMintConfig this deposit uses. - pub voting_mint_config_idx: u8, + // Locked state. + pub lockup: Lockup, /// Amount in deposited, in native currency. Withdraws of vested tokens /// directly reduce this amount. @@ -32,11 +29,18 @@ pub struct DepositEntry { /// which should not change due to withdraws. pub amount_initially_locked_native: u64, + // True if the deposit entry is being used. + pub is_used: bool, + + /// If the clawback authority is allowed to extract locked tokens. pub allow_clawback: bool, - // Locked state. - pub lockup: Lockup, + // Points to the VotingMintConfig this deposit uses. + pub voting_mint_config_idx: u8, + + pub padding: [u8; 13], } +const_assert!(std::mem::size_of::() == 32 + 2 * 8 + 3 + 13); impl DepositEntry { /// # Voting Power Caclulation diff --git a/programs/voter-stake-registry/src/state/lockup.rs b/programs/voter-stake-registry/src/state/lockup.rs index 003966f..ff2b924 100644 --- a/programs/voter-stake-registry/src/state/lockup.rs +++ b/programs/voter-stake-registry/src/state/lockup.rs @@ -21,9 +21,7 @@ pub const SECS_PER_MONTH: i64 = 10; pub const SECS_PER_MONTH: i64 = 365 * SECS_PER_DAY / 12; #[zero_copy] -#[derive(AnchorSerialize, AnchorDeserialize)] pub struct Lockup { - pub kind: LockupKind, /// Start of the lockup. /// /// Note, that if start_ts is in the future, the funds are nevertheless @@ -32,12 +30,17 @@ pub struct Lockup { /// Similarly vote power computations don't care about start_ts and always /// assume the full interval from now to end_ts. pub start_ts: i64, - // End of the lockup. + + /// End of the lockup. pub end_ts: i64, + + /// Type of lockup. + pub kind: LockupKind, + // Empty bytes for future upgrades. - // TODO: what kinds of upgrades do we foresee? - pub padding: [u8; 16], + pub padding: [u8; 15], } +const_assert!(std::mem::size_of::() == 2 * 8 + 1 + 15); impl Default for Lockup { fn default() -> Self { @@ -45,7 +48,7 @@ impl Default for Lockup { kind: LockupKind::None, start_ts: 0, end_ts: 0, - padding: [0; 16], + padding: [0; 15], } } } @@ -59,7 +62,7 @@ impl Lockup { end_ts: start_ts .checked_add(i64::from(periods).checked_mul(kind.period_secs()).unwrap()) .unwrap(), - padding: [0; 16], + padding: [0; 15], }) } @@ -651,7 +654,7 @@ mod tests { kind: LockupKind::Cliff, start_ts, end_ts, - padding: [0u8; 16], + padding: [0u8; 15], }; let days_left = l.periods_left(curr_ts)?; assert_eq!(days_left, t.expected_days_left); @@ -666,7 +669,7 @@ mod tests { kind: LockupKind::Monthly, start_ts, end_ts, - padding: [0u8; 16], + padding: [0u8; 15], }; let months_left = l.periods_left(curr_ts)?; assert_eq!(months_left, t.expected_months_left); @@ -686,8 +689,9 @@ mod tests { start_ts, end_ts, kind: t.kind, - padding: [0u8; 16], + padding: [0u8; 15], }, + padding: [0; 13], }; let curr_ts = start_ts + days_to_secs(t.curr_day); let power = d.voting_power_locked(curr_ts, t.amount_deposited, MAX_SECS_LOCKED)?; diff --git a/programs/voter-stake-registry/src/state/registrar.rs b/programs/voter-stake-registry/src/state/registrar.rs index 9d6e59e..9e56598 100644 --- a/programs/voter-stake-registry/src/state/registrar.rs +++ b/programs/voter-stake-registry/src/state/registrar.rs @@ -4,7 +4,7 @@ use anchor_lang::prelude::*; use anchor_spl::token::Mint; /// Instance of a voting rights distributor. -#[account] +#[account(zero_copy)] #[derive(Default)] pub struct Registrar { pub governance_program_id: Pubkey, @@ -12,13 +12,15 @@ pub struct Registrar { pub realm_governing_token_mint: Pubkey, pub realm_authority: Pubkey, pub clawback_authority: Pubkey, - pub bump: u8, // The length should be adjusted for one's use case. pub voting_mints: [VotingMintConfig; 2], /// Debug only: time offset, to allow tests to move forward in time. pub time_offset: i64, + pub bump: u8, + pub padding: [u8; 31], } +const_assert!(std::mem::size_of::() == 5 * 32 + 2 * 120 + 8 + 1 + 31); impl Registrar { pub fn clock_unix_timestamp(&self) -> i64 { diff --git a/programs/voter-stake-registry/src/state/voter.rs b/programs/voter-stake-registry/src/state/voter.rs index de9b107..3ff6ec0 100644 --- a/programs/voter-stake-registry/src/state/voter.rs +++ b/programs/voter-stake-registry/src/state/voter.rs @@ -9,10 +9,12 @@ use spl_governance::state::token_owner_record; pub struct Voter { pub voter_authority: Pubkey, pub registrar: Pubkey, + pub deposits: [DepositEntry; 32], pub voter_bump: u8, pub voter_weight_record_bump: u8, - pub deposits: [DepositEntry; 32], + pub padding: [u8; 30], } +const_assert!(std::mem::size_of::() == 2 * 32 + 32 * 64 + 2 + 30); impl Voter { pub fn weight(&self, registrar: &Registrar) -> Result { diff --git a/programs/voter-stake-registry/src/state/voting_mint_config.rs b/programs/voter-stake-registry/src/state/voting_mint_config.rs index a7b3c92..da13b40 100644 --- a/programs/voter-stake-registry/src/state/voting_mint_config.rs +++ b/programs/voter-stake-registry/src/state/voting_mint_config.rs @@ -10,13 +10,13 @@ const SCALED_FACTOR_BASE: u64 = 1_000_000_000; /// See documentation of configure_voting_mint for details on how /// native token amounts convert to vote weight. #[zero_copy] -#[derive(AnchorSerialize, AnchorDeserialize, Default)] +#[derive(Default)] pub struct VotingMintConfig { /// Mint for this entry. pub mint: Pubkey, - /// Number of digits to shift native amounts, applying a 10^digit_shift factor. - pub digit_shift: i8, + /// The authority that is allowed to push grants into voters + pub grant_authority: Pubkey, /// Vote weight factor for deposits, in 1/SCALED_FACTOR_BASE units. pub deposit_scaled_factor: u64, @@ -27,9 +27,13 @@ pub struct VotingMintConfig { /// Number of seconds of lockup needed to reach the maximum lockup bonus. pub lockup_saturation_secs: u64, - /// The authority that is allowed to push grants into voters - pub grant_authority: Pubkey, + /// Number of digits to shift native amounts, applying a 10^digit_shift factor. + pub digit_shift: i8, + + // Empty bytes for future upgrades. + pub padding: [u8; 31], } +const_assert!(std::mem::size_of::() == 2 * 32 + 3 * 8 + 1 + 31); impl VotingMintConfig { /// Converts an amount in this voting mints's native currency