Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Governance: Check tipped proposal owner #2793

Merged
merged 1 commit into from Jan 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 8 additions & 5 deletions governance/program/src/processor/process_cast_vote.rs
Expand Up @@ -135,14 +135,17 @@ pub fn process_cast_vote(
&realm_data,
clock.unix_timestamp,
)? {
// Deserialize proposal owner and validate it's the actual owner of the proposal
let mut proposal_owner_record_data = get_token_owner_record_data_for_proposal_owner(
program_id,
proposal_owner_record_info,
&proposal_data.token_owner_record,
)?;

// If the voter is also the proposal owner then update the voter record which is serialized for the voter later on
if proposal_owner_record_info.key == voter_token_owner_record_info.key {
voter_token_owner_record_data.decrease_outstanding_proposal_count();
} else {
let mut proposal_owner_record_data = get_token_owner_record_data_for_proposal_owner(
program_id,
proposal_owner_record_info,
&proposal_data.token_owner_record,
)?;
proposal_owner_record_data.decrease_outstanding_proposal_count();
proposal_owner_record_data
.serialize(&mut *proposal_owner_record_info.data.borrow_mut())?;
Expand Down
96 changes: 96 additions & 0 deletions governance/program/tests/process_cast_vote.rs
Expand Up @@ -2,6 +2,7 @@

mod program_test;

use solana_program::pubkey::Pubkey;
use solana_program_test::tokio;

use program_test::*;
Expand Down Expand Up @@ -676,3 +677,98 @@ async fn test_cast_vote_with_cast_twice_error() {
// Assert
assert_eq!(err, GovernanceError::VoteAlreadyExists.into());
}

#[tokio::test]
async fn test_cast_vote_with_invalid_proposal_owner_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 account_governance_cookie = governance_test
.with_account_governance(
&realm_cookie,
&governed_account_cookie,
&token_owner_record_cookie,
)
.await
.unwrap();

let mut proposal_cookie = governance_test
.with_signed_off_proposal(&token_owner_record_cookie, &mut account_governance_cookie)
.await
.unwrap();

// Try to use an invalid account as the proposal owner
proposal_cookie.account.token_owner_record = Pubkey::new_unique();

// Act
let err = governance_test
.with_cast_vote(&proposal_cookie, &token_owner_record_cookie, YesNoVote::Yes)
.await
.err()
.unwrap();

assert_eq!(err, GovernanceError::InvalidProposalOwnerAccount.into());
}

#[tokio::test]
async fn test_cast_tipping_vote_with_invalid_proposal_owner_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 account_governance_cookie = governance_test
.with_account_governance(
&realm_cookie,
&governed_account_cookie,
&token_owner_record_cookie,
)
.await
.unwrap();

let mut proposal_cookie = governance_test
.with_signed_off_proposal(&token_owner_record_cookie, &mut account_governance_cookie)
.await
.unwrap();

// Create another voter and vote
let token_owner_record_cookie2 = governance_test
.with_community_token_deposit(&realm_cookie)
.await
.unwrap();

governance_test
.with_cast_vote(
&proposal_cookie,
&token_owner_record_cookie2,
YesNoVote::Yes,
)
.await
.unwrap();

// Try to use the other voter as the proposal owner
proposal_cookie.account.token_owner_record = token_owner_record_cookie2.address;

// Act
let err = governance_test
.with_cast_vote(&proposal_cookie, &token_owner_record_cookie, YesNoVote::Yes)
.await
.err()
.unwrap();

assert_eq!(err, GovernanceError::InvalidProposalOwnerAccount.into());
}