Skip to content

Commit

Permalink
Merge pull request #178 from confio/feat/multistatus-logic
Browse files Browse the repository at this point in the history
Backport multisig fixes to voting contracts
  • Loading branch information
0xFable authored Sep 7, 2022
2 parents 001d45f + 3975c3c commit 69b1d8f
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 3 deletions.
10 changes: 8 additions & 2 deletions packages/voting-contract/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,15 @@ where
// ensure proposal exists and can be voted on
let mut prop = proposals().load(deps.storage, proposal_id)?;

if prop.current_status(&env.block) != Status::Open {
if ![Status::Open, Status::Passed, Status::Rejected].contains(&prop.status) {
return Err(ContractError::NotOpen {});
}

// if they are not expired
if prop.expires.is_expired(&env.block) {
return Err(ContractError::Expired {});
}

// use a snapshot of "start of proposal"
// Must be a member of voting group and have voting power >= 1
let cfg = CONFIG.load(deps.storage)?;
Expand Down Expand Up @@ -157,7 +162,8 @@ where
P: Serialize + DeserializeOwned,
{
let mut proposal = proposals::<P>().load(storage, proposal_id)?;

// Update Status
proposal.update_status(&env.block);
// We allow execution even after the proposal "expiration" as long as all votes come in before
// that point. If it was approved on time, it can be executed any time.
if proposal.current_status(&env.block) != Status::Passed {
Expand Down
47 changes: 46 additions & 1 deletion packages/voting-contract/src/multitest/voting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,5 +368,50 @@ fn expired_proposals_cannot_be_voted_on() {
// Bob can't vote on the expired proposal
let err = suite.vote("bob", proposal_id, Vote::Yes).unwrap_err();
// proposal that is open and expired is rejected
assert_eq!(ContractError::NotOpen {}, err.downcast().unwrap());
assert_eq!(ContractError::Expired {}, err.downcast().unwrap());
}

#[test]
fn proposal_pass_on_expiration() {
let rules = RulesBuilder::new()
.with_threshold(Decimal::percent(51))
.with_quorum(Decimal::percent(35))
.build();

let mut suite = SuiteBuilder::new()
.with_member("alice", 1)
.with_member("bob", 2)
.with_rules(rules.clone())
.build();

// Create proposal with 1 voting power
let response = suite.propose("alice", "cool proposal", "proposal").unwrap();
let proposal_id: u64 = get_proposal_id(&response).unwrap();

// Bob can vote on the proposal
suite.vote("bob", proposal_id, Vote::Yes).unwrap();

// Move time forward so voting ends
suite.app.advance_seconds(rules.voting_period_secs());

// Verify proposal is now passed
let prop = suite.query_proposal(proposal_id).unwrap();
assert_eq!(prop.status, Status::Passed);

// Alice can't vote on the proposal
let err = suite.vote("alice", proposal_id, Vote::Yes).unwrap_err();

// cannot vote on proposal as it has expired
assert_eq!(ContractError::Expired {}, err.downcast().unwrap());

// But she can execute the proposal
suite.execute_proposal("alice", proposal_id).unwrap();

// Verify proposal is now 'executed'
let prop = suite.query_proposal(proposal_id).unwrap();
assert_eq!(prop.status, Status::Executed);

// Closing should NOT be possible
let err = suite.close("bob", proposal_id).unwrap_err();
assert_eq!(ContractError::WrongCloseStatus {}, err.downcast().unwrap());
}

0 comments on commit 69b1d8f

Please sign in to comment.