diff --git a/substrate-node/pallets/pallet-dao/src/dao.rs b/substrate-node/pallets/pallet-dao/src/dao.rs index c3ad7dcaa..569ee1303 100644 --- a/substrate-node/pallets/pallet-dao/src/dao.rs +++ b/substrate-node/pallets/pallet-dao/src/dao.rs @@ -205,17 +205,20 @@ impl Pallet { let no_votes = voting.nays.len() as u32; let yes_votes = voting.ayes.len() as u32; + let threshold_is_met = (no_votes + yes_votes) >= voting.threshold; + let proposal_is_expired = frame_system::Pallet::::block_number() >= voting.end; + // Only allow actual closing of the proposal after the voting threshold is met or voting period has ended ensure!( - (no_votes + yes_votes) >= voting.threshold - || frame_system::Pallet::::block_number() >= voting.end, + threshold_is_met || proposal_is_expired, Error::::OngoingVoteAndTresholdStillNotMet ); let total_aye_weight: u64 = voting.ayes.iter().map(|y| y.weight).sum(); let total_naye_weight: u64 = voting.nays.iter().map(|y| y.weight).sum(); - let approved = total_aye_weight > total_naye_weight; + // Only approve proposal if the voting threshold is met and simple majority (expressed in weight) is reached + let approved = threshold_is_met && (total_aye_weight > total_naye_weight); if approved { let proposal = Self::validate_and_get_proposal(&proposal_hash)?; diff --git a/substrate-node/pallets/pallet-dao/src/tests.rs b/substrate-node/pallets/pallet-dao/src/tests.rs index c9a60fd61..7fb41600a 100644 --- a/substrate-node/pallets/pallet-dao/src/tests.rs +++ b/substrate-node/pallets/pallet-dao/src/tests.rs @@ -262,6 +262,52 @@ fn close_after_proposal_duration_works() { }); } +#[test] +fn close_after_proposal_duration_threshold_not_met_works() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + + let proposal = make_proposal(b"some_remark".to_vec()); + let hash = BlakeTwo256::hash_of(&proposal); + let threshold = 2; + + assert_ok!(DaoModule::propose( + RuntimeOrigin::signed(1), + threshold, + Box::new(proposal.clone()), + b"some_description".to_vec(), + b"some_link".to_vec(), + None + )); + let proposal_index = 0; + + // Farmer 1 votes yes + let farm_id = 1; + prepare_twin_farm_and_node(10, b"farm1".to_vec(), farm_id); + assert_ok!(DaoModule::vote( + RuntimeOrigin::signed(10), + farm_id, + hash.clone(), + true + )); + + System::set_block_number(5); // default duration is 4 blocks + assert_ok!(DaoModule::close( + RuntimeOrigin::signed(2), + hash.clone(), + proposal_index + )); + + let e = System::events(); + assert_eq!( + e[6], + record(MockEvent::DaoModule(DaoEvent::Disapproved { + proposal_hash: hash, + })) + ); + }); +} + #[test] fn close_if_not_council_member_fails() { new_test_ext().execute_with(|| {