Skip to content
This repository was archived by the owner on Feb 9, 2025. It is now read-only.

Commit a7eedd5

Browse files
authored
Code cleanup & Tests (#36)
* chore: extract get_vote_record_address * chore: add reserved space to NftVoteRecord * chore: test_relinquish_nft_vote_for_proposal_in_voting_state_and_vote_record_exists_error * chore: log version
1 parent 47036ce commit a7eedd5

File tree

7 files changed

+121
-10
lines changed

7 files changed

+121
-10
lines changed

programs/nft-voter/src/instructions/cast_nft_vote.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ pub fn cast_nft_vote<'a,'b,'c,'info>(ctx: Context<'a,'b,'c,'info,CastNftVote<'in
7575
proposal,
7676
nft_mint,
7777
governing_token_owner:*governing_token_owner,
78+
reserved: [0; 8],
7879
};
7980

8081
// Anchor doesn't natively support dynamic account creation using remaining_accounts

programs/nft-voter/src/instructions/relinquish_nft_vote.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use anchor_lang::prelude::*;
2-
use spl_governance::state::{vote_record,token_owner_record};
32
use spl_governance::state::{enums::ProposalState, governance, proposal};
43
use spl_governance_tools::account::dispose_account;
54
use crate::error::NftVoterError;
5+
use crate::tools::governance::get_vote_record_address;
66
use crate::{state::*};
77

88
use crate::state::{get_nft_vote_record_data_for_proposal_and_token_owner, Registrar};
@@ -71,16 +71,12 @@ pub fn relinquish_nft_vote(ctx: Context<RelinquishNftVote>) -> Result<()> {
7171
let vote_record_info = &ctx.accounts.vote_record.to_account_info();
7272

7373
// Ensure the given VoteRecord address matches the expected PDA
74-
let token_owner_record_key = token_owner_record::get_token_owner_record_address(
74+
let vote_record_key = get_vote_record_address(
7575
&registrar.governance_program_id,
76-
&registrar.realm,
76+
&registrar.realm,
7777
&registrar.governing_token_mint,
78-
&ctx.accounts.governing_token_owner.key());
79-
80-
let vote_record_key = vote_record::get_vote_record_address(
81-
&registrar.governance_program_id,
82-
&ctx.accounts.proposal.key(),
83-
&token_owner_record_key);
78+
&ctx.accounts.governing_token_owner.key(),
79+
&ctx.accounts.proposal.key());
8480

8581
require!(
8682
vote_record_key == vote_record_info.key(),

programs/nft-voter/src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,25 @@ pub mod nft_voter {
1818

1919
use super::*;
2020
pub fn create_registrar(ctx: Context<CreateRegistrar>, max_collections: u8) -> Result<()> {
21+
log_version();
2122
instructions::create_registrar(ctx, max_collections)
2223
}
2324
pub fn create_voter_weight_record(
2425
ctx: Context<CreateVoterWeightRecord>,
2526
governing_token_owner: Pubkey,
2627
) -> Result<()> {
28+
log_version();
2729
instructions::create_voter_weight_record(ctx, governing_token_owner)
2830
}
2931
pub fn create_max_voter_weight_record(ctx: Context<CreateMaxVoterWeightRecord>) -> Result<()> {
32+
log_version();
3033
instructions::create_max_voter_weight_record(ctx)
3134
}
3235
pub fn update_voter_weight_record(
3336
ctx: Context<UpdateVoterWeightRecord>,
3437
voter_weight_action: VoterWeightAction,
3538
) -> Result<()> {
39+
log_version();
3640
instructions::update_voter_weight_record(ctx, voter_weight_action)
3741
}
3842
pub fn relinquish_nft_vote(ctx: Context<RelinquishNftVote>) -> Result<()> {
@@ -43,13 +47,20 @@ pub mod nft_voter {
4347
weight: u64,
4448
size: u32,
4549
) -> Result<()> {
50+
log_version();
4651
instructions::configure_collection(ctx, weight, size)
4752
}
4853

4954
pub fn cast_nft_vote<'a, 'b, 'c, 'info>(
5055
ctx: Context<'a, 'b, 'c, 'info, CastNftVote<'info>>,
5156
proposal: Pubkey,
5257
) -> Result<()> {
58+
log_version();
5359
instructions::cast_nft_vote(ctx, proposal)
5460
}
5561
}
62+
63+
fn log_version() {
64+
// TODO: Check if Anchor allows to log it before instruction is deserialized
65+
msg!("VERSION:{:?}", env!("CARGO_PKG_VERSION"));
66+
}

programs/nft-voter/src/state/nft_vote_record.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ pub struct NftVoteRecord {
2727
/// The voter who casted this vote
2828
/// It's a Realm member pubkey corresponding to TokenOwnerRecord.governing_token_owner
2929
pub governing_token_owner: Pubkey,
30+
31+
/// Reserved for future upgrades
32+
pub reserved: [u8; 8],
3033
}
3134

3235
impl NftVoteRecord {

programs/nft-voter/src/tools/governance.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::id;
22
use anchor_lang::prelude::Pubkey;
3+
use spl_governance::state::{token_owner_record, vote_record};
34

45
/// A macro is exposed so that we can embed the program ID.
56
#[macro_export]
@@ -187,3 +188,20 @@ pub fn get_max_voter_weight_record_address(
187188
)
188189
.0
189190
}
191+
192+
pub fn get_vote_record_address(
193+
program_id: &Pubkey,
194+
realm: &Pubkey,
195+
governing_token_mint: &Pubkey,
196+
governing_token_owner: &Pubkey,
197+
proposal: &Pubkey,
198+
) -> Pubkey {
199+
let token_owner_record_key = token_owner_record::get_token_owner_record_address(
200+
program_id,
201+
realm,
202+
governing_token_mint,
203+
governing_token_owner,
204+
);
205+
206+
vote_record::get_vote_record_address(program_id, proposal, &token_owner_record_key)
207+
}

programs/nft-voter/tests/program_test/nft_voter_test.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ impl NftVoterTest {
459459
Ok(CollectionConfigCookie { collection_config })
460460
}
461461

462-
/// Casts NFT vote
462+
/// Casts NFT Vote and spl-gov Vote
463463
#[allow(dead_code)]
464464
pub async fn cast_nft_vote(
465465
&mut self,
@@ -501,6 +501,7 @@ impl NftVoterTest {
501501
nft_mint: nft_cookie.mint_cookie.address,
502502
governing_token_owner: voter_weight_record_cookie.account.governing_token_owner,
503503
account_discriminator: NftVoteRecord::ACCOUNT_DISCRIMINATOR,
504+
reserved: [0; 8],
504505
};
505506

506507
nft_vote_record_cookies.push(NftVoteRecordCookie {

programs/nft-voter/tests/relinquish_nft_vote.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::program_test::nft_voter_test::ConfigureCollectionArgs;
2+
use gpl_nft_voter::error::NftVoterError;
23
use program_test::nft_voter_test::NftVoterTest;
4+
use program_test::tools::assert_nft_voter_err;
35
use solana_program_test::*;
46
use solana_sdk::transport::TransportError;
57

@@ -194,3 +196,82 @@ async fn test_relinquish_nft_vote_for_proposal_in_voting_state() -> Result<(), T
194196

195197
Ok(())
196198
}
199+
200+
#[tokio::test]
201+
async fn test_relinquish_nft_vote_for_proposal_in_voting_state_and_vote_record_exists_error(
202+
) -> Result<(), TransportError> {
203+
// Arrange
204+
let mut nft_voter_test = NftVoterTest::start_new().await;
205+
206+
let realm_cookie = nft_voter_test.governance.with_realm().await?;
207+
208+
let registrar_cookie = nft_voter_test.with_registrar(&realm_cookie).await?;
209+
210+
let nft_collection_cookie = nft_voter_test.token_metadata.with_nft_collection().await?;
211+
212+
let max_voter_weight_record_cookie = nft_voter_test
213+
.with_max_voter_weight_record(&registrar_cookie)
214+
.await?;
215+
216+
nft_voter_test
217+
.with_collection(
218+
&registrar_cookie,
219+
&nft_collection_cookie,
220+
&max_voter_weight_record_cookie,
221+
None,
222+
)
223+
.await?;
224+
225+
let voter_cookie = nft_voter_test.bench.with_wallet().await;
226+
227+
let voter_token_owner_record_cookie = nft_voter_test
228+
.governance
229+
.with_token_owner_record(&realm_cookie, &voter_cookie)
230+
.await?;
231+
232+
let voter_weight_record_cookie = nft_voter_test
233+
.with_voter_weight_record(&registrar_cookie, &voter_cookie)
234+
.await?;
235+
236+
let proposal_cookie = nft_voter_test
237+
.governance
238+
.with_proposal(&realm_cookie)
239+
.await?;
240+
241+
let nft_cookie1 = nft_voter_test
242+
.token_metadata
243+
.with_nft_v2(&nft_collection_cookie, &voter_cookie, None)
244+
.await?;
245+
246+
let nft_vote_record_cookies = nft_voter_test
247+
.cast_nft_vote(
248+
&registrar_cookie,
249+
&voter_weight_record_cookie,
250+
&max_voter_weight_record_cookie,
251+
&proposal_cookie,
252+
&voter_cookie,
253+
&voter_token_owner_record_cookie,
254+
&[&nft_cookie1],
255+
)
256+
.await?;
257+
258+
// Act
259+
260+
let err = nft_voter_test
261+
.relinquish_nft_vote(
262+
&registrar_cookie,
263+
&voter_weight_record_cookie,
264+
&proposal_cookie,
265+
&voter_cookie,
266+
&voter_token_owner_record_cookie,
267+
&nft_vote_record_cookies,
268+
)
269+
.await
270+
.err()
271+
.unwrap();
272+
273+
// Assert
274+
assert_nft_voter_err(err, NftVoterError::VoteRecordMustBeWithdrawn);
275+
276+
Ok(())
277+
}

0 commit comments

Comments
 (0)