Create and write vote weight records
This commit is contained in:
parent
f00531fb7f
commit
eaf6890146
|
@ -1,4 +1,3 @@
|
|||
use crate::account::*;
|
||||
use crate::context::*;
|
||||
use crate::error::*;
|
||||
use anchor_lang::prelude::*;
|
||||
|
|
|
@ -20,6 +20,7 @@ pub const MAX_DAYS_LOCKED: u64 = 2555;
|
|||
pub struct Registrar {
|
||||
pub authority: Pubkey,
|
||||
pub realm: Pubkey,
|
||||
pub realm_community_mint: Pubkey,
|
||||
pub warmup_secs: i64,
|
||||
pub bump: u8,
|
||||
// The length should be adjusted for one's use case.
|
||||
|
@ -32,6 +33,7 @@ pub struct Voter {
|
|||
pub authority: Pubkey,
|
||||
pub registrar: Pubkey,
|
||||
pub voter_bump: u8,
|
||||
pub voter_weight_record_bump: u8,
|
||||
pub deposits: [DepositEntry; 32],
|
||||
}
|
||||
|
||||
|
@ -286,7 +288,7 @@ impl Lockup {
|
|||
|
||||
u64::try_from({
|
||||
let secs_elapsed = curr_ts.checked_sub(self.start_ts).unwrap();
|
||||
secs_elapsed.checked_sub(SECS_PER_DAY).unwrap()
|
||||
secs_elapsed.checked_div(SECS_PER_DAY).unwrap()
|
||||
})
|
||||
.map_err(|_| ErrorCode::UnableToConvert.into())
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ use anchor_spl::associated_token::AssociatedToken;
|
|||
use anchor_spl::token::{self, Mint, Token, TokenAccount};
|
||||
use std::mem::size_of;
|
||||
|
||||
pub const VOTER_WEIGHT_RECORD: [u8; 19] = *b"voter-weight-record";
|
||||
|
||||
#[derive(Accounts)]
|
||||
#[instruction(warmup_secs: i64, registrar_bump: u8)]
|
||||
pub struct CreateRegistrar<'info> {
|
||||
|
@ -15,7 +17,10 @@ pub struct CreateRegistrar<'info> {
|
|||
space = 8 + size_of::<Registrar>()
|
||||
)]
|
||||
pub registrar: AccountLoader<'info, Registrar>,
|
||||
// Unsafe and untrusted. This instruction needs to be invoked immediatley
|
||||
// after the realm is created.
|
||||
pub realm: UncheckedAccount<'info>,
|
||||
pub realm_community_mint: Account<'info, Mint>,
|
||||
pub authority: UncheckedAccount<'info>,
|
||||
pub payer: Signer<'info>,
|
||||
pub system_program: Program<'info, System>,
|
||||
|
@ -24,7 +29,7 @@ pub struct CreateRegistrar<'info> {
|
|||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
#[instruction(voter_bump: u8)]
|
||||
#[instruction(voter_bump: u8, voter_weight_record_bump: u8)]
|
||||
pub struct CreateVoter<'info> {
|
||||
#[account(
|
||||
init,
|
||||
|
@ -34,8 +39,17 @@ pub struct CreateVoter<'info> {
|
|||
space = 8 + size_of::<Voter>(),
|
||||
)]
|
||||
pub voter: AccountLoader<'info, Voter>,
|
||||
#[account(
|
||||
init
|
||||
, seeds = [VOTER_WEIGHT_RECORD.as_ref(), registrar.key().as_ref(), authority.key().as_ref()],
|
||||
bump = voter_weight_record_bump,
|
||||
payer = payer,
|
||||
space = 150,
|
||||
)]
|
||||
pub voter_weight_record: Account<'info, VoterWeightRecord>,
|
||||
pub registrar: AccountLoader<'info, Registrar>,
|
||||
pub authority: Signer<'info>,
|
||||
pub payer: Signer<'info>,
|
||||
pub token_program: Program<'info, Token>,
|
||||
pub associated_token_program: Program<'info, AssociatedToken>,
|
||||
pub system_program: Program<'info, System>,
|
||||
|
@ -237,9 +251,9 @@ pub struct UpdateSchedule<'info> {
|
|||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct DecayVotingPower<'info> {
|
||||
pub struct UpdateVoterWeightRecord<'info> {
|
||||
#[account(
|
||||
seeds = [vote_weight_record.realm.as_ref()],
|
||||
seeds = [voter_weight_record.realm.as_ref()],
|
||||
bump = registrar.load()?.bump,
|
||||
)]
|
||||
pub registrar: AccountLoader<'info, Registrar>,
|
||||
|
@ -250,10 +264,14 @@ pub struct DecayVotingPower<'info> {
|
|||
pub voter: AccountLoader<'info, Voter>,
|
||||
#[account(
|
||||
mut,
|
||||
constraint = vote_weight_record.governing_token_owner == voter.load()?.authority,
|
||||
seeds = [VOTER_WEIGHT_RECORD.as_ref(), registrar.key().as_ref(), authority.key().as_ref()],
|
||||
bump = voter.load()?.voter_weight_record_bump,
|
||||
constraint = voter_weight_record.realm == registrar.load()?.realm,
|
||||
constraint = voter_weight_record.governing_token_owner == voter.load()?.authority,
|
||||
)]
|
||||
pub vote_weight_record: Account<'info, VoterWeightRecord>,
|
||||
pub voter_weight_record: Account<'info, VoterWeightRecord>,
|
||||
pub authority: Signer<'info>,
|
||||
pub system_program: Program<'info, System>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
|
|
|
@ -4,6 +4,7 @@ use anchor_lang::prelude::*;
|
|||
use anchor_spl::token;
|
||||
use context::*;
|
||||
use error::*;
|
||||
use spl_governance::addins::voter_weight::VoterWeightAccountType;
|
||||
|
||||
mod access_control;
|
||||
mod account;
|
||||
|
@ -71,6 +72,7 @@ pub mod governance_registry {
|
|||
let registrar = &mut ctx.accounts.registrar.load_init()?;
|
||||
registrar.bump = registrar_bump;
|
||||
registrar.realm = ctx.accounts.realm.key();
|
||||
registrar.realm_community_mint = ctx.accounts.realm_community_mint.key();
|
||||
registrar.authority = ctx.accounts.authority.key();
|
||||
registrar.warmup_secs = warmup_secs;
|
||||
|
||||
|
@ -97,12 +99,28 @@ pub mod governance_registry {
|
|||
|
||||
/// Creates a new voter account. There can only be a single voter per
|
||||
/// user wallet.
|
||||
pub fn create_voter(ctx: Context<CreateVoter>, voter_bump: u8) -> Result<()> {
|
||||
pub fn create_voter(
|
||||
ctx: Context<CreateVoter>,
|
||||
voter_bump: u8,
|
||||
voter_weight_record_bump: u8,
|
||||
) -> Result<()> {
|
||||
// Load accounts.
|
||||
let registrar = &ctx.accounts.registrar.load()?;
|
||||
let voter = &mut ctx.accounts.voter.load_init()?;
|
||||
let voter_weight_record = &mut ctx.accounts.voter_weight_record;
|
||||
|
||||
// Init the voter.
|
||||
voter.voter_bump = voter_bump;
|
||||
voter.voter_weight_record_bump = voter_weight_record_bump;
|
||||
voter.authority = ctx.accounts.authority.key();
|
||||
voter.registrar = ctx.accounts.registrar.key();
|
||||
|
||||
// Init the voter weight record.
|
||||
voter_weight_record.account_type = VoterWeightAccountType::VoterWeightRecord;
|
||||
voter_weight_record.realm = registrar.realm;
|
||||
voter_weight_record.governing_token_mint = registrar.realm_community_mint;
|
||||
voter_weight_record.governing_token_owner = ctx.accounts.authority.key();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -306,11 +324,12 @@ pub mod governance_registry {
|
|||
///
|
||||
/// This "revise" instruction should be called in the same transaction,
|
||||
/// immediately before voting.
|
||||
pub fn decay_voting_power(ctx: Context<DecayVotingPower>) -> Result<()> {
|
||||
pub fn update_voter_weight_record(ctx: Context<UpdateVoterWeightRecord>) -> Result<()> {
|
||||
let voter = ctx.accounts.voter.load()?;
|
||||
let record = &mut ctx.accounts.vote_weight_record;
|
||||
let record = &mut ctx.accounts.voter_weight_record;
|
||||
record.voter_weight = voter.weight()?;
|
||||
record.voter_weight_expiry = Some(Clock::get()?.slot);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -35,14 +35,20 @@ describe("voting-rights", () => {
|
|||
votingMintA: PublicKey,
|
||||
votingMintB: PublicKey,
|
||||
voter: PublicKey,
|
||||
voterWeightRecord: PublicKey,
|
||||
votingToken: PublicKey,
|
||||
exchangeVaultA: PublicKey,
|
||||
exchangeVaultB: PublicKey;
|
||||
let registrarBump: number,
|
||||
votingMintBumpA: number,
|
||||
votingMintBumpB: number,
|
||||
voterBump: number;
|
||||
let mintA: PublicKey, mintB: PublicKey, godA: PublicKey, godB: PublicKey;
|
||||
voterBump: number,
|
||||
voterWeightRecordBump: number;
|
||||
let mintA: PublicKey,
|
||||
mintB: PublicKey,
|
||||
godA: PublicKey,
|
||||
godB: PublicKey,
|
||||
realmCommunityMint: PublicKey;
|
||||
let tokenAClient: Token,
|
||||
tokenBClient: Token,
|
||||
votingTokenClientA: Token,
|
||||
|
@ -66,6 +72,7 @@ describe("voting-rights", () => {
|
|||
mintB = _mintB;
|
||||
godA = _godA;
|
||||
godB = _godB;
|
||||
realmCommunityMint = mintA;
|
||||
});
|
||||
|
||||
it("Creates PDAs", async () => {
|
||||
|
@ -85,6 +92,15 @@ describe("voting-rights", () => {
|
|||
[_registrar.toBuffer(), program.provider.wallet.publicKey.toBuffer()],
|
||||
program.programId
|
||||
);
|
||||
const [_voterWeightRecord, _voterWeightRecordBump] =
|
||||
await PublicKey.findProgramAddress(
|
||||
[
|
||||
anchor.utils.bytes.utf8.encode("voter-weight-record"),
|
||||
_registrar.toBuffer(),
|
||||
program.provider.wallet.publicKey.toBuffer(),
|
||||
],
|
||||
program.programId
|
||||
);
|
||||
votingToken = await Token.getAssociatedTokenAddress(
|
||||
associatedTokenProgram,
|
||||
tokenProgram,
|
||||
|
@ -115,6 +131,8 @@ describe("voting-rights", () => {
|
|||
votingMintBumpA = _votingMintBumpA;
|
||||
votingMintBumpB = _votingMintBumpB;
|
||||
voterBump = _voterBump;
|
||||
voterWeightRecord = _voterWeightRecord;
|
||||
voterWeightRecordBump = _voterWeightRecordBump;
|
||||
});
|
||||
|
||||
it("Creates token clients", async () => {
|
||||
|
@ -149,21 +167,18 @@ describe("voting-rights", () => {
|
|||
});
|
||||
|
||||
it("Initializes a registrar", async () => {
|
||||
await program.rpc.createRegistrar(
|
||||
new BN(0),
|
||||
registrarBump,
|
||||
{
|
||||
await program.rpc.createRegistrar(new BN(0), registrarBump, {
|
||||
accounts: {
|
||||
registrar,
|
||||
realm,
|
||||
realmCommunityMint,
|
||||
authority: program.provider.wallet.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram,
|
||||
tokenProgram,
|
||||
rent,
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("Adds an exchange rate A", async () => {
|
||||
|
@ -209,11 +224,13 @@ describe("voting-rights", () => {
|
|||
});
|
||||
|
||||
it("Initializes a voter", async () => {
|
||||
await program.rpc.createVoter(voterBump, {
|
||||
await program.rpc.createVoter(voterBump, voterWeightRecordBump, {
|
||||
accounts: {
|
||||
voter,
|
||||
voterWeightRecord,
|
||||
registrar,
|
||||
authority: program.provider.wallet.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram,
|
||||
associatedTokenProgram,
|
||||
tokenProgram,
|
||||
|
@ -313,4 +330,16 @@ describe("voting-rights", () => {
|
|||
assert.ok(deposit.amountDeposited.toNumber() === 10);
|
||||
assert.ok(deposit.rateIdx === 0);
|
||||
});
|
||||
|
||||
it("Updates a vote weight record", async () => {
|
||||
await program.rpc.updateVoterWeightRecord({
|
||||
accounts: {
|
||||
registrar,
|
||||
voter,
|
||||
voterWeightRecord,
|
||||
authority: program.provider.wallet.publicKey,
|
||||
systemProgram,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue