From c32a69eaf027809768f0dc414fe0c9e017ed9094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Mon, 24 Jul 2023 12:48:39 +0300 Subject: [PATCH 01/12] Governance-v2: Add merkle proof support --- .../governance-v2/src/configurable.rs | 8 +- .../governance-v2/src/errors.rs | 10 +- energy-integration/governance-v2/src/lib.rs | 119 ++++++----- .../governance-v2/src/proposal.rs | 5 +- energy-integration/governance-v2/src/views.rs | 15 +- .../governance-v2/tests/gov_rust_test.rs | 30 +-- .../governance-v2/tests/gov_test_setup/mod.rs | 198 +++++++++++------- 7 files changed, 234 insertions(+), 151 deletions(-) diff --git a/energy-integration/governance-v2/src/configurable.rs b/energy-integration/governance-v2/src/configurable.rs index 5ed97fefc..c7982e68a 100644 --- a/energy-integration/governance-v2/src/configurable.rs +++ b/energy-integration/governance-v2/src/configurable.rs @@ -60,9 +60,9 @@ pub trait ConfigurablePropertiesModule: } #[only_owner] - #[endpoint(changeQuorum)] - fn change_quorum(&self, new_value: BigUint) { - self.try_change_quorum(new_value); + #[endpoint(changeQuorumPercentage)] + fn change_quorum_percentage(&self, new_value: BigUint) { + self.try_change_quorum_percentage(new_value); } #[only_owner] @@ -96,7 +96,7 @@ pub trait ConfigurablePropertiesModule: self.min_fee_for_propose().set(&new_value); } - fn try_change_quorum(&self, new_value: BigUint) { + fn try_change_quorum_percentage(&self, new_value: BigUint) { require!( new_value > MIN_QUORUM && new_value < MAX_QUORUM, "Not valid value for Quorum!" diff --git a/energy-integration/governance-v2/src/errors.rs b/energy-integration/governance-v2/src/errors.rs index ff552346b..f569688a8 100644 --- a/energy-integration/governance-v2/src/errors.rs +++ b/energy-integration/governance-v2/src/errors.rs @@ -1,6 +1,14 @@ pub const WRONG_TOKEN_ID: &[u8] = b"Wrong payment token id for fee"; pub const NOT_ENOUGH_FEE: &[u8] = b"Minimum fee required not reached"; -pub const NOT_ENOUGH_ENERGY: &[u8] = b"Not enough energy for propose"; pub const TOO_MUCH_GAS: &[u8] = b"Actions require too much gas to be executed"; pub const PROPOSAL_NOT_ACTIVE: &[u8] = b"Proposal is not active"; pub const ERROR_NOT_AN_ESDT: &[u8] = b"Not a valid esdt id"; +pub const ALREADY_VOTED_ERR_MSG: &[u8] = b"Already voted for this proposal"; +pub const INVALID_ROOT_HASH: &[u8] = b"Invalid root hash provided"; +pub const PROPOSAL_NO_ACTION: &[u8] = b"Proposal has no actions"; +pub const EXEEDED_MAX_ACTIONS: &[u8] = b"Exceeded max actions per proposal"; +pub const ONLY_PROPOSER_CANCEL: &[u8] = b"Only original proposer may cancel a pending proposal"; +pub const ONLY_PROPOSER_WITHDRAW: &[u8] = b"Only original proposer may cancel a pending proposal"; +pub const NO_PROPOSAL: &[u8] = b"Proposal does not exist"; +pub const WITHDRAW_NOT_ALLOWED: &[u8] = b"You may not withdraw funds from this proposal!"; +pub const INVALID_MERKLE_PROOF: &[u8] = b"Invalid merkle proof provided"; \ No newline at end of file diff --git a/energy-integration/governance-v2/src/lib.rs b/energy-integration/governance-v2/src/lib.rs index 39459c1b7..4035ef03d 100644 --- a/energy-integration/governance-v2/src/lib.rs +++ b/energy-integration/governance-v2/src/lib.rs @@ -12,15 +12,12 @@ pub mod views; use proposal::*; use proposal_storage::VoteType; -use weekly_rewards_splitting::events::Week; -use weekly_rewards_splitting::global_info::ProxyTrait as _; use crate::errors::*; use crate::proposal_storage::ProposalVotes; const MAX_GAS_LIMIT_PER_BLOCK: u64 = 600_000_000; const FULL_PERCENTAGE: u64 = 10_000; -static ALREADY_VOTED_ERR_MSG: &[u8] = b"Already voted for this proposal"; /// An empty contract. To be used as a template when starting a new contract from scratch. #[multiversx_sc::contract] @@ -33,34 +30,34 @@ pub trait GovernanceV2: + energy_query::EnergyQueryModule + permissions_module::PermissionsModule { - /// - `min_energy_for_propose` - the minimum energy required for submitting a proposal - /// - `min_fee_for_propose` - the minimum fee required for submitting a proposal - /// - `quorum` - the minimum number of (`votes` minus `downvotes`) at the end of voting period - /// - `maxActionsPerProposal` - Maximum number of actions (transfers and/or smart contract calls) that a proposal may have - /// - `votingDelayInBlocks` - Number of blocks to wait after a block is proposed before being able to vote/downvote that proposal - /// - `votingPeriodInBlocks` - Number of blocks the voting period lasts (voting delay does not count towards this) - /// - `lockTimeAfterVotingEndsInBlocks` - Number of blocks to wait before a successful proposal can be executed + /// - `min_energy_for_propose` - the minimum energy required for submitting a proposal; + /// - `min_fee_for_propose` - the minimum fee required for submitting a proposal; + /// - `quorum` - the minimum number of (`votes` minus `downvotes`) at the end of voting period; + /// - `votingDelayInBlocks` - Number of blocks to wait after a block is proposed before being able to vote/downvote that proposal; + /// - `votingPeriodInBlocks` - Number of blocks the voting period lasts (voting delay does not count towards this); + /// - `withdraw_percentage_defeated` - The percentage used to return in case of DownVetoVote; + /// - `energy_factory_address`; + /// - `fees_collector_address`; + /// - `fee_token` - The token used to pay the fee for governance proposal; #[init] fn init( &self, - min_energy_for_propose: BigUint, + // min_energy_for_propose: BigUint, min_fee_for_propose: BigUint, quorum_percentage: BigUint, voting_delay_in_blocks: u64, voting_period_in_blocks: u64, withdraw_percentage_defeated: u64, energy_factory_address: ManagedAddress, - fees_collector_address: ManagedAddress, fee_token: TokenIdentifier, ) { - self.try_change_min_energy_for_propose(min_energy_for_propose); + // self.try_change_min_energy_for_propose(min_energy_for_propose); self.try_change_min_fee_for_propose(min_fee_for_propose); - self.try_change_quorum(quorum_percentage); + self.try_change_quorum_percentage(quorum_percentage); self.try_change_voting_delay_in_blocks(voting_delay_in_blocks); self.try_change_voting_period_in_blocks(voting_period_in_blocks); self.try_change_withdraw_percentage_defeated(withdraw_percentage_defeated); self.set_energy_factory_address(energy_factory_address); - self.fees_collector_address().set(&fees_collector_address); self.try_change_fee_token_id(fee_token); } @@ -81,20 +78,23 @@ pub trait GovernanceV2: #[endpoint] fn propose( &self, + root_hash: ManagedByteArray, + total_voting_power: BigUint, description: ManagedBuffer, actions: MultiValueEncoded>, ) -> ProposalId { self.require_caller_not_self(); - require!(!actions.is_empty(), "Proposal has no actions"); + require!(!root_hash.is_empty(), INVALID_ROOT_HASH); + require!(!actions.is_empty(), PROPOSAL_NO_ACTION); require!( actions.len() <= MAX_GOVERNANCE_PROPOSAL_ACTIONS, - "Exceeded max actions per proposal" + EXEEDED_MAX_ACTIONS ); let proposer = self.blockchain().get_caller(); - let user_energy = self.get_energy_amount_non_zero(&proposer); - let min_energy_for_propose = self.min_energy_for_propose().get(); - require!(user_energy >= min_energy_for_propose, NOT_ENOUGH_ENERGY); + // let user_energy = self.get_energy_amount_non_zero(&proposer); + // let min_energy_for_propose = self.min_energy_for_propose().get(); + // require!(user_energy >= min_energy_for_propose, NOT_ENOUGH_ENERGY); let user_fee = self.call_value().single_esdt(); require!( @@ -134,13 +134,14 @@ pub trait GovernanceV2: proposal_id: self.proposals().len() + 1, proposer: proposer.clone(), description, + root_hash, actions: gov_actions, fee_payment: user_fee, minimum_quorum, voting_delay_in_blocks, voting_period_in_blocks, withdraw_percentage_defeated, - total_energy: BigUint::zero(), + total_voting_power, proposal_start_block: current_block, }; let proposal_id = self.proposals().push(&proposal); @@ -154,7 +155,7 @@ pub trait GovernanceV2: /// Vote on a proposal. The voting power depends on the user's energy. #[endpoint] - fn vote(&self, proposal_id: ProposalId, vote: VoteType) { + fn vote(&self, proposal_id: ProposalId, vote: VoteType, voting_power: BigUint, proof: ArrayVec, PROOF_LENGTH>) { self.require_caller_not_self(); self.require_valid_proposal_id(proposal_id); require!( @@ -166,59 +167,46 @@ pub trait GovernanceV2: let new_user = self.user_voted_proposals(&voter).insert(proposal_id); require!(new_user, ALREADY_VOTED_ERR_MSG); - let current_quorum = self.proposal_votes(proposal_id).get().quorum; - - // First voter -> update total_energy - if current_quorum == BigUint::zero() { - let fees_collector_addr = self.fees_collector_address().get(); - let last_global_update_week: Week = self - .fees_collector_proxy(fees_collector_addr.clone()) - .last_global_update_week() - .execute_on_dest_context(); - - let total_energy: BigUint = self - .fees_collector_proxy(fees_collector_addr) - .total_energy_for_week(last_global_update_week) - .execute_on_dest_context(); - - let mut proposal = self.proposals().get(proposal_id); - proposal.total_energy = total_energy; - self.proposals().set(proposal_id, &proposal); + match self.get_root_hash(proposal_id) { + OptionalValue::None => { + sc_panic!(NO_PROPOSAL); + } + OptionalValue::Some(root_hash) => { + require!(self.verify_merkle_proof(voting_power.clone(), proof, root_hash), INVALID_MERKLE_PROOF); + } } - let user_energy = self.get_energy_amount_non_zero(&voter); - let voting_power = user_energy.sqrt(); - match vote { VoteType::UpVote => { self.proposal_votes(proposal_id).update(|proposal_votes| { proposal_votes.up_votes += &voting_power.clone(); - proposal_votes.quorum += &user_energy.clone(); + proposal_votes.quorum += &voting_power.clone(); }); self.up_vote_cast_event(&voter, proposal_id, &voting_power); } VoteType::DownVote => { self.proposal_votes(proposal_id).update(|proposal_votes| { proposal_votes.down_votes += &voting_power.clone(); - proposal_votes.quorum += &user_energy.clone(); + proposal_votes.quorum += &voting_power.clone(); }); self.down_vote_cast_event(&voter, proposal_id, &voting_power); } VoteType::DownVetoVote => { self.proposal_votes(proposal_id).update(|proposal_votes| { proposal_votes.down_veto_votes += &voting_power.clone(); - proposal_votes.quorum += &user_energy.clone(); + proposal_votes.quorum += &voting_power.clone(); }); self.down_veto_vote_cast_event(&voter, proposal_id, &voting_power); } VoteType::AbstainVote => { self.proposal_votes(proposal_id).update(|proposal_votes| { proposal_votes.abstain_votes += &voting_power.clone(); - proposal_votes.quorum += &user_energy.clone(); + proposal_votes.quorum += &voting_power.clone(); }); self.abstain_vote_cast_event(&voter, proposal_id, &voting_power); } } + self.user_voted_proposals(&voter).insert(proposal_id); } /// Cancel a proposed action. This can be done: @@ -230,7 +218,7 @@ pub trait GovernanceV2: match self.get_proposal_status(proposal_id) { GovernanceProposalStatus::None => { - sc_panic!("Proposal does not exist"); + sc_panic!(NO_PROPOSAL); } GovernanceProposalStatus::Pending => { let proposal = self.proposals().get(proposal_id); @@ -238,7 +226,7 @@ pub trait GovernanceV2: require!( caller == proposal.proposer, - "Only original proposer may cancel a pending proposal" + ONLY_PROPOSER_CANCEL ); self.refund_proposal_fee(proposal_id, &proposal.fee_payment.amount); self.clear_proposal(proposal_id); @@ -259,14 +247,14 @@ pub trait GovernanceV2: match self.get_proposal_status(proposal_id) { GovernanceProposalStatus::None => { - sc_panic!("Proposal does not exist"); + sc_panic!(NO_PROPOSAL); } GovernanceProposalStatus::Succeeded | GovernanceProposalStatus::Defeated => { let proposal = self.proposals().get(proposal_id); require!( caller == proposal.proposer, - "Only original proposer may cancel a pending proposal" + ONLY_PROPOSER_WITHDRAW ); self.refund_proposal_fee(proposal_id, &proposal.fee_payment.amount); @@ -279,7 +267,7 @@ pub trait GovernanceV2: require!( caller == proposal.proposer, - "Only original proposer may cancel a pending proposal" + ONLY_PROPOSER_WITHDRAW ); self.refund_proposal_fee(proposal_id, &refund_amount); @@ -294,7 +282,7 @@ pub trait GovernanceV2: }); } _ => { - sc_panic!("You may not withdraw funds from this proposal!"); + sc_panic!(WITHDRAW_NOT_ALLOWED); } } self.proposal_withdraw_after_defeated_event(proposal_id); @@ -324,6 +312,31 @@ pub trait GovernanceV2: ); } + fn verify_merkle_proof(&self, power: BigUint, proof: ArrayVec, PROOF_LENGTH>, root_hash: ManagedByteArray) -> bool { + let caller = self.blockchain().get_caller(); + let mut leaf_bytes = caller.as_managed_buffer().clone(); + + let p = power.to_bytes_be_buffer(); + leaf_bytes.append(&p); + + let mut hash = self.crypto().sha256(&leaf_bytes); + for proof_item in proof { + if BigUint::from(hash.as_managed_buffer()) < BigUint::from(proof_item.as_managed_buffer()) { + let mut tst = hash.as_managed_buffer().clone(); + tst.append(proof_item.as_managed_buffer()); + + hash = self.crypto().sha256(tst); + } else { + let mut tst = proof_item.as_managed_buffer().clone(); + tst.append(hash.as_managed_buffer()); + + hash = self.crypto().sha256(tst); + } + } + + hash == root_hash + } + #[storage_mapper("proposalRemainingFees")] fn proposal_remaining_fees(&self) -> SingleValueMapper>>; diff --git a/energy-integration/governance-v2/src/proposal.rs b/energy-integration/governance-v2/src/proposal.rs index 9c4190b0e..ba12bfb4d 100644 --- a/energy-integration/governance-v2/src/proposal.rs +++ b/energy-integration/governance-v2/src/proposal.rs @@ -1,6 +1,8 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); +pub const HASH_LENGTH: usize = 32; +pub const PROOF_LENGTH: usize = 18; pub const MAX_GOVERNANCE_PROPOSAL_ACTIONS: usize = 4; pub type ProposalId = usize; @@ -56,11 +58,12 @@ pub struct GovernanceProposal { pub proposer: ManagedAddress, pub actions: ArrayVec, MAX_GOVERNANCE_PROPOSAL_ACTIONS>, pub description: ManagedBuffer, + pub root_hash: ManagedByteArray, pub fee_payment: EsdtTokenPayment, pub minimum_quorum: BigUint, pub voting_delay_in_blocks: u64, pub voting_period_in_blocks: u64, pub withdraw_percentage_defeated: u64, - pub total_energy: BigUint, + pub total_voting_power: BigUint, pub proposal_start_block: u64, } diff --git a/energy-integration/governance-v2/src/views.rs b/energy-integration/governance-v2/src/views.rs index f5e93b2aa..55200675f 100644 --- a/energy-integration/governance-v2/src/views.rs +++ b/energy-integration/governance-v2/src/views.rs @@ -1,7 +1,7 @@ multiversx_sc::imports!(); use crate::{ - proposal::{GovernanceProposalStatus, ProposalId}, + proposal::{GovernanceProposalStatus, ProposalId, HASH_LENGTH}, FULL_PERCENTAGE, }; @@ -45,6 +45,15 @@ pub trait ViewsModule: } } + #[view(getProposalRootHash)] + fn get_root_hash(&self, proposal_id: ProposalId) -> OptionalValue> { + if !self.proposal_exists(proposal_id) { + return OptionalValue::None; + } + + OptionalValue::Some(self.proposals().get(proposal_id).root_hash) + } + fn vote_reached(&self, proposal_id: ProposalId) -> bool { let proposal_votes = self.proposal_votes(proposal_id).get(); let total_votes = proposal_votes.get_total_votes(); @@ -81,13 +90,13 @@ pub trait ViewsModule: fn quorum_reached(&self, proposal_id: ProposalId) -> bool { let proposal = self.proposals().get(proposal_id); - let total_energy_for_proposal = proposal.total_energy; + let total_voting_power_for_proposal = proposal.total_voting_power; let required_minimum_percentage = proposal.minimum_quorum; let current_quorum = self.proposal_votes(proposal_id).get().quorum; let current_quorum_percentage = - current_quorum * FULL_PERCENTAGE / total_energy_for_proposal; + current_quorum * FULL_PERCENTAGE / total_voting_power_for_proposal; current_quorum_percentage >= required_minimum_percentage } diff --git a/energy-integration/governance-v2/tests/gov_rust_test.rs b/energy-integration/governance-v2/tests/gov_rust_test.rs index 50f88b42d..9e42178b8 100644 --- a/energy-integration/governance-v2/tests/gov_rust_test.rs +++ b/energy-integration/governance-v2/tests/gov_rust_test.rs @@ -17,7 +17,9 @@ fn init_gov_test() { fn gov_propose_test() { let mut gov_setup = GovSetup::new(governance_v2::contract_obj); - let first_user_addr = gov_setup.first_user.clone(); + let first_user_addr = gov_setup.first_merkle_user.clone(); + let first_user_power = gov_setup.get_first_user_voting_power(); + let first_user_proof = gov_setup.first_merkle_proof(); let second_user_addr = gov_setup.second_user.clone(); let sc_addr = gov_setup.gov_wrapper.address_ref().clone(); let min_fee = rust_biguint!(MIN_FEE_FOR_PROPOSE) * DECIMALS_CONST; @@ -38,19 +40,19 @@ fn gov_propose_test() { // vote too early gov_setup - .up_vote(&second_user_addr, proposal_id) + .up_vote(&second_user_addr) .assert_user_error("Proposal is not active"); gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.up_vote(&first_user_addr, proposal_id).assert_ok(); + gov_setup.up_vote(&first_user_addr).assert_ok(); gov_setup - .up_vote(&second_user_addr, proposal_id) + .up_vote(&second_user_addr) .assert_ok(); // user 2 try vote again gov_setup - .up_vote(&second_user_addr, proposal_id) + .up_vote(&second_user_addr) .assert_user_error("Already voted for this proposal"); gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); @@ -118,9 +120,9 @@ fn gov_no_veto_vote_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.up_vote(&first_user_addr, proposal_id).assert_ok(); + gov_setup.up_vote(&first_user_addr).assert_ok(); gov_setup - .up_vote(&second_user_addr, proposal_id) + .up_vote(&second_user_addr) .assert_ok(); // Third User DownWithVetoVote = 1_100 @@ -166,7 +168,7 @@ fn gov_abstain_vote_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.up_vote(&first_user_addr, proposal_id).assert_ok(); + gov_setup.up_vote(&first_user_addr).assert_ok(); gov_setup .abstain_vote(&third_user_addr, proposal_id) .assert_ok(); @@ -208,7 +210,7 @@ fn gov_no_quorum_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.up_vote(&first_user_addr, proposal_id).assert_ok(); + gov_setup.up_vote(&first_user_addr).assert_ok(); gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); @@ -247,7 +249,7 @@ fn gov_modify_quorum_after_end_vote_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.up_vote(&first_user_addr, proposal_id).assert_ok(); + gov_setup.up_vote(&first_user_addr).assert_ok(); gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); @@ -258,7 +260,7 @@ fn gov_modify_quorum_after_end_vote_test() { sc.get_proposal_status(1) == GovernanceProposalStatus::Defeated, "Action should have been Defeated" ); - sc.try_change_quorum(managed_biguint!(QUORUM_PERCENTAGE / 2)); + sc.try_change_quorum_percentage(managed_biguint!(QUORUM_PERCENTAGE / 2)); assert!(sc.quorum_percentage().get() == managed_biguint!(QUORUM_PERCENTAGE / 2)); assert!( @@ -303,7 +305,7 @@ fn gov_withdraw_defeated_proposal_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.up_vote(&first_user_addr, proposal_id).assert_ok(); + gov_setup.up_vote(&first_user_addr).assert_ok(); gov_setup .down_vote(&third_user_addr, proposal_id) .assert_ok(); @@ -374,7 +376,7 @@ fn gov_modify_withdraw_defeated_proposal_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.up_vote(&first_user_addr, proposal_id).assert_ok(); + gov_setup.up_vote(&first_user_addr).assert_ok(); gov_setup .down_vote(&third_user_addr, proposal_id) .assert_ok(); @@ -449,7 +451,7 @@ fn gov_withdraw_no_with_veto_defeated_proposal_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.up_vote(&first_user_addr, proposal_id).assert_ok(); + gov_setup.up_vote(&first_user_addr).assert_ok(); gov_setup .down_veto_vote(&third_user_addr, proposal_id) .assert_ok(); diff --git a/energy-integration/governance-v2/tests/gov_test_setup/mod.rs b/energy-integration/governance-v2/tests/gov_test_setup/mod.rs index 3c02e7e09..8683d41f6 100644 --- a/energy-integration/governance-v2/tests/gov_test_setup/mod.rs +++ b/energy-integration/governance-v2/tests/gov_test_setup/mod.rs @@ -1,14 +1,12 @@ use energy_factory_mock::EnergyFactoryMock; use energy_query::Energy; -use fees_collector::FeesCollector; use governance_v2::{ - configurable::ConfigurablePropertiesModule, proposal_storage::{ProposalStorageModule, VoteType}, GovernanceV2, }; use multiversx_sc::{ - codec::multi_types::OptionalValue, - types::{Address, BigInt, ManagedVec, MultiValueEncoded}, + hex_literal::hex, + types::{Address, BigInt, ManagedByteArray, ManagedVec, MultiValueEncoded, BigUint}, arrayvec::ArrayVec, }; use multiversx_sc_scenario::{ managed_address, managed_biguint, managed_buffer, managed_token_id, rust_biguint, @@ -16,18 +14,17 @@ use multiversx_sc_scenario::{ whitebox::{BlockchainStateWrapper, ContractObjWrapper}, DebugApi, }; -use num_bigint::BigUint; -pub const MIN_ENERGY_FOR_PROPOSE: u64 = 500_000; pub const MIN_FEE_FOR_PROPOSE: u64 = 3_000_000; pub const QUORUM_PERCENTAGE: u64 = 5000; pub const VOTING_DELAY_BLOCKS: u64 = 10; pub const VOTING_PERIOD_BLOCKS: u64 = 14_500; pub const LOCKING_PERIOD_BLOCKS: u64 = 30; pub const WITHDRAW_PERCENTAGE: u64 = 5_000; // 50% -pub static WXMEX_TOKEN_ID: &[u8] = b"WXMEX-123456"; +pub const WXMEX_TOKEN_ID: &[u8] = b"WXMEX-123456"; pub const LOCKED_TOKEN_ID: &[u8] = b"LOCKED-abcdef"; pub const DECIMALS_CONST: u64 = 1_000_000_000_000_000_000; +pub const QUORUM: u64 = 217_433_990_694; pub const USER_ENERGY: u64 = 1_000_000; pub const GAS_LIMIT: u64 = 1_000_000; @@ -48,6 +45,9 @@ where pub first_user: Address, pub second_user: Address, pub third_user: Address, + pub first_merkle_user: Address, + pub second_merkle_user: Address, + pub third_merkle_user: Address, pub gov_wrapper: ContractObjWrapper, GovBuilder>, pub current_block: u64, } @@ -63,6 +63,16 @@ where let first_user = b_mock.create_user_account(&rust_zero); let second_user = b_mock.create_user_account(&rust_zero); let third_user = b_mock.create_user_account(&rust_zero); + let first_merkle_user = Address::from(&hex!( + "25ee243280fc6e740424a28fa40c795458943b475cd77f3778f9c8e0b4a1e7f8" + )); + let second_merkle_user = Address::from(&hex!( + "0d5acc0ee5a229ae549dad903fb7bcbc1f80b67198949f02fd611d25d41689cb" + )); + let third_merkle_user = Address::from(&hex!( + "190c55b8f27547244c65ad13cbbe7457d5fb90481f34b84160a1cf6e44e0875c" + )); + b_mock.create_user_account_fixed_address(&first_merkle_user, &rust_zero); // init energy factory let energy_factory_wrapper = b_mock.create_sc_account( @@ -72,14 +82,6 @@ where "energy factory path", ); - // init fees collector - let fees_collector_wrapper = b_mock.create_sc_account( - &rust_biguint!(0), - None, - fees_collector::contract_obj, - "fees collector path", - ); - b_mock .execute_tx(&owner, &energy_factory_wrapper, &rust_zero, |sc| { sc.init(); @@ -104,48 +106,6 @@ where }) .assert_ok(); - b_mock - .execute_tx(&owner, &fees_collector_wrapper, &rust_biguint!(0), |sc| { - sc.init( - managed_token_id!(LOCKED_TOKEN_ID), - managed_address!(energy_factory_wrapper.address_ref()), - ); - }) - .assert_ok(); - - b_mock - .execute_tx( - &first_user, - &fees_collector_wrapper, - &rust_biguint!(0), - |sc| { - sc.claim_rewards(OptionalValue::None); - }, - ) - .assert_ok(); - - b_mock - .execute_tx( - &second_user, - &fees_collector_wrapper, - &rust_biguint!(0), - |sc| { - sc.claim_rewards(OptionalValue::None); - }, - ) - .assert_ok(); - - b_mock - .execute_tx( - &third_user, - &fees_collector_wrapper, - &rust_biguint!(0), - |sc| { - sc.claim_rewards(OptionalValue::None); - }, - ) - .assert_ok(); - // init governance sc let gov_wrapper = b_mock.create_sc_account(&rust_zero, Some(&owner), gov_builder, "gov path"); @@ -154,31 +114,26 @@ where b_mock .execute_tx(&owner, &gov_wrapper, &rust_zero, |sc| { sc.init( - managed_biguint!(MIN_ENERGY_FOR_PROPOSE), managed_biguint!(MIN_FEE_FOR_PROPOSE) * DECIMALS_CONST, managed_biguint!(QUORUM_PERCENTAGE), VOTING_DELAY_BLOCKS, VOTING_PERIOD_BLOCKS, WITHDRAW_PERCENTAGE, managed_address!(energy_factory_wrapper.address_ref()), - managed_address!(fees_collector_wrapper.address_ref()), managed_token_id!(WXMEX_TOKEN_ID), ); }) .assert_ok(); - b_mock - .execute_tx(&owner, &gov_wrapper, &rust_zero, |sc| { - sc.fee_token_id().set(managed_token_id!(WXMEX_TOKEN_ID)); - }) - .assert_ok(); - Self { b_mock, owner, first_user, second_user, third_user, + first_merkle_user, + second_merkle_user, + third_merkle_user, gov_wrapper, current_block: 0, } @@ -186,8 +141,9 @@ where pub fn propose( &mut self, + root_hash: ManagedByteArray, proposer: &Address, - fee_amount: &BigUint, + fee_amount: &BigUint, dest_address: &Address, endpoint_name: &[u8], args: Vec>, @@ -216,38 +172,43 @@ where .into(), ); - proposal_id = sc.propose(managed_buffer!(b"changeTODO"), actions); + proposal_id = sc.propose( + root_hash, + managed_biguint!(QUORUM), + managed_buffer!(b"changeTODO"), + actions, + ); }, ); (result, proposal_id) } - pub fn up_vote(&mut self, voter: &Address, proposal_id: usize) -> TxResult { + pub fn up_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { self.b_mock .execute_tx(voter, &self.gov_wrapper, &rust_biguint!(0), |sc| { - sc.vote(proposal_id, VoteType::UpVote); + sc.vote(proposal_id, VoteType::UpVote, power.clone(), proof.clone()); }) } - pub fn down_vote(&mut self, voter: &Address, proposal_id: usize) -> TxResult { + pub fn down_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { self.b_mock .execute_tx(voter, &self.gov_wrapper, &rust_biguint!(0), |sc| { - sc.vote(proposal_id, VoteType::DownVote); + sc.vote(proposal_id, VoteType::DownVote, power.clone(), proof.clone()); }) } - pub fn down_veto_vote(&mut self, voter: &Address, proposal_id: usize) -> TxResult { + pub fn down_veto_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { self.b_mock .execute_tx(voter, &self.gov_wrapper, &rust_biguint!(0), |sc| { - sc.vote(proposal_id, VoteType::DownVetoVote); + sc.vote(proposal_id, VoteType::DownVetoVote, power.clone(), proof.clone()); }) } - pub fn abstain_vote(&mut self, voter: &Address, proposal_id: usize) -> TxResult { + pub fn abstain_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { self.b_mock .execute_tx(voter, &self.gov_wrapper, &rust_biguint!(0), |sc| { - sc.vote(proposal_id, VoteType::AbstainVote); + sc.vote(proposal_id, VoteType::AbstainVote, power.clone(), proof.clone()); }) } @@ -283,4 +244,91 @@ where self.current_block += inc_amount; self.b_mock.set_block_nonce(self.current_block); } + pub fn first_merkle_proof(&self) -> ArrayVec, 18> { + ArrayVec::from([ + ManagedByteArray::from(&hex!("5e9e904152b2a06dafc26aa02b8c55b2ec3370cdf55b06b15fe8c94bc56e43fc")), + ManagedByteArray::from(&hex!("47aa547fa524519bc946d0883591e9d273a65b4a8f06a37baf170c707c4fb782")), + ManagedByteArray::from(&hex!("da05a587448779b9368680f0ee745b3ff2df1132e309a2de518aa9814cc25de8")), + ManagedByteArray::from(&hex!("14ae69620e727d8e899119ef7a1f04191f15f7c704c2673445510a1bbce7edb2")), + ManagedByteArray::from(&hex!("449e8beb9a901efc2815253a2ce416e3b98ff771fdfc9e35f4ce31004003e533")), + ManagedByteArray::from(&hex!("fdf33783f8de396173fd37b558213117bb2be3430d50b18eeb5da1af0b98fd66")), + ManagedByteArray::from(&hex!("889a7d403faae66ec51db6b0708d889ca277e2fd64f78e47612c07077df6eccc")), + ManagedByteArray::from(&hex!("5cc55493d05c9bf63431384f184e0cc6ab13c14509c3e9a64dc49b47e3821c6f")), + ManagedByteArray::from(&hex!("ca559e91dee09fccf8d3dbf9bda81f57d4094faecf2f9ac3a98e84b3f376c81c")), + ManagedByteArray::from(&hex!("781cf1316f87a336a7219095aa8b523a821d260ca0b7a7f94af5c769e17c8f82")), + ManagedByteArray::from(&hex!("5e97339ee010d2ae3ac54c38c7158e7a7ef4311f89b28b4634d0d35fd4097dc0")), + ManagedByteArray::from(&hex!("2c7b2103c3e48386a7eda174cec726c28ec6ce80466deaac49dbaf469f35d059")), + ManagedByteArray::from(&hex!("9b2ceb7809f078724efb71ea3542885c990985d41746d4cab7948928384c3a4c")), + ManagedByteArray::from(&hex!("b1f37e46c3f84a3c68804d62b26b7f035c90f344252d77fdeff2393793ae34d4")), + ManagedByteArray::from(&hex!("95ead464db14a9a65c3b9c5378cf927b76ff530ae0762dbb6456bfeb467f97b2")), + ManagedByteArray::from(&hex!("39e10ed734ddaa3098edc6300edeed2fce75780fc718140359b13c58045a1838")), + ManagedByteArray::from(&hex!("b36fbf7a645b24bab3eaca5c351985f6bbb95723b47db78171dd7d7f8883ecad")), + ManagedByteArray::from(&hex!("bffe20aa722c488465e18d10ac3abe3002603bbd4c535211d9bd9b34ce7259a1")), + ]) + } + + pub fn second_merkle_proof(&self) -> ArrayVec, 18> { + ArrayVec::from([ + ManagedByteArray::from(&hex!("b1d7a256ae6b35cce14497b3735d71dd205f099f1a035a7a5cb96e8bf5c32f31")), + ManagedByteArray::from(&hex!("81dc00d137001723d5654e3120d63601b08ca2b4b8dc41802476529e6d6ada9e")), + ManagedByteArray::from(&hex!("985e3554adfefea5d2c3f7c93d404fd547cfead9054ce313845656507037df40")), + ManagedByteArray::from(&hex!("14ae69620e727d8e899119ef7a1f04191f15f7c704c2673445510a1bbce7edb2")), + ManagedByteArray::from(&hex!("449e8beb9a901efc2815253a2ce416e3b98ff771fdfc9e35f4ce31004003e533")), + ManagedByteArray::from(&hex!("fdf33783f8de396173fd37b558213117bb2be3430d50b18eeb5da1af0b98fd66")), + ManagedByteArray::from(&hex!("889a7d403faae66ec51db6b0708d889ca277e2fd64f78e47612c07077df6eccc")), + ManagedByteArray::from(&hex!("5cc55493d05c9bf63431384f184e0cc6ab13c14509c3e9a64dc49b47e3821c6f")), + ManagedByteArray::from(&hex!("ca559e91dee09fccf8d3dbf9bda81f57d4094faecf2f9ac3a98e84b3f376c81c")), + ManagedByteArray::from(&hex!("781cf1316f87a336a7219095aa8b523a821d260ca0b7a7f94af5c769e17c8f82")), + ManagedByteArray::from(&hex!("5e97339ee010d2ae3ac54c38c7158e7a7ef4311f89b28b4634d0d35fd4097dc0")), + ManagedByteArray::from(&hex!("2c7b2103c3e48386a7eda174cec726c28ec6ce80466deaac49dbaf469f35d059")), + ManagedByteArray::from(&hex!("9b2ceb7809f078724efb71ea3542885c990985d41746d4cab7948928384c3a4c")), + ManagedByteArray::from(&hex!("b1f37e46c3f84a3c68804d62b26b7f035c90f344252d77fdeff2393793ae34d4")), + ManagedByteArray::from(&hex!("95ead464db14a9a65c3b9c5378cf927b76ff530ae0762dbb6456bfeb467f97b2")), + ManagedByteArray::from(&hex!("39e10ed734ddaa3098edc6300edeed2fce75780fc718140359b13c58045a1838")), + ManagedByteArray::from(&hex!("b36fbf7a645b24bab3eaca5c351985f6bbb95723b47db78171dd7d7f8883ecad")), + ManagedByteArray::from(&hex!("bffe20aa722c488465e18d10ac3abe3002603bbd4c535211d9bd9b34ce7259a1")), + ]) + } + + pub fn third_merkle_proof(&self) -> ArrayVec, 18> { + ArrayVec::from([ + ManagedByteArray::from(&hex!("aa68ae7eac4de3cc643717d33ab7d2e1b098788b127f298f23a34e8720ec609d")), + ManagedByteArray::from(&hex!("e3db2cf9f85b49279eba44b0f62ac2c6bcdf870f198b9484344634a58860ba2d")), + ManagedByteArray::from(&hex!("64468b8481d2c1737977e7382eaaa12c8072ee76fda33c3b6aaa193b38d4f1f2")), + ManagedByteArray::from(&hex!("6159dc0c80183e89221a36db3fedfabe38933d0db73c1156ad32d8caf0537085")), + ManagedByteArray::from(&hex!("449e8beb9a901efc2815253a2ce416e3b98ff771fdfc9e35f4ce31004003e533")), + ManagedByteArray::from(&hex!("fdf33783f8de396173fd37b558213117bb2be3430d50b18eeb5da1af0b98fd66")), + ManagedByteArray::from(&hex!("889a7d403faae66ec51db6b0708d889ca277e2fd64f78e47612c07077df6eccc")), + ManagedByteArray::from(&hex!("5cc55493d05c9bf63431384f184e0cc6ab13c14509c3e9a64dc49b47e3821c6f")), + ManagedByteArray::from(&hex!("ca559e91dee09fccf8d3dbf9bda81f57d4094faecf2f9ac3a98e84b3f376c81c")), + ManagedByteArray::from(&hex!("781cf1316f87a336a7219095aa8b523a821d260ca0b7a7f94af5c769e17c8f82")), + ManagedByteArray::from(&hex!("5e97339ee010d2ae3ac54c38c7158e7a7ef4311f89b28b4634d0d35fd4097dc0")), + ManagedByteArray::from(&hex!("2c7b2103c3e48386a7eda174cec726c28ec6ce80466deaac49dbaf469f35d059")), + ManagedByteArray::from(&hex!("9b2ceb7809f078724efb71ea3542885c990985d41746d4cab7948928384c3a4c")), + ManagedByteArray::from(&hex!("b1f37e46c3f84a3c68804d62b26b7f035c90f344252d77fdeff2393793ae34d4")), + ManagedByteArray::from(&hex!("95ead464db14a9a65c3b9c5378cf927b76ff530ae0762dbb6456bfeb467f97b2")), + ManagedByteArray::from(&hex!("39e10ed734ddaa3098edc6300edeed2fce75780fc718140359b13c58045a1838")), + ManagedByteArray::from(&hex!("b36fbf7a645b24bab3eaca5c351985f6bbb95723b47db78171dd7d7f8883ecad")), + ManagedByteArray::from(&hex!("bffe20aa722c488465e18d10ac3abe3002603bbd4c535211d9bd9b34ce7259a1")), + + ]) + } + + + pub fn get_first_user_voting_power(&self) -> BigUint { + managed_biguint!(217433990694) + } + + pub fn get_second_user_voting_power(&self) -> BigUint { + managed_biguint!(59024824840) + } + + pub fn get_third_user_voting_power(&self) -> BigUint { + managed_biguint!(40000000000) + } + + pub fn get_merkle_root_hash(&self) -> ManagedByteArray { + ManagedByteArray::from(&hex!("0fdb09afb35351d5becc3a79dd9bf03bae7c2366d186a6c8e8276f545d024ef5")) + } + } From 89ba184f52534da94d52df0dad712bd1f1d2e97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Wed, 26 Jul 2023 15:03:57 +0300 Subject: [PATCH 02/12] governance-v2: Fix tests --- .../governance-v2/tests/gov_rust_test.rs | 151 +++++++++++++----- .../governance-v2/tests/gov_test_setup/mod.rs | 43 ++--- 2 files changed, 137 insertions(+), 57 deletions(-) diff --git a/energy-integration/governance-v2/tests/gov_rust_test.rs b/energy-integration/governance-v2/tests/gov_rust_test.rs index 9e42178b8..c0b885c31 100644 --- a/energy-integration/governance-v2/tests/gov_rust_test.rs +++ b/energy-integration/governance-v2/tests/gov_rust_test.rs @@ -20,15 +20,19 @@ fn gov_propose_test() { let first_user_addr = gov_setup.first_merkle_user.clone(); let first_user_power = gov_setup.get_first_user_voting_power(); let first_user_proof = gov_setup.first_merkle_proof(); - let second_user_addr = gov_setup.second_user.clone(); + let second_user_addr = gov_setup.second_merkle_user.clone(); + let second_user_power = gov_setup.get_second_user_voting_power(); + let second_user_proof = gov_setup.second_merkle_proof(); let sc_addr = gov_setup.gov_wrapper.address_ref().clone(); let min_fee = rust_biguint!(MIN_FEE_FOR_PROPOSE) * DECIMALS_CONST; + // Give proposer the minimum fee gov_setup .b_mock .set_nft_balance(&first_user_addr, WXMEX_TOKEN_ID, 1, &min_fee, &Empty); let (result, proposal_id) = gov_setup.propose( + gov_setup.get_merkle_root_hash(), &first_user_addr, &min_fee, &sc_addr, @@ -40,19 +44,41 @@ fn gov_propose_test() { // vote too early gov_setup - .up_vote(&second_user_addr) + .up_vote( + &second_user_addr, + &second_user_power, + &second_user_proof, + proposal_id, + ) .assert_user_error("Proposal is not active"); gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.up_vote(&first_user_addr).assert_ok(); gov_setup - .up_vote(&second_user_addr) + .up_vote( + &first_user_addr, + &first_user_power, + &first_user_proof, + proposal_id, + ) + .assert_ok(); + gov_setup + .up_vote( + &second_user_addr, + &second_user_power, + &second_user_proof, + proposal_id, + ) .assert_ok(); // user 2 try vote again gov_setup - .up_vote(&second_user_addr) + .up_vote( + &second_user_addr, + &second_user_power, + &second_user_proof, + proposal_id, + ) .assert_user_error("Already voted for this proposal"); gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); @@ -88,9 +114,16 @@ fn gov_propose_test() { fn gov_no_veto_vote_test() { let mut gov_setup = GovSetup::new(governance_v2::contract_obj); - let first_user_addr = gov_setup.first_user.clone(); - let second_user_addr = gov_setup.second_user.clone(); - let third_user_addr = gov_setup.third_user.clone(); + let first_user_addr = gov_setup.first_merkle_user.clone(); + let first_user_power = gov_setup.get_first_user_voting_power(); + let first_user_proof = gov_setup.first_merkle_proof(); + let second_user_addr = gov_setup.second_merkle_user.clone(); + let second_user_power = gov_setup.get_second_user_voting_power(); + let second_user_proof = gov_setup.second_merkle_proof(); + let third_user_addr = gov_setup.third_merkle_user.clone(); + let third_user_power = gov_setup.get_third_user_voting_power(); + let third_user_proof = gov_setup.third_merkle_proof(); + let sc_addr = gov_setup.gov_wrapper.address_ref().clone(); let min_fee = rust_biguint!(MIN_FEE_FOR_PROPOSE) * DECIMALS_CONST; // Give proposer the minimum fee @@ -99,6 +132,7 @@ fn gov_no_veto_vote_test() { .set_nft_balance(&first_user_addr, WXMEX_TOKEN_ID, 1, &min_fee, &Empty); let (result, proposal_id) = gov_setup.propose( + gov_setup.get_merkle_root_hash(), &first_user_addr, &min_fee, &sc_addr, @@ -120,14 +154,26 @@ fn gov_no_veto_vote_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.up_vote(&first_user_addr).assert_ok(); gov_setup - .up_vote(&second_user_addr) + .down_veto_vote( + &first_user_addr, + &first_user_power, + &first_user_proof, + proposal_id, + ) + .assert_ok(); + gov_setup + .up_vote( + &second_user_addr, + &second_user_power, + &second_user_proof, + proposal_id, + ) .assert_ok(); // Third User DownWithVetoVote = 1_100 gov_setup - .down_veto_vote(&third_user_addr, proposal_id) + .up_vote(&third_user_addr, &third_user_power, &third_user_proof, proposal_id) .assert_ok(); gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); @@ -147,8 +193,12 @@ fn gov_no_veto_vote_test() { fn gov_abstain_vote_test() { let mut gov_setup = GovSetup::new(governance_v2::contract_obj); - let first_user_addr = gov_setup.first_user.clone(); - let third_user_addr = gov_setup.third_user.clone(); + let first_user_addr = gov_setup.first_merkle_user.clone(); + let first_user_power = gov_setup.get_first_user_voting_power(); + let first_user_proof = gov_setup.first_merkle_proof(); + let third_user_addr = gov_setup.third_merkle_user.clone(); + let third_user_power = gov_setup.get_third_user_voting_power(); + let third_user_proof = gov_setup.third_merkle_proof(); let sc_addr = gov_setup.gov_wrapper.address_ref().clone(); let min_fee = rust_biguint!(MIN_FEE_FOR_PROPOSE) * DECIMALS_CONST; // Give proposer the minimum fee @@ -157,6 +207,7 @@ fn gov_abstain_vote_test() { .set_nft_balance(&first_user_addr, WXMEX_TOKEN_ID, 1, &min_fee, &Empty); let (result, proposal_id) = gov_setup.propose( + gov_setup.get_merkle_root_hash(), &first_user_addr, &min_fee, &sc_addr, @@ -168,9 +219,9 @@ fn gov_abstain_vote_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.up_vote(&first_user_addr).assert_ok(); + gov_setup.abstain_vote(&first_user_addr, &first_user_power, &first_user_proof, proposal_id).assert_ok(); gov_setup - .abstain_vote(&third_user_addr, proposal_id) + .up_vote(&third_user_addr, &third_user_power, &third_user_proof, proposal_id) .assert_ok(); gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); @@ -190,7 +241,10 @@ fn gov_abstain_vote_test() { fn gov_no_quorum_test() { let mut gov_setup = GovSetup::new(governance_v2::contract_obj); - let first_user_addr = gov_setup.first_user.clone(); + let first_user_addr = gov_setup.first_merkle_user.clone(); + let third_user_addr = gov_setup.third_merkle_user.clone(); + let third_user_power = gov_setup.get_third_user_voting_power(); + let third_user_proof = gov_setup.third_merkle_proof(); let sc_addr = gov_setup.gov_wrapper.address_ref().clone(); let min_fee = rust_biguint!(MIN_FEE_FOR_PROPOSE) * DECIMALS_CONST; // Give proposer the minimum fee @@ -199,6 +253,7 @@ fn gov_no_quorum_test() { .set_nft_balance(&first_user_addr, WXMEX_TOKEN_ID, 1, &min_fee, &Empty); let (result, proposal_id) = gov_setup.propose( + gov_setup.get_merkle_root_hash(), &first_user_addr, &min_fee, &sc_addr, @@ -210,7 +265,7 @@ fn gov_no_quorum_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.up_vote(&first_user_addr).assert_ok(); + gov_setup.up_vote(&third_user_addr, &third_user_power, &third_user_proof, proposal_id).assert_ok(); gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); @@ -229,7 +284,10 @@ fn gov_no_quorum_test() { fn gov_modify_quorum_after_end_vote_test() { let mut gov_setup = GovSetup::new(governance_v2::contract_obj); - let first_user_addr = gov_setup.first_user.clone(); + let first_user_addr = gov_setup.first_merkle_user.clone(); + let third_user_addr = gov_setup.third_merkle_user.clone(); + let third_user_power = gov_setup.get_third_user_voting_power(); + let third_user_proof = gov_setup.third_merkle_proof(); let sc_addr = gov_setup.gov_wrapper.address_ref().clone(); let min_fee = rust_biguint!(MIN_FEE_FOR_PROPOSE) * DECIMALS_CONST; // Give proposer the minimum fee @@ -238,6 +296,7 @@ fn gov_modify_quorum_after_end_vote_test() { .set_nft_balance(&first_user_addr, WXMEX_TOKEN_ID, 1, &min_fee, &Empty); let (result, proposal_id) = gov_setup.propose( + gov_setup.get_merkle_root_hash(), &first_user_addr, &min_fee, &sc_addr, @@ -247,11 +306,11 @@ fn gov_modify_quorum_after_end_vote_test() { result.assert_ok(); assert_eq!(proposal_id, 1); - gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); + gov_setup.increment_block_nonce(VOTING_DELAY_BLOCKS); - gov_setup.up_vote(&first_user_addr).assert_ok(); + gov_setup.up_vote(&third_user_addr, &third_user_power, &third_user_proof, proposal_id).assert_ok(); - gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); + gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); gov_setup .b_mock @@ -275,8 +334,12 @@ fn gov_modify_quorum_after_end_vote_test() { fn gov_withdraw_defeated_proposal_test() { let mut gov_setup = GovSetup::new(governance_v2::contract_obj); - let first_user_addr = gov_setup.first_user.clone(); - let third_user_addr = gov_setup.third_user.clone(); + let first_user_addr = gov_setup.first_merkle_user.clone(); + let first_user_power = gov_setup.get_first_user_voting_power(); + let first_user_proof = gov_setup.first_merkle_proof(); + let third_user_addr = gov_setup.third_merkle_user.clone(); + let third_user_power = gov_setup.get_third_user_voting_power(); + let third_user_proof = gov_setup.third_merkle_proof(); let sc_addr = gov_setup.gov_wrapper.address_ref().clone(); let min_fee = rust_biguint!(MIN_FEE_FOR_PROPOSE) * DECIMALS_CONST; // Give proposer the minimum fee @@ -285,6 +348,7 @@ fn gov_withdraw_defeated_proposal_test() { .set_nft_balance(&first_user_addr, WXMEX_TOKEN_ID, 1, &min_fee, &Empty); let (result, proposal_id) = gov_setup.propose( + gov_setup.get_merkle_root_hash(), &first_user_addr, &min_fee, &sc_addr, @@ -303,14 +367,14 @@ fn gov_withdraw_defeated_proposal_test() { None, ); - gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); + gov_setup.increment_block_nonce(VOTING_DELAY_BLOCKS); - gov_setup.up_vote(&first_user_addr).assert_ok(); + gov_setup.down_vote(&first_user_addr, &first_user_power, &first_user_proof, proposal_id).assert_ok(); gov_setup - .down_vote(&third_user_addr, proposal_id) + .up_vote(&third_user_addr, &third_user_power, &third_user_proof, proposal_id) .assert_ok(); - gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); + gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); gov_setup .b_mock @@ -346,8 +410,12 @@ fn gov_withdraw_defeated_proposal_test() { fn gov_modify_withdraw_defeated_proposal_test() { let mut gov_setup = GovSetup::new(governance_v2::contract_obj); - let first_user_addr = gov_setup.first_user.clone(); - let third_user_addr = gov_setup.third_user.clone(); + let first_user_addr = gov_setup.first_merkle_user.clone(); + let first_user_power = gov_setup.get_first_user_voting_power(); + let first_user_proof = gov_setup.first_merkle_proof(); + let third_user_addr = gov_setup.third_merkle_user.clone(); + let third_user_power = gov_setup.get_third_user_voting_power(); + let third_user_proof = gov_setup.third_merkle_proof(); let sc_addr = gov_setup.gov_wrapper.address_ref().clone(); let min_fee = rust_biguint!(MIN_FEE_FOR_PROPOSE) * DECIMALS_CONST; // Give proposer the minimum fee @@ -356,6 +424,7 @@ fn gov_modify_withdraw_defeated_proposal_test() { .set_nft_balance(&first_user_addr, WXMEX_TOKEN_ID, 1, &min_fee, &Empty); let (result, proposal_id) = gov_setup.propose( + gov_setup.get_merkle_root_hash(), &first_user_addr, &min_fee, &sc_addr, @@ -376,9 +445,9 @@ fn gov_modify_withdraw_defeated_proposal_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.up_vote(&first_user_addr).assert_ok(); + gov_setup.down_vote(&first_user_addr, &first_user_power, &first_user_proof, proposal_id).assert_ok(); gov_setup - .down_vote(&third_user_addr, proposal_id) + .up_vote(&third_user_addr, &third_user_power, &third_user_proof, proposal_id) .assert_ok(); gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); @@ -421,8 +490,12 @@ fn gov_modify_withdraw_defeated_proposal_test() { fn gov_withdraw_no_with_veto_defeated_proposal_test() { let mut gov_setup = GovSetup::new(governance_v2::contract_obj); - let first_user_addr = gov_setup.first_user.clone(); - let third_user_addr = gov_setup.third_user.clone(); + let first_user_addr = gov_setup.first_merkle_user.clone(); + let first_user_power = gov_setup.get_first_user_voting_power(); + let first_user_proof = gov_setup.first_merkle_proof(); + let third_user_addr = gov_setup.third_merkle_user.clone(); + let third_user_power = gov_setup.get_third_user_voting_power(); + let third_user_proof = gov_setup.third_merkle_proof(); let sc_addr = gov_setup.gov_wrapper.address_ref().clone(); let min_fee = rust_biguint!(MIN_FEE_FOR_PROPOSE) * DECIMALS_CONST; // Give proposer the minimum fee @@ -431,6 +504,7 @@ fn gov_withdraw_no_with_veto_defeated_proposal_test() { .set_nft_balance(&first_user_addr, WXMEX_TOKEN_ID, 1, &min_fee, &Empty); let (result, proposal_id) = gov_setup.propose( + gov_setup.get_merkle_root_hash(), &first_user_addr, &min_fee, &sc_addr, @@ -451,9 +525,9 @@ fn gov_withdraw_no_with_veto_defeated_proposal_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.up_vote(&first_user_addr).assert_ok(); + gov_setup.down_veto_vote(&first_user_addr, &first_user_power, &first_user_proof, proposal_id).assert_ok(); gov_setup - .down_veto_vote(&third_user_addr, proposal_id) + .up_vote(&third_user_addr, &third_user_power, &third_user_proof, proposal_id) .assert_ok(); gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); @@ -492,7 +566,7 @@ fn gov_withdraw_no_with_veto_defeated_proposal_test() { fn gov_propose_cancel_proposal_id_test() { let mut gov_setup = GovSetup::new(governance_v2::contract_obj); - let first_user_addr = gov_setup.first_user.clone(); + let first_user_addr = gov_setup.first_merkle_user.clone(); let sc_addr = gov_setup.gov_wrapper.address_ref().clone(); let min_fee = rust_biguint!(MIN_FEE_FOR_PROPOSE) * DECIMALS_CONST; // Give proposer the minimum fee @@ -505,6 +579,7 @@ fn gov_propose_cancel_proposal_id_test() { ); let (result, proposal_id) = gov_setup.propose( + gov_setup.get_merkle_root_hash(), &first_user_addr, &min_fee, &sc_addr, @@ -519,6 +594,7 @@ fn gov_propose_cancel_proposal_id_test() { // Proposal ID = 2 let (result, proposal_id) = gov_setup.propose( + gov_setup.get_merkle_root_hash(), &first_user_addr, &min_fee, &sc_addr, @@ -533,6 +609,7 @@ fn gov_propose_cancel_proposal_id_test() { // Proposal ID = 3 let (result, proposal_id) = gov_setup.propose( + gov_setup.get_merkle_root_hash(), &first_user_addr, &min_fee, &sc_addr, @@ -567,6 +644,7 @@ fn gov_propose_cancel_proposal_id_test() { // Proposal ID = 4 let (result, proposal_id) = gov_setup.propose( + gov_setup.get_merkle_root_hash(), &first_user_addr, &min_fee, &sc_addr, @@ -583,6 +661,7 @@ fn gov_propose_cancel_proposal_id_test() { // Proposal ID = 5 let (result, proposal_id) = gov_setup.propose( + gov_setup.get_merkle_root_hash(), &first_user_addr, &min_fee, &sc_addr, diff --git a/energy-integration/governance-v2/tests/gov_test_setup/mod.rs b/energy-integration/governance-v2/tests/gov_test_setup/mod.rs index 8683d41f6..171888ec7 100644 --- a/energy-integration/governance-v2/tests/gov_test_setup/mod.rs +++ b/energy-integration/governance-v2/tests/gov_test_setup/mod.rs @@ -6,7 +6,7 @@ use governance_v2::{ }; use multiversx_sc::{ hex_literal::hex, - types::{Address, BigInt, ManagedByteArray, ManagedVec, MultiValueEncoded, BigUint}, arrayvec::ArrayVec, + types::{Address, BigInt, ManagedByteArray, ManagedVec, MultiValueEncoded}, arrayvec::ArrayVec, }; use multiversx_sc_scenario::{ managed_address, managed_biguint, managed_buffer, managed_token_id, rust_biguint, @@ -14,6 +14,7 @@ use multiversx_sc_scenario::{ whitebox::{BlockchainStateWrapper, ContractObjWrapper}, DebugApi, }; +use num_bigint::BigUint; pub const MIN_FEE_FOR_PROPOSE: u64 = 3_000_000; pub const QUORUM_PERCENTAGE: u64 = 5000; @@ -22,11 +23,10 @@ pub const VOTING_PERIOD_BLOCKS: u64 = 14_500; pub const LOCKING_PERIOD_BLOCKS: u64 = 30; pub const WITHDRAW_PERCENTAGE: u64 = 5_000; // 50% pub const WXMEX_TOKEN_ID: &[u8] = b"WXMEX-123456"; -pub const LOCKED_TOKEN_ID: &[u8] = b"LOCKED-abcdef"; pub const DECIMALS_CONST: u64 = 1_000_000_000_000_000_000; pub const QUORUM: u64 = 217_433_990_694; -pub const USER_ENERGY: u64 = 1_000_000; +pub const VOTING_POWER: u64 = 1_000_000; pub const GAS_LIMIT: u64 = 1_000_000; #[derive(Clone)] @@ -57,6 +57,7 @@ where GovBuilder: 'static + Copy + Fn() -> governance_v2::ContractObj, { pub fn new(gov_builder: GovBuilder) -> Self { + let _ = DebugApi::dummy(); let rust_zero = rust_biguint!(0); let mut b_mock = BlockchainStateWrapper::new(); let owner = b_mock.create_user_account(&rust_zero); @@ -87,19 +88,19 @@ where sc.init(); sc.user_energy(&managed_address!(&first_user)) .set(&Energy::new( - BigInt::from(managed_biguint!(USER_ENERGY)), + BigInt::from(managed_biguint!(VOTING_POWER)), 0, managed_biguint!(0), )); sc.user_energy(&managed_address!(&second_user)) .set(&Energy::new( - BigInt::from(managed_biguint!(USER_ENERGY)), + BigInt::from(managed_biguint!(VOTING_POWER)), 0, managed_biguint!(0), )); sc.user_energy(&managed_address!(&third_user)) .set(&Energy::new( - BigInt::from(managed_biguint!(USER_ENERGY + 210_000)), + BigInt::from(managed_biguint!(VOTING_POWER + 210_000)), 0, managed_biguint!(0), )); @@ -143,7 +144,7 @@ where &mut self, root_hash: ManagedByteArray, proposer: &Address, - fee_amount: &BigUint, + fee_amount: &BigUint, dest_address: &Address, endpoint_name: &[u8], args: Vec>, @@ -184,31 +185,31 @@ where (result, proposal_id) } - pub fn up_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { + pub fn up_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { self.b_mock .execute_tx(voter, &self.gov_wrapper, &rust_biguint!(0), |sc| { - sc.vote(proposal_id, VoteType::UpVote, power.clone(), proof.clone()); + sc.vote(proposal_id, VoteType::UpVote, power.into(), proof.clone()); }) } - pub fn down_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { + pub fn down_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { self.b_mock .execute_tx(voter, &self.gov_wrapper, &rust_biguint!(0), |sc| { - sc.vote(proposal_id, VoteType::DownVote, power.clone(), proof.clone()); + sc.vote(proposal_id, VoteType::DownVote, power.into(), proof.clone()); }) } - pub fn down_veto_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { + pub fn down_veto_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { self.b_mock .execute_tx(voter, &self.gov_wrapper, &rust_biguint!(0), |sc| { - sc.vote(proposal_id, VoteType::DownVetoVote, power.clone(), proof.clone()); + sc.vote(proposal_id, VoteType::DownVetoVote, power.into(), proof.clone()); }) } - pub fn abstain_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { + pub fn abstain_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { self.b_mock .execute_tx(voter, &self.gov_wrapper, &rust_biguint!(0), |sc| { - sc.vote(proposal_id, VoteType::AbstainVote, power.clone(), proof.clone()); + sc.vote(proposal_id, VoteType::AbstainVote, power.into(), proof.clone()); }) } @@ -315,16 +316,16 @@ where } - pub fn get_first_user_voting_power(&self) -> BigUint { - managed_biguint!(217433990694) + pub fn get_first_user_voting_power(&self) -> BigUint { + BigUint::from(217_433_990_694u64) } - pub fn get_second_user_voting_power(&self) -> BigUint { - managed_biguint!(59024824840) + pub fn get_second_user_voting_power(&self) -> BigUint { + BigUint::from(59_024_824_840u64) } - pub fn get_third_user_voting_power(&self) -> BigUint { - managed_biguint!(40000000000) + pub fn get_third_user_voting_power(&self) -> BigUint { + BigUint::from(40_000_000_000u64) } pub fn get_merkle_root_hash(&self) -> ManagedByteArray { From db6743c305940f1ca8645cbc977c96b5b2b750b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Thu, 27 Jul 2023 12:41:35 +0300 Subject: [PATCH 03/12] Governance-v2:voting power is sqrt of user balance Fix tests --- .../governance-v2/src/errors.rs | 2 +- energy-integration/governance-v2/src/lib.rs | 59 ++-- .../governance-v2/src/proposal.rs | 2 +- energy-integration/governance-v2/src/views.rs | 14 +- .../governance-v2/tests/gov_rust_test.rs | 93 +++++- .../governance-v2/tests/gov_test_setup/mod.rs | 315 ++++++++++++------ 6 files changed, 332 insertions(+), 153 deletions(-) diff --git a/energy-integration/governance-v2/src/errors.rs b/energy-integration/governance-v2/src/errors.rs index f569688a8..f1676ff79 100644 --- a/energy-integration/governance-v2/src/errors.rs +++ b/energy-integration/governance-v2/src/errors.rs @@ -11,4 +11,4 @@ pub const ONLY_PROPOSER_CANCEL: &[u8] = b"Only original proposer may cancel a pe pub const ONLY_PROPOSER_WITHDRAW: &[u8] = b"Only original proposer may cancel a pending proposal"; pub const NO_PROPOSAL: &[u8] = b"Proposal does not exist"; pub const WITHDRAW_NOT_ALLOWED: &[u8] = b"You may not withdraw funds from this proposal!"; -pub const INVALID_MERKLE_PROOF: &[u8] = b"Invalid merkle proof provided"; \ No newline at end of file +pub const INVALID_MERKLE_PROOF: &[u8] = b"Invalid merkle proof provided"; diff --git a/energy-integration/governance-v2/src/lib.rs b/energy-integration/governance-v2/src/lib.rs index e5964eba1..b0c924800 100644 --- a/energy-integration/governance-v2/src/lib.rs +++ b/energy-integration/governance-v2/src/lib.rs @@ -36,8 +36,6 @@ pub trait GovernanceV2: /// - `votingDelayInBlocks` - Number of blocks to wait after a block is proposed before being able to vote/downvote that proposal; /// - `votingPeriodInBlocks` - Number of blocks the voting period lasts (voting delay does not count towards this); /// - `withdraw_percentage_defeated` - The percentage used to return in case of DownVetoVote; - /// - `energy_factory_address`; - /// - `fees_collector_address`; /// - `fee_token` - The token used to pay the fee for governance proposal; #[init] fn init( @@ -48,7 +46,6 @@ pub trait GovernanceV2: voting_delay_in_blocks: u64, voting_period_in_blocks: u64, withdraw_percentage_defeated: u64, - energy_factory_address: ManagedAddress, fee_token: TokenIdentifier, ) { // self.try_change_min_energy_for_propose(min_energy_for_propose); @@ -57,7 +54,6 @@ pub trait GovernanceV2: self.try_change_voting_delay_in_blocks(voting_delay_in_blocks); self.try_change_voting_period_in_blocks(voting_period_in_blocks); self.try_change_withdraw_percentage_defeated(withdraw_percentage_defeated); - self.set_energy_factory_address(energy_factory_address); self.try_change_fee_token_id(fee_token); } @@ -79,7 +75,7 @@ pub trait GovernanceV2: fn propose( &self, root_hash: ManagedByteArray, - total_voting_power: BigUint, + total_balance: BigUint, description: ManagedBuffer, actions: MultiValueEncoded>, ) -> ProposalId { @@ -141,7 +137,7 @@ pub trait GovernanceV2: voting_delay_in_blocks, voting_period_in_blocks, withdraw_percentage_defeated, - total_voting_power, + total_balance, proposal_start_block: current_block, }; let proposal_id = self.proposals().push(&proposal); @@ -153,9 +149,15 @@ pub trait GovernanceV2: proposal_id } - /// Vote on a proposal. The voting power depends on the user's energy. + /// Vote on a proposal. The voting balance depends on the user's energy. #[endpoint] - fn vote(&self, proposal_id: ProposalId, vote: VoteType, voting_power: BigUint, proof: ArrayVec, PROOF_LENGTH>) { + fn vote( + &self, + proposal_id: ProposalId, + vote: VoteType, + user_balance: BigUint, + proof: ArrayVec, PROOF_LENGTH>, + ) { self.require_caller_not_self(); self.require_valid_proposal_id(proposal_id); require!( @@ -167,12 +169,17 @@ pub trait GovernanceV2: let new_user = self.user_voted_proposals(&voter).insert(proposal_id); require!(new_user, ALREADY_VOTED_ERR_MSG); + let voting_power = user_balance.sqrt(); + match self.get_root_hash(proposal_id) { OptionalValue::None => { sc_panic!(NO_PROPOSAL); } OptionalValue::Some(root_hash) => { - require!(self.verify_merkle_proof(voting_power.clone(), proof, root_hash), INVALID_MERKLE_PROOF); + require!( + self.verify_merkle_proof(voting_power.clone(), proof, root_hash), + INVALID_MERKLE_PROOF + ); } } @@ -182,28 +189,28 @@ pub trait GovernanceV2: proposal_votes.up_votes += &voting_power.clone(); proposal_votes.quorum += &voting_power.clone(); }); - self.up_vote_cast_event(&voter, proposal_id, &voting_power, &user_energy); + self.up_vote_cast_event(&voter, proposal_id, &voting_power, &user_balance); } VoteType::DownVote => { self.proposal_votes(proposal_id).update(|proposal_votes| { proposal_votes.down_votes += &voting_power.clone(); proposal_votes.quorum += &voting_power.clone(); }); - self.down_vote_cast_event(&voter, proposal_id, &voting_power, &user_energy); + self.down_vote_cast_event(&voter, proposal_id, &voting_power, &user_balance); } VoteType::DownVetoVote => { self.proposal_votes(proposal_id).update(|proposal_votes| { proposal_votes.down_veto_votes += &voting_power.clone(); proposal_votes.quorum += &voting_power.clone(); }); - self.down_veto_vote_cast_event(&voter, proposal_id, &voting_power, &user_energy); + self.down_veto_vote_cast_event(&voter, proposal_id, &voting_power, &user_balance); } VoteType::AbstainVote => { self.proposal_votes(proposal_id).update(|proposal_votes| { proposal_votes.abstain_votes += &voting_power.clone(); proposal_votes.quorum += &voting_power.clone(); }); - self.abstain_vote_cast_event(&voter, proposal_id, &voting_power, &user_energy); + self.abstain_vote_cast_event(&voter, proposal_id, &voting_power, &user_balance); } } self.user_voted_proposals(&voter).insert(proposal_id); @@ -224,10 +231,7 @@ pub trait GovernanceV2: let proposal = self.proposals().get(proposal_id); let caller = self.blockchain().get_caller(); - require!( - caller == proposal.proposer, - ONLY_PROPOSER_CANCEL - ); + require!(caller == proposal.proposer, ONLY_PROPOSER_CANCEL); self.refund_proposal_fee(proposal_id, &proposal.fee_payment.amount); self.clear_proposal(proposal_id); self.proposal_canceled_event(proposal_id); @@ -252,10 +256,7 @@ pub trait GovernanceV2: GovernanceProposalStatus::Succeeded | GovernanceProposalStatus::Defeated => { let proposal = self.proposals().get(proposal_id); - require!( - caller == proposal.proposer, - ONLY_PROPOSER_WITHDRAW - ); + require!(caller == proposal.proposer, ONLY_PROPOSER_WITHDRAW); self.refund_proposal_fee(proposal_id, &proposal.fee_payment.amount); } @@ -265,10 +266,7 @@ pub trait GovernanceV2: let refund_amount = refund_percentage * proposal.fee_payment.amount.clone() / FULL_PERCENTAGE; - require!( - caller == proposal.proposer, - ONLY_PROPOSER_WITHDRAW - ); + require!(caller == proposal.proposer, ONLY_PROPOSER_WITHDRAW); self.refund_proposal_fee(proposal_id, &refund_amount); let remaining_fee = proposal.fee_payment.amount - refund_amount; @@ -312,7 +310,12 @@ pub trait GovernanceV2: ); } - fn verify_merkle_proof(&self, power: BigUint, proof: ArrayVec, PROOF_LENGTH>, root_hash: ManagedByteArray) -> bool { + fn verify_merkle_proof( + &self, + power: BigUint, + proof: ArrayVec, PROOF_LENGTH>, + root_hash: ManagedByteArray, + ) -> bool { let caller = self.blockchain().get_caller(); let mut leaf_bytes = caller.as_managed_buffer().clone(); @@ -321,7 +324,9 @@ pub trait GovernanceV2: let mut hash = self.crypto().sha256(&leaf_bytes); for proof_item in proof { - if BigUint::from(hash.as_managed_buffer()) < BigUint::from(proof_item.as_managed_buffer()) { + if BigUint::from(hash.as_managed_buffer()) + < BigUint::from(proof_item.as_managed_buffer()) + { let mut tst = hash.as_managed_buffer().clone(); tst.append(proof_item.as_managed_buffer()); diff --git a/energy-integration/governance-v2/src/proposal.rs b/energy-integration/governance-v2/src/proposal.rs index ba12bfb4d..57ac96c17 100644 --- a/energy-integration/governance-v2/src/proposal.rs +++ b/energy-integration/governance-v2/src/proposal.rs @@ -64,6 +64,6 @@ pub struct GovernanceProposal { pub voting_delay_in_blocks: u64, pub voting_period_in_blocks: u64, pub withdraw_percentage_defeated: u64, - pub total_voting_power: BigUint, + pub total_balance: BigUint, pub proposal_start_block: u64, } diff --git a/energy-integration/governance-v2/src/views.rs b/energy-integration/governance-v2/src/views.rs index 0bca00939..f448c887c 100644 --- a/energy-integration/governance-v2/src/views.rs +++ b/energy-integration/governance-v2/src/views.rs @@ -46,7 +46,10 @@ pub trait ViewsModule: } #[view(getProposalRootHash)] - fn get_root_hash(&self, proposal_id: ProposalId) -> OptionalValue> { + fn get_root_hash( + &self, + proposal_id: ProposalId, + ) -> OptionalValue> { if !self.proposal_exists(proposal_id) { return OptionalValue::None; } @@ -90,17 +93,16 @@ pub trait ViewsModule: fn quorum_reached(&self, proposal_id: ProposalId) -> bool { let proposal = self.proposals().get(proposal_id); - let total_voting_power_for_proposal = proposal.total_voting_power; + let total_balance = proposal.total_balance; - if total_energy_for_proposal == 0u64 { - return false + if total_balance == 0u64 { + return false; } let required_minimum_percentage = proposal.minimum_quorum; let current_quorum = self.proposal_votes(proposal_id).get().quorum; - let current_quorum_percentage = - current_quorum * FULL_PERCENTAGE / total_voting_power_for_proposal; + let current_quorum_percentage = current_quorum * FULL_PERCENTAGE / total_balance; current_quorum_percentage >= required_minimum_percentage } diff --git a/energy-integration/governance-v2/tests/gov_rust_test.rs b/energy-integration/governance-v2/tests/gov_rust_test.rs index f90b9e1b2..4e99595cd 100644 --- a/energy-integration/governance-v2/tests/gov_rust_test.rs +++ b/energy-integration/governance-v2/tests/gov_rust_test.rs @@ -123,6 +123,7 @@ fn gov_propose_total_energy_0_test() { .set_nft_balance(&first_user_addr, WXMEX_TOKEN_ID, 1, &min_fee, &Empty); let (result, proposal_id) = gov_setup.propose( + gov_setup.get_merkle_root_hash(), &first_user_addr, &min_fee, &sc_addr, @@ -137,7 +138,7 @@ fn gov_propose_total_energy_0_test() { .b_mock .execute_query(&gov_setup.gov_wrapper, |sc| { let mut proposal = sc.proposals().get(1); - proposal.total_energy = managed_biguint!(0); + proposal.total_balance = managed_biguint!(0); sc.proposals().set(1, &proposal); assert!( sc.get_proposal_status(1) == GovernanceProposalStatus::Defeated, @@ -147,7 +148,6 @@ fn gov_propose_total_energy_0_test() { .assert_ok(); } - #[test] fn gov_no_veto_vote_test() { let mut gov_setup = GovSetup::new(governance_v2::contract_obj); @@ -211,7 +211,12 @@ fn gov_no_veto_vote_test() { // Third User DownWithVetoVote = 1_100 gov_setup - .up_vote(&third_user_addr, &third_user_power, &third_user_proof, proposal_id) + .up_vote( + &third_user_addr, + &third_user_power, + &third_user_proof, + proposal_id, + ) .assert_ok(); gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); @@ -257,9 +262,21 @@ fn gov_abstain_vote_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.abstain_vote(&first_user_addr, &first_user_power, &first_user_proof, proposal_id).assert_ok(); gov_setup - .up_vote(&third_user_addr, &third_user_power, &third_user_proof, proposal_id) + .abstain_vote( + &first_user_addr, + &first_user_power, + &first_user_proof, + proposal_id, + ) + .assert_ok(); + gov_setup + .up_vote( + &third_user_addr, + &third_user_power, + &third_user_proof, + proposal_id, + ) .assert_ok(); gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); @@ -303,7 +320,14 @@ fn gov_no_quorum_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.up_vote(&third_user_addr, &third_user_power, &third_user_proof, proposal_id).assert_ok(); + gov_setup + .up_vote( + &third_user_addr, + &third_user_power, + &third_user_proof, + proposal_id, + ) + .assert_ok(); gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); @@ -346,7 +370,14 @@ fn gov_modify_quorum_after_end_vote_test() { gov_setup.increment_block_nonce(VOTING_DELAY_BLOCKS); - gov_setup.up_vote(&third_user_addr, &third_user_power, &third_user_proof, proposal_id).assert_ok(); + gov_setup + .up_vote( + &third_user_addr, + &third_user_power, + &third_user_proof, + proposal_id, + ) + .assert_ok(); gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); @@ -407,9 +438,21 @@ fn gov_withdraw_defeated_proposal_test() { gov_setup.increment_block_nonce(VOTING_DELAY_BLOCKS); - gov_setup.down_vote(&first_user_addr, &first_user_power, &first_user_proof, proposal_id).assert_ok(); gov_setup - .up_vote(&third_user_addr, &third_user_power, &third_user_proof, proposal_id) + .down_vote( + &first_user_addr, + &first_user_power, + &first_user_proof, + proposal_id, + ) + .assert_ok(); + gov_setup + .up_vote( + &third_user_addr, + &third_user_power, + &third_user_proof, + proposal_id, + ) .assert_ok(); gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); @@ -483,9 +526,21 @@ fn gov_modify_withdraw_defeated_proposal_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.down_vote(&first_user_addr, &first_user_power, &first_user_proof, proposal_id).assert_ok(); gov_setup - .up_vote(&third_user_addr, &third_user_power, &third_user_proof, proposal_id) + .down_vote( + &first_user_addr, + &first_user_power, + &first_user_proof, + proposal_id, + ) + .assert_ok(); + gov_setup + .up_vote( + &third_user_addr, + &third_user_power, + &third_user_proof, + proposal_id, + ) .assert_ok(); gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); @@ -563,9 +618,21 @@ fn gov_withdraw_no_with_veto_defeated_proposal_test() { gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.down_veto_vote(&first_user_addr, &first_user_power, &first_user_proof, proposal_id).assert_ok(); gov_setup - .up_vote(&third_user_addr, &third_user_power, &third_user_proof, proposal_id) + .down_veto_vote( + &first_user_addr, + &first_user_power, + &first_user_proof, + proposal_id, + ) + .assert_ok(); + gov_setup + .up_vote( + &third_user_addr, + &third_user_power, + &third_user_proof, + proposal_id, + ) .assert_ok(); gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); diff --git a/energy-integration/governance-v2/tests/gov_test_setup/mod.rs b/energy-integration/governance-v2/tests/gov_test_setup/mod.rs index 171888ec7..5e74a9f54 100644 --- a/energy-integration/governance-v2/tests/gov_test_setup/mod.rs +++ b/energy-integration/governance-v2/tests/gov_test_setup/mod.rs @@ -1,12 +1,11 @@ -use energy_factory_mock::EnergyFactoryMock; -use energy_query::Energy; use governance_v2::{ proposal_storage::{ProposalStorageModule, VoteType}, GovernanceV2, }; use multiversx_sc::{ + arrayvec::ArrayVec, hex_literal::hex, - types::{Address, BigInt, ManagedByteArray, ManagedVec, MultiValueEncoded}, arrayvec::ArrayVec, + types::{Address, ManagedByteArray, ManagedVec, MultiValueEncoded}, }; use multiversx_sc_scenario::{ managed_address, managed_biguint, managed_buffer, managed_token_id, rust_biguint, @@ -25,8 +24,6 @@ pub const WITHDRAW_PERCENTAGE: u64 = 5_000; // 50% pub const WXMEX_TOKEN_ID: &[u8] = b"WXMEX-123456"; pub const DECIMALS_CONST: u64 = 1_000_000_000_000_000_000; pub const QUORUM: u64 = 217_433_990_694; - -pub const VOTING_POWER: u64 = 1_000_000; pub const GAS_LIMIT: u64 = 1_000_000; #[derive(Clone)] @@ -75,38 +72,6 @@ where )); b_mock.create_user_account_fixed_address(&first_merkle_user, &rust_zero); - // init energy factory - let energy_factory_wrapper = b_mock.create_sc_account( - &rust_zero, - Some(&owner), - energy_factory_mock::contract_obj, - "energy factory path", - ); - - b_mock - .execute_tx(&owner, &energy_factory_wrapper, &rust_zero, |sc| { - sc.init(); - sc.user_energy(&managed_address!(&first_user)) - .set(&Energy::new( - BigInt::from(managed_biguint!(VOTING_POWER)), - 0, - managed_biguint!(0), - )); - sc.user_energy(&managed_address!(&second_user)) - .set(&Energy::new( - BigInt::from(managed_biguint!(VOTING_POWER)), - 0, - managed_biguint!(0), - )); - sc.user_energy(&managed_address!(&third_user)) - .set(&Energy::new( - BigInt::from(managed_biguint!(VOTING_POWER + 210_000)), - 0, - managed_biguint!(0), - )); - }) - .assert_ok(); - // init governance sc let gov_wrapper = b_mock.create_sc_account(&rust_zero, Some(&owner), gov_builder, "gov path"); @@ -120,7 +85,6 @@ where VOTING_DELAY_BLOCKS, VOTING_PERIOD_BLOCKS, WITHDRAW_PERCENTAGE, - managed_address!(energy_factory_wrapper.address_ref()), managed_token_id!(WXMEX_TOKEN_ID), ); }) @@ -185,31 +149,65 @@ where (result, proposal_id) } - pub fn up_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { + pub fn up_vote( + &mut self, + voter: &Address, + power: &BigUint, + proof: &ArrayVec, 18>, + proposal_id: usize, + ) -> TxResult { self.b_mock .execute_tx(voter, &self.gov_wrapper, &rust_biguint!(0), |sc| { sc.vote(proposal_id, VoteType::UpVote, power.into(), proof.clone()); }) } - pub fn down_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { + pub fn down_vote( + &mut self, + voter: &Address, + power: &BigUint, + proof: &ArrayVec, 18>, + proposal_id: usize, + ) -> TxResult { self.b_mock .execute_tx(voter, &self.gov_wrapper, &rust_biguint!(0), |sc| { sc.vote(proposal_id, VoteType::DownVote, power.into(), proof.clone()); }) } - pub fn down_veto_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { + pub fn down_veto_vote( + &mut self, + voter: &Address, + power: &BigUint, + proof: &ArrayVec, 18>, + proposal_id: usize, + ) -> TxResult { self.b_mock .execute_tx(voter, &self.gov_wrapper, &rust_biguint!(0), |sc| { - sc.vote(proposal_id, VoteType::DownVetoVote, power.into(), proof.clone()); + sc.vote( + proposal_id, + VoteType::DownVetoVote, + power.into(), + proof.clone(), + ); }) } - pub fn abstain_vote(&mut self, voter: &Address, power: &BigUint, proof: &ArrayVec, 18>, proposal_id: usize) -> TxResult { + pub fn abstain_vote( + &mut self, + voter: &Address, + power: &BigUint, + proof: &ArrayVec, 18>, + proposal_id: usize, + ) -> TxResult { self.b_mock .execute_tx(voter, &self.gov_wrapper, &rust_biguint!(0), |sc| { - sc.vote(proposal_id, VoteType::AbstainVote, power.into(), proof.clone()); + sc.vote( + proposal_id, + VoteType::AbstainVote, + power.into(), + proof.clone(), + ); }) } @@ -247,89 +245,196 @@ where } pub fn first_merkle_proof(&self) -> ArrayVec, 18> { ArrayVec::from([ - ManagedByteArray::from(&hex!("5e9e904152b2a06dafc26aa02b8c55b2ec3370cdf55b06b15fe8c94bc56e43fc")), - ManagedByteArray::from(&hex!("47aa547fa524519bc946d0883591e9d273a65b4a8f06a37baf170c707c4fb782")), - ManagedByteArray::from(&hex!("da05a587448779b9368680f0ee745b3ff2df1132e309a2de518aa9814cc25de8")), - ManagedByteArray::from(&hex!("14ae69620e727d8e899119ef7a1f04191f15f7c704c2673445510a1bbce7edb2")), - ManagedByteArray::from(&hex!("449e8beb9a901efc2815253a2ce416e3b98ff771fdfc9e35f4ce31004003e533")), - ManagedByteArray::from(&hex!("fdf33783f8de396173fd37b558213117bb2be3430d50b18eeb5da1af0b98fd66")), - ManagedByteArray::from(&hex!("889a7d403faae66ec51db6b0708d889ca277e2fd64f78e47612c07077df6eccc")), - ManagedByteArray::from(&hex!("5cc55493d05c9bf63431384f184e0cc6ab13c14509c3e9a64dc49b47e3821c6f")), - ManagedByteArray::from(&hex!("ca559e91dee09fccf8d3dbf9bda81f57d4094faecf2f9ac3a98e84b3f376c81c")), - ManagedByteArray::from(&hex!("781cf1316f87a336a7219095aa8b523a821d260ca0b7a7f94af5c769e17c8f82")), - ManagedByteArray::from(&hex!("5e97339ee010d2ae3ac54c38c7158e7a7ef4311f89b28b4634d0d35fd4097dc0")), - ManagedByteArray::from(&hex!("2c7b2103c3e48386a7eda174cec726c28ec6ce80466deaac49dbaf469f35d059")), - ManagedByteArray::from(&hex!("9b2ceb7809f078724efb71ea3542885c990985d41746d4cab7948928384c3a4c")), - ManagedByteArray::from(&hex!("b1f37e46c3f84a3c68804d62b26b7f035c90f344252d77fdeff2393793ae34d4")), - ManagedByteArray::from(&hex!("95ead464db14a9a65c3b9c5378cf927b76ff530ae0762dbb6456bfeb467f97b2")), - ManagedByteArray::from(&hex!("39e10ed734ddaa3098edc6300edeed2fce75780fc718140359b13c58045a1838")), - ManagedByteArray::from(&hex!("b36fbf7a645b24bab3eaca5c351985f6bbb95723b47db78171dd7d7f8883ecad")), - ManagedByteArray::from(&hex!("bffe20aa722c488465e18d10ac3abe3002603bbd4c535211d9bd9b34ce7259a1")), + ManagedByteArray::from(&hex!( + "5e9e904152b2a06dafc26aa02b8c55b2ec3370cdf55b06b15fe8c94bc56e43fc" + )), + ManagedByteArray::from(&hex!( + "47aa547fa524519bc946d0883591e9d273a65b4a8f06a37baf170c707c4fb782" + )), + ManagedByteArray::from(&hex!( + "da05a587448779b9368680f0ee745b3ff2df1132e309a2de518aa9814cc25de8" + )), + ManagedByteArray::from(&hex!( + "14ae69620e727d8e899119ef7a1f04191f15f7c704c2673445510a1bbce7edb2" + )), + ManagedByteArray::from(&hex!( + "449e8beb9a901efc2815253a2ce416e3b98ff771fdfc9e35f4ce31004003e533" + )), + ManagedByteArray::from(&hex!( + "fdf33783f8de396173fd37b558213117bb2be3430d50b18eeb5da1af0b98fd66" + )), + ManagedByteArray::from(&hex!( + "889a7d403faae66ec51db6b0708d889ca277e2fd64f78e47612c07077df6eccc" + )), + ManagedByteArray::from(&hex!( + "5cc55493d05c9bf63431384f184e0cc6ab13c14509c3e9a64dc49b47e3821c6f" + )), + ManagedByteArray::from(&hex!( + "ca559e91dee09fccf8d3dbf9bda81f57d4094faecf2f9ac3a98e84b3f376c81c" + )), + ManagedByteArray::from(&hex!( + "781cf1316f87a336a7219095aa8b523a821d260ca0b7a7f94af5c769e17c8f82" + )), + ManagedByteArray::from(&hex!( + "5e97339ee010d2ae3ac54c38c7158e7a7ef4311f89b28b4634d0d35fd4097dc0" + )), + ManagedByteArray::from(&hex!( + "2c7b2103c3e48386a7eda174cec726c28ec6ce80466deaac49dbaf469f35d059" + )), + ManagedByteArray::from(&hex!( + "9b2ceb7809f078724efb71ea3542885c990985d41746d4cab7948928384c3a4c" + )), + ManagedByteArray::from(&hex!( + "b1f37e46c3f84a3c68804d62b26b7f035c90f344252d77fdeff2393793ae34d4" + )), + ManagedByteArray::from(&hex!( + "95ead464db14a9a65c3b9c5378cf927b76ff530ae0762dbb6456bfeb467f97b2" + )), + ManagedByteArray::from(&hex!( + "39e10ed734ddaa3098edc6300edeed2fce75780fc718140359b13c58045a1838" + )), + ManagedByteArray::from(&hex!( + "b36fbf7a645b24bab3eaca5c351985f6bbb95723b47db78171dd7d7f8883ecad" + )), + ManagedByteArray::from(&hex!( + "bffe20aa722c488465e18d10ac3abe3002603bbd4c535211d9bd9b34ce7259a1" + )), ]) } pub fn second_merkle_proof(&self) -> ArrayVec, 18> { ArrayVec::from([ - ManagedByteArray::from(&hex!("b1d7a256ae6b35cce14497b3735d71dd205f099f1a035a7a5cb96e8bf5c32f31")), - ManagedByteArray::from(&hex!("81dc00d137001723d5654e3120d63601b08ca2b4b8dc41802476529e6d6ada9e")), - ManagedByteArray::from(&hex!("985e3554adfefea5d2c3f7c93d404fd547cfead9054ce313845656507037df40")), - ManagedByteArray::from(&hex!("14ae69620e727d8e899119ef7a1f04191f15f7c704c2673445510a1bbce7edb2")), - ManagedByteArray::from(&hex!("449e8beb9a901efc2815253a2ce416e3b98ff771fdfc9e35f4ce31004003e533")), - ManagedByteArray::from(&hex!("fdf33783f8de396173fd37b558213117bb2be3430d50b18eeb5da1af0b98fd66")), - ManagedByteArray::from(&hex!("889a7d403faae66ec51db6b0708d889ca277e2fd64f78e47612c07077df6eccc")), - ManagedByteArray::from(&hex!("5cc55493d05c9bf63431384f184e0cc6ab13c14509c3e9a64dc49b47e3821c6f")), - ManagedByteArray::from(&hex!("ca559e91dee09fccf8d3dbf9bda81f57d4094faecf2f9ac3a98e84b3f376c81c")), - ManagedByteArray::from(&hex!("781cf1316f87a336a7219095aa8b523a821d260ca0b7a7f94af5c769e17c8f82")), - ManagedByteArray::from(&hex!("5e97339ee010d2ae3ac54c38c7158e7a7ef4311f89b28b4634d0d35fd4097dc0")), - ManagedByteArray::from(&hex!("2c7b2103c3e48386a7eda174cec726c28ec6ce80466deaac49dbaf469f35d059")), - ManagedByteArray::from(&hex!("9b2ceb7809f078724efb71ea3542885c990985d41746d4cab7948928384c3a4c")), - ManagedByteArray::from(&hex!("b1f37e46c3f84a3c68804d62b26b7f035c90f344252d77fdeff2393793ae34d4")), - ManagedByteArray::from(&hex!("95ead464db14a9a65c3b9c5378cf927b76ff530ae0762dbb6456bfeb467f97b2")), - ManagedByteArray::from(&hex!("39e10ed734ddaa3098edc6300edeed2fce75780fc718140359b13c58045a1838")), - ManagedByteArray::from(&hex!("b36fbf7a645b24bab3eaca5c351985f6bbb95723b47db78171dd7d7f8883ecad")), - ManagedByteArray::from(&hex!("bffe20aa722c488465e18d10ac3abe3002603bbd4c535211d9bd9b34ce7259a1")), + ManagedByteArray::from(&hex!( + "b1d7a256ae6b35cce14497b3735d71dd205f099f1a035a7a5cb96e8bf5c32f31" + )), + ManagedByteArray::from(&hex!( + "81dc00d137001723d5654e3120d63601b08ca2b4b8dc41802476529e6d6ada9e" + )), + ManagedByteArray::from(&hex!( + "985e3554adfefea5d2c3f7c93d404fd547cfead9054ce313845656507037df40" + )), + ManagedByteArray::from(&hex!( + "14ae69620e727d8e899119ef7a1f04191f15f7c704c2673445510a1bbce7edb2" + )), + ManagedByteArray::from(&hex!( + "449e8beb9a901efc2815253a2ce416e3b98ff771fdfc9e35f4ce31004003e533" + )), + ManagedByteArray::from(&hex!( + "fdf33783f8de396173fd37b558213117bb2be3430d50b18eeb5da1af0b98fd66" + )), + ManagedByteArray::from(&hex!( + "889a7d403faae66ec51db6b0708d889ca277e2fd64f78e47612c07077df6eccc" + )), + ManagedByteArray::from(&hex!( + "5cc55493d05c9bf63431384f184e0cc6ab13c14509c3e9a64dc49b47e3821c6f" + )), + ManagedByteArray::from(&hex!( + "ca559e91dee09fccf8d3dbf9bda81f57d4094faecf2f9ac3a98e84b3f376c81c" + )), + ManagedByteArray::from(&hex!( + "781cf1316f87a336a7219095aa8b523a821d260ca0b7a7f94af5c769e17c8f82" + )), + ManagedByteArray::from(&hex!( + "5e97339ee010d2ae3ac54c38c7158e7a7ef4311f89b28b4634d0d35fd4097dc0" + )), + ManagedByteArray::from(&hex!( + "2c7b2103c3e48386a7eda174cec726c28ec6ce80466deaac49dbaf469f35d059" + )), + ManagedByteArray::from(&hex!( + "9b2ceb7809f078724efb71ea3542885c990985d41746d4cab7948928384c3a4c" + )), + ManagedByteArray::from(&hex!( + "b1f37e46c3f84a3c68804d62b26b7f035c90f344252d77fdeff2393793ae34d4" + )), + ManagedByteArray::from(&hex!( + "95ead464db14a9a65c3b9c5378cf927b76ff530ae0762dbb6456bfeb467f97b2" + )), + ManagedByteArray::from(&hex!( + "39e10ed734ddaa3098edc6300edeed2fce75780fc718140359b13c58045a1838" + )), + ManagedByteArray::from(&hex!( + "b36fbf7a645b24bab3eaca5c351985f6bbb95723b47db78171dd7d7f8883ecad" + )), + ManagedByteArray::from(&hex!( + "bffe20aa722c488465e18d10ac3abe3002603bbd4c535211d9bd9b34ce7259a1" + )), ]) } pub fn third_merkle_proof(&self) -> ArrayVec, 18> { ArrayVec::from([ - ManagedByteArray::from(&hex!("aa68ae7eac4de3cc643717d33ab7d2e1b098788b127f298f23a34e8720ec609d")), - ManagedByteArray::from(&hex!("e3db2cf9f85b49279eba44b0f62ac2c6bcdf870f198b9484344634a58860ba2d")), - ManagedByteArray::from(&hex!("64468b8481d2c1737977e7382eaaa12c8072ee76fda33c3b6aaa193b38d4f1f2")), - ManagedByteArray::from(&hex!("6159dc0c80183e89221a36db3fedfabe38933d0db73c1156ad32d8caf0537085")), - ManagedByteArray::from(&hex!("449e8beb9a901efc2815253a2ce416e3b98ff771fdfc9e35f4ce31004003e533")), - ManagedByteArray::from(&hex!("fdf33783f8de396173fd37b558213117bb2be3430d50b18eeb5da1af0b98fd66")), - ManagedByteArray::from(&hex!("889a7d403faae66ec51db6b0708d889ca277e2fd64f78e47612c07077df6eccc")), - ManagedByteArray::from(&hex!("5cc55493d05c9bf63431384f184e0cc6ab13c14509c3e9a64dc49b47e3821c6f")), - ManagedByteArray::from(&hex!("ca559e91dee09fccf8d3dbf9bda81f57d4094faecf2f9ac3a98e84b3f376c81c")), - ManagedByteArray::from(&hex!("781cf1316f87a336a7219095aa8b523a821d260ca0b7a7f94af5c769e17c8f82")), - ManagedByteArray::from(&hex!("5e97339ee010d2ae3ac54c38c7158e7a7ef4311f89b28b4634d0d35fd4097dc0")), - ManagedByteArray::from(&hex!("2c7b2103c3e48386a7eda174cec726c28ec6ce80466deaac49dbaf469f35d059")), - ManagedByteArray::from(&hex!("9b2ceb7809f078724efb71ea3542885c990985d41746d4cab7948928384c3a4c")), - ManagedByteArray::from(&hex!("b1f37e46c3f84a3c68804d62b26b7f035c90f344252d77fdeff2393793ae34d4")), - ManagedByteArray::from(&hex!("95ead464db14a9a65c3b9c5378cf927b76ff530ae0762dbb6456bfeb467f97b2")), - ManagedByteArray::from(&hex!("39e10ed734ddaa3098edc6300edeed2fce75780fc718140359b13c58045a1838")), - ManagedByteArray::from(&hex!("b36fbf7a645b24bab3eaca5c351985f6bbb95723b47db78171dd7d7f8883ecad")), - ManagedByteArray::from(&hex!("bffe20aa722c488465e18d10ac3abe3002603bbd4c535211d9bd9b34ce7259a1")), - + ManagedByteArray::from(&hex!( + "aa68ae7eac4de3cc643717d33ab7d2e1b098788b127f298f23a34e8720ec609d" + )), + ManagedByteArray::from(&hex!( + "e3db2cf9f85b49279eba44b0f62ac2c6bcdf870f198b9484344634a58860ba2d" + )), + ManagedByteArray::from(&hex!( + "64468b8481d2c1737977e7382eaaa12c8072ee76fda33c3b6aaa193b38d4f1f2" + )), + ManagedByteArray::from(&hex!( + "6159dc0c80183e89221a36db3fedfabe38933d0db73c1156ad32d8caf0537085" + )), + ManagedByteArray::from(&hex!( + "449e8beb9a901efc2815253a2ce416e3b98ff771fdfc9e35f4ce31004003e533" + )), + ManagedByteArray::from(&hex!( + "fdf33783f8de396173fd37b558213117bb2be3430d50b18eeb5da1af0b98fd66" + )), + ManagedByteArray::from(&hex!( + "889a7d403faae66ec51db6b0708d889ca277e2fd64f78e47612c07077df6eccc" + )), + ManagedByteArray::from(&hex!( + "5cc55493d05c9bf63431384f184e0cc6ab13c14509c3e9a64dc49b47e3821c6f" + )), + ManagedByteArray::from(&hex!( + "ca559e91dee09fccf8d3dbf9bda81f57d4094faecf2f9ac3a98e84b3f376c81c" + )), + ManagedByteArray::from(&hex!( + "781cf1316f87a336a7219095aa8b523a821d260ca0b7a7f94af5c769e17c8f82" + )), + ManagedByteArray::from(&hex!( + "5e97339ee010d2ae3ac54c38c7158e7a7ef4311f89b28b4634d0d35fd4097dc0" + )), + ManagedByteArray::from(&hex!( + "2c7b2103c3e48386a7eda174cec726c28ec6ce80466deaac49dbaf469f35d059" + )), + ManagedByteArray::from(&hex!( + "9b2ceb7809f078724efb71ea3542885c990985d41746d4cab7948928384c3a4c" + )), + ManagedByteArray::from(&hex!( + "b1f37e46c3f84a3c68804d62b26b7f035c90f344252d77fdeff2393793ae34d4" + )), + ManagedByteArray::from(&hex!( + "95ead464db14a9a65c3b9c5378cf927b76ff530ae0762dbb6456bfeb467f97b2" + )), + ManagedByteArray::from(&hex!( + "39e10ed734ddaa3098edc6300edeed2fce75780fc718140359b13c58045a1838" + )), + ManagedByteArray::from(&hex!( + "b36fbf7a645b24bab3eaca5c351985f6bbb95723b47db78171dd7d7f8883ecad" + )), + ManagedByteArray::from(&hex!( + "bffe20aa722c488465e18d10ac3abe3002603bbd4c535211d9bd9b34ce7259a1" + )), ]) } - pub fn get_first_user_voting_power(&self) -> BigUint { - BigUint::from(217_433_990_694u64) + BigUint::from(217_433_990_694u64).pow(2) } pub fn get_second_user_voting_power(&self) -> BigUint { - BigUint::from(59_024_824_840u64) + BigUint::from(59_024_824_840u64).pow(2) } pub fn get_third_user_voting_power(&self) -> BigUint { - BigUint::from(40_000_000_000u64) + BigUint::from(40_000_000_000u64).pow(2) } pub fn get_merkle_root_hash(&self) -> ManagedByteArray { - ManagedByteArray::from(&hex!("0fdb09afb35351d5becc3a79dd9bf03bae7c2366d186a6c8e8276f545d024ef5")) + ManagedByteArray::from(&hex!( + "0fdb09afb35351d5becc3a79dd9bf03bae7c2366d186a6c8e8276f545d024ef5" + )) } - } From 55c2653b76872ae16a12899f701bbf4ec19b5a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Thu, 27 Jul 2023 12:42:33 +0300 Subject: [PATCH 04/12] Governance-v2: Remove unnecesarry modules --- energy-integration/governance-v2/Cargo.toml | 14 -------------- .../governance-v2/src/configurable.rs | 4 +--- energy-integration/governance-v2/src/lib.rs | 2 -- energy-integration/governance-v2/src/views.rs | 9 --------- 4 files changed, 1 insertion(+), 28 deletions(-) diff --git a/energy-integration/governance-v2/Cargo.toml b/energy-integration/governance-v2/Cargo.toml index e1993198d..5e368a734 100644 --- a/energy-integration/governance-v2/Cargo.toml +++ b/energy-integration/governance-v2/Cargo.toml @@ -7,8 +7,6 @@ publish = false [lib] path = "src/lib.rs" -[dependencies.energy-query] -path = "../common-modules/energy-query" [dependencies.multiversx-sc] version = "=0.39.4" @@ -19,15 +17,3 @@ num-bigint = "0.4.2" [dev-dependencies.multiversx-sc-scenario] version = "=0.39.4" - -[dev-dependencies.energy-factory-mock] -path = "../energy-factory-mock" - -[dependencies.permissions_module] -path = "../../common/modules/permissions_module" - -[dependencies.fees-collector] -path = "../fees-collector" - -[dependencies.weekly-rewards-splitting] -path = "../common-modules/weekly-rewards-splitting" diff --git a/energy-integration/governance-v2/src/configurable.rs b/energy-integration/governance-v2/src/configurable.rs index c7982e68a..81a56e398 100644 --- a/energy-integration/governance-v2/src/configurable.rs +++ b/energy-integration/governance-v2/src/configurable.rs @@ -41,9 +41,7 @@ const MAX_MIN_FEE_FOR_PROPOSE: u64 = 200_000_000_000; const DECIMALS_CONST: u64 = 1_000_000_000_000_000_000; #[multiversx_sc::module] -pub trait ConfigurablePropertiesModule: - energy_query::EnergyQueryModule + permissions_module::PermissionsModule -{ +pub trait ConfigurablePropertiesModule { // endpoints - these can only be called by the SC itself. // i.e. only by proposing and executing an action with the SC as dest and the respective func name diff --git a/energy-integration/governance-v2/src/lib.rs b/energy-integration/governance-v2/src/lib.rs index b0c924800..b28ef1335 100644 --- a/energy-integration/governance-v2/src/lib.rs +++ b/energy-integration/governance-v2/src/lib.rs @@ -27,8 +27,6 @@ pub trait GovernanceV2: + proposal_storage::ProposalStorageModule + caller_check::CallerCheckModule + views::ViewsModule - + energy_query::EnergyQueryModule - + permissions_module::PermissionsModule { /// - `min_energy_for_propose` - the minimum energy required for submitting a proposal; /// - `min_fee_for_propose` - the minimum fee required for submitting a proposal; diff --git a/energy-integration/governance-v2/src/views.rs b/energy-integration/governance-v2/src/views.rs index f448c887c..e59efc5da 100644 --- a/energy-integration/governance-v2/src/views.rs +++ b/energy-integration/governance-v2/src/views.rs @@ -10,8 +10,6 @@ pub trait ViewsModule: crate::proposal_storage::ProposalStorageModule + crate::configurable::ConfigurablePropertiesModule + crate::caller_check::CallerCheckModule - + permissions_module::PermissionsModule - + energy_query::EnergyQueryModule { #[view(getProposalStatus)] fn get_proposal_status(&self, proposal_id: ProposalId) -> GovernanceProposalStatus { @@ -121,11 +119,4 @@ pub trait ViewsModule: fn proposal_exists(&self, proposal_id: ProposalId) -> bool { self.is_valid_proposal_id(proposal_id) && !self.proposals().item_is_empty(proposal_id) } - - #[proxy] - fn fees_collector_proxy(&self, sc_address: ManagedAddress) -> fees_collector::Proxy; - - #[view(getFeesCollectorAddress)] - #[storage_mapper("feesCollectorAddress")] - fn fees_collector_address(&self) -> SingleValueMapper; } From cee59c3bb9518a78b9631509e7b1c5f453263f8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Thu, 27 Jul 2023 13:06:28 +0300 Subject: [PATCH 05/12] Governance-v2: Refactor balance -> quorum --- energy-integration/governance-v2/src/lib.rs | 18 +++++++++--------- .../governance-v2/src/proposal.rs | 2 +- energy-integration/governance-v2/src/views.rs | 2 +- .../governance-v2/tests/gov_rust_test.rs | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/energy-integration/governance-v2/src/lib.rs b/energy-integration/governance-v2/src/lib.rs index b28ef1335..25acab967 100644 --- a/energy-integration/governance-v2/src/lib.rs +++ b/energy-integration/governance-v2/src/lib.rs @@ -73,7 +73,7 @@ pub trait GovernanceV2: fn propose( &self, root_hash: ManagedByteArray, - total_balance: BigUint, + total_quorum: BigUint, description: ManagedBuffer, actions: MultiValueEncoded>, ) -> ProposalId { @@ -135,7 +135,7 @@ pub trait GovernanceV2: voting_delay_in_blocks, voting_period_in_blocks, withdraw_percentage_defeated, - total_balance, + total_quorum, proposal_start_block: current_block, }; let proposal_id = self.proposals().push(&proposal); @@ -147,13 +147,13 @@ pub trait GovernanceV2: proposal_id } - /// Vote on a proposal. The voting balance depends on the user's energy. + /// Vote on a proposal. The voting power depends on the user's quorum (number of tokens). #[endpoint] fn vote( &self, proposal_id: ProposalId, vote: VoteType, - user_balance: BigUint, + user_quorum: BigUint, proof: ArrayVec, PROOF_LENGTH>, ) { self.require_caller_not_self(); @@ -167,7 +167,7 @@ pub trait GovernanceV2: let new_user = self.user_voted_proposals(&voter).insert(proposal_id); require!(new_user, ALREADY_VOTED_ERR_MSG); - let voting_power = user_balance.sqrt(); + let voting_power = user_quorum.sqrt(); match self.get_root_hash(proposal_id) { OptionalValue::None => { @@ -187,28 +187,28 @@ pub trait GovernanceV2: proposal_votes.up_votes += &voting_power.clone(); proposal_votes.quorum += &voting_power.clone(); }); - self.up_vote_cast_event(&voter, proposal_id, &voting_power, &user_balance); + self.up_vote_cast_event(&voter, proposal_id, &voting_power, &user_quorum); } VoteType::DownVote => { self.proposal_votes(proposal_id).update(|proposal_votes| { proposal_votes.down_votes += &voting_power.clone(); proposal_votes.quorum += &voting_power.clone(); }); - self.down_vote_cast_event(&voter, proposal_id, &voting_power, &user_balance); + self.down_vote_cast_event(&voter, proposal_id, &voting_power, &user_quorum); } VoteType::DownVetoVote => { self.proposal_votes(proposal_id).update(|proposal_votes| { proposal_votes.down_veto_votes += &voting_power.clone(); proposal_votes.quorum += &voting_power.clone(); }); - self.down_veto_vote_cast_event(&voter, proposal_id, &voting_power, &user_balance); + self.down_veto_vote_cast_event(&voter, proposal_id, &voting_power, &user_quorum); } VoteType::AbstainVote => { self.proposal_votes(proposal_id).update(|proposal_votes| { proposal_votes.abstain_votes += &voting_power.clone(); proposal_votes.quorum += &voting_power.clone(); }); - self.abstain_vote_cast_event(&voter, proposal_id, &voting_power, &user_balance); + self.abstain_vote_cast_event(&voter, proposal_id, &voting_power, &user_quorum); } } self.user_voted_proposals(&voter).insert(proposal_id); diff --git a/energy-integration/governance-v2/src/proposal.rs b/energy-integration/governance-v2/src/proposal.rs index 57ac96c17..b91f57969 100644 --- a/energy-integration/governance-v2/src/proposal.rs +++ b/energy-integration/governance-v2/src/proposal.rs @@ -64,6 +64,6 @@ pub struct GovernanceProposal { pub voting_delay_in_blocks: u64, pub voting_period_in_blocks: u64, pub withdraw_percentage_defeated: u64, - pub total_balance: BigUint, + pub total_quorum: BigUint, pub proposal_start_block: u64, } diff --git a/energy-integration/governance-v2/src/views.rs b/energy-integration/governance-v2/src/views.rs index e59efc5da..23c7f20ad 100644 --- a/energy-integration/governance-v2/src/views.rs +++ b/energy-integration/governance-v2/src/views.rs @@ -91,7 +91,7 @@ pub trait ViewsModule: fn quorum_reached(&self, proposal_id: ProposalId) -> bool { let proposal = self.proposals().get(proposal_id); - let total_balance = proposal.total_balance; + let total_balance = proposal.total_quorum; if total_balance == 0u64 { return false; diff --git a/energy-integration/governance-v2/tests/gov_rust_test.rs b/energy-integration/governance-v2/tests/gov_rust_test.rs index 4e99595cd..c35c72b50 100644 --- a/energy-integration/governance-v2/tests/gov_rust_test.rs +++ b/energy-integration/governance-v2/tests/gov_rust_test.rs @@ -138,7 +138,7 @@ fn gov_propose_total_energy_0_test() { .b_mock .execute_query(&gov_setup.gov_wrapper, |sc| { let mut proposal = sc.proposals().get(1); - proposal.total_balance = managed_biguint!(0); + proposal.total_quorum = managed_biguint!(0); sc.proposals().set(1, &proposal); assert!( sc.get_proposal_status(1) == GovernanceProposalStatus::Defeated, From 96f670f12b5083e587a104690fe85ce6cddc22b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Thu, 27 Jul 2023 13:25:08 +0300 Subject: [PATCH 06/12] Governance-v2: Rebuild contracts + refactor events --- .../governance-v2/src/configurable.rs | 19 +- .../governance-v2/src/events.rs | 16 +- energy-integration/governance-v2/src/lib.rs | 9 +- .../governance-v2/tests/gov_rust_test.rs | 2 +- .../governance-v2/wasm/Cargo.lock | 182 ------------------ .../governance-v2/wasm/src/lib.rs | 16 +- 6 files changed, 15 insertions(+), 229 deletions(-) diff --git a/energy-integration/governance-v2/src/configurable.rs b/energy-integration/governance-v2/src/configurable.rs index 81a56e398..11235c71b 100644 --- a/energy-integration/governance-v2/src/configurable.rs +++ b/energy-integration/governance-v2/src/configurable.rs @@ -9,10 +9,9 @@ multiversx_sc::imports!(); /// - voting/downvoting a certain proposal /// - after a voting period, either putting the action in a queue (if it reached quorum), or canceling /// -/// Voting is done through energy. +/// Voting is done through tokens ownership. /// /// The module provides the following configurable parameters: -/// - `minEnergyForPropose` - the minimum energy required for submitting a proposal /// - `quorum` - the minimum number of (`votes` minus `downvotes`) at the end of voting period /// - `maxActionsPerProposal` - Maximum number of actions (transfers and/or smart contract calls) that a proposal may have /// - `votingDelayInBlocks` - Number of blocks to wait after a block is proposed before being able to vote/downvote that proposal @@ -45,12 +44,6 @@ pub trait ConfigurablePropertiesModule { // endpoints - these can only be called by the SC itself. // i.e. only by proposing and executing an action with the SC as dest and the respective func name - #[only_owner] - #[endpoint(changeMinEnergyForProposal)] - fn change_min_energy_for_propose(&self, new_value: BigUint) { - self.try_change_min_energy_for_propose(new_value); - } - #[only_owner] #[endpoint(changeMinFeeForProposal)] fn change_min_fee_for_propose(&self, new_value: BigUint) { @@ -75,12 +68,6 @@ pub trait ConfigurablePropertiesModule { self.try_change_voting_period_in_blocks(new_value); } - fn try_change_min_energy_for_propose(&self, new_value: BigUint) { - require!(new_value != 0, "Min energy for proposal can't be set to 0"); - - self.min_energy_for_propose().set(&new_value); - } - fn try_change_min_fee_for_propose(&self, new_value: BigUint) { let minimum_min_fee = BigUint::from(MIN_MIN_FEE_FOR_PROPOSE) * BigUint::from(DECIMALS_CONST); @@ -135,10 +122,6 @@ pub trait ConfigurablePropertiesModule { self.fee_token_id().set_if_empty(&fee_token_id); } - #[view(getMinEnergyForPropose)] - #[storage_mapper("minEnergyForPropose")] - fn min_energy_for_propose(&self) -> SingleValueMapper; - #[view(getMinFeeForPropose)] #[storage_mapper("minFeeForPropose")] fn min_fee_for_propose(&self) -> SingleValueMapper; diff --git a/energy-integration/governance-v2/src/events.rs b/energy-integration/governance-v2/src/events.rs index 763f7a1c4..eb736bcc9 100644 --- a/energy-integration/governance-v2/src/events.rs +++ b/energy-integration/governance-v2/src/events.rs @@ -19,8 +19,8 @@ pub trait EventsModule { &self, #[indexed] up_voter: &ManagedAddress, #[indexed] proposal_id: ProposalId, - #[indexed] nr_votes: &BigUint, - #[indexed] energy: &BigUint, + #[indexed] voting_power: &BigUint, + #[indexed] user_quorum: &BigUint, ); #[event("downVoteCast")] @@ -28,8 +28,8 @@ pub trait EventsModule { &self, #[indexed] down_voter: &ManagedAddress, #[indexed] proposal_id: ProposalId, - #[indexed] nr_votes: &BigUint, - #[indexed] energy: &BigUint, + #[indexed] voting_power: &BigUint, + #[indexed] user_quorum: &BigUint, ); #[event("downVetoVoteCast")] @@ -37,8 +37,8 @@ pub trait EventsModule { &self, #[indexed] down_veto_voter: &ManagedAddress, #[indexed] proposal_id: ProposalId, - #[indexed] nr_votes: &BigUint, - #[indexed] energy: &BigUint, + #[indexed] voting_power: &BigUint, + #[indexed] user_quorum: &BigUint, ); #[event("abstainVoteCast")] @@ -46,8 +46,8 @@ pub trait EventsModule { &self, #[indexed] abstain_voter: &ManagedAddress, #[indexed] proposal_id: ProposalId, - #[indexed] nr_votes: &BigUint, - #[indexed] energy: &BigUint, + #[indexed] voting_power: &BigUint, + #[indexed] user_quorum: &BigUint, ); #[event("proposalCanceled")] diff --git a/energy-integration/governance-v2/src/lib.rs b/energy-integration/governance-v2/src/lib.rs index 25acab967..359652149 100644 --- a/energy-integration/governance-v2/src/lib.rs +++ b/energy-integration/governance-v2/src/lib.rs @@ -28,7 +28,6 @@ pub trait GovernanceV2: + caller_check::CallerCheckModule + views::ViewsModule { - /// - `min_energy_for_propose` - the minimum energy required for submitting a proposal; /// - `min_fee_for_propose` - the minimum fee required for submitting a proposal; /// - `quorum` - the minimum number of (`votes` minus `downvotes`) at the end of voting period; /// - `votingDelayInBlocks` - Number of blocks to wait after a block is proposed before being able to vote/downvote that proposal; @@ -38,7 +37,6 @@ pub trait GovernanceV2: #[init] fn init( &self, - // min_energy_for_propose: BigUint, min_fee_for_propose: BigUint, quorum_percentage: BigUint, voting_delay_in_blocks: u64, @@ -46,7 +44,6 @@ pub trait GovernanceV2: withdraw_percentage_defeated: u64, fee_token: TokenIdentifier, ) { - // self.try_change_min_energy_for_propose(min_energy_for_propose); self.try_change_min_fee_for_propose(min_fee_for_propose); self.try_change_quorum_percentage(quorum_percentage); self.try_change_voting_delay_in_blocks(voting_delay_in_blocks); @@ -65,7 +62,7 @@ pub trait GovernanceV2: /// - endpoint to be called on the destination /// - a vector of arguments for the endpoint, in the form of ManagedVec /// - /// The proposer's energy is NOT automatically used for voting. A separate vote is needed. + /// The proposer's quorum is NOT automatically used for voting. A separate vote is needed. /// /// Returns the ID of the newly created proposal. #[payable("*")] @@ -86,10 +83,6 @@ pub trait GovernanceV2: ); let proposer = self.blockchain().get_caller(); - // let user_energy = self.get_energy_amount_non_zero(&proposer); - // let min_energy_for_propose = self.min_energy_for_propose().get(); - // require!(user_energy >= min_energy_for_propose, NOT_ENOUGH_ENERGY); - let user_fee = self.call_value().single_esdt(); require!( self.fee_token_id().get() == user_fee.token_identifier, diff --git a/energy-integration/governance-v2/tests/gov_rust_test.rs b/energy-integration/governance-v2/tests/gov_rust_test.rs index c35c72b50..f8b443b41 100644 --- a/energy-integration/governance-v2/tests/gov_rust_test.rs +++ b/energy-integration/governance-v2/tests/gov_rust_test.rs @@ -111,7 +111,7 @@ fn gov_propose_test() { } #[test] -fn gov_propose_total_energy_0_test() { +fn gov_propose_total_quorum_0_test() { let mut gov_setup = GovSetup::new(governance_v2::contract_obj); let first_user_addr = gov_setup.first_user.clone(); diff --git a/energy-integration/governance-v2/wasm/Cargo.lock b/energy-integration/governance-v2/wasm/Cargo.lock index 40bcf7baa..7dc6f8db8 100644 --- a/energy-integration/governance-v2/wasm/Cargo.lock +++ b/energy-integration/governance-v2/wasm/Cargo.lock @@ -43,95 +43,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "common-types" -version = "0.0.0" -dependencies = [ - "multiversx-sc", -] - -[[package]] -name = "common_errors" -version = "0.0.0" -dependencies = [ - "multiversx-sc", -] - -[[package]] -name = "common_structs" -version = "0.0.0" -dependencies = [ - "fixed-supply-token", - "math", - "mergeable", - "multiversx-sc", - "unwrappable", -] - [[package]] name = "endian-type" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" -[[package]] -name = "energy-factory" -version = "0.0.0" -dependencies = [ - "common_structs", - "legacy_token_decode_module", - "math", - "mergeable", - "multiversx-sc", - "multiversx-sc-modules", - "sc_whitelist_module", - "simple-lock", - "unwrappable", - "utils", -] - -[[package]] -name = "energy-query" -version = "0.0.0" -dependencies = [ - "energy-factory", - "multiversx-sc", -] - -[[package]] -name = "fees-collector" -version = "0.0.0" -dependencies = [ - "common-types", - "common_errors", - "energy-factory", - "energy-query", - "locking_module", - "multiversx-sc", - "multiversx-sc-modules", - "sc_whitelist_module", - "simple-lock", - "utils", - "week-timekeeping", - "weekly-rewards-splitting", -] - -[[package]] -name = "fixed-supply-token" -version = "0.0.0" -dependencies = [ - "multiversx-sc", -] - [[package]] name = "governance-v2" version = "0.0.0" dependencies = [ - "energy-query", - "fees-collector", "multiversx-sc", - "permissions_module", - "weekly-rewards-splitting", ] [[package]] @@ -163,50 +85,18 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" -[[package]] -name = "legacy_token_decode_module" -version = "0.0.0" -dependencies = [ - "common_structs", - "multiversx-sc", - "utils", -] - [[package]] name = "libc" version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" -[[package]] -name = "locking_module" -version = "0.0.0" -dependencies = [ - "energy-factory", - "multiversx-sc", - "simple-lock", -] - -[[package]] -name = "math" -version = "0.0.0" -dependencies = [ - "multiversx-sc", -] - [[package]] name = "memory_units" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" -[[package]] -name = "mergeable" -version = "0.0.0" -dependencies = [ - "multiversx-sc", -] - [[package]] name = "multiversx-sc" version = "0.39.4" @@ -257,15 +147,6 @@ dependencies = [ "syn", ] -[[package]] -name = "multiversx-sc-modules" -version = "0.39.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12284a3e31c0852b6ca0ce8306d3f404c3712b996a05ed78e97e765c98461f3" -dependencies = [ - "multiversx-sc", -] - [[package]] name = "multiversx-sc-wasm-adapter" version = "0.39.4" @@ -300,15 +181,6 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" -[[package]] -name = "permissions_module" -version = "0.0.0" -dependencies = [ - "bitflags", - "common_errors", - "multiversx-sc", -] - [[package]] name = "proc-macro2" version = "1.0.50" @@ -337,23 +209,6 @@ dependencies = [ "nibble_vec", ] -[[package]] -name = "sc_whitelist_module" -version = "0.0.0" -dependencies = [ - "common_errors", - "multiversx-sc", -] - -[[package]] -name = "simple-lock" -version = "0.0.0" -dependencies = [ - "common_structs", - "multiversx-sc", - "multiversx-sc-modules", -] - [[package]] name = "smallvec" version = "1.10.0" @@ -377,23 +232,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" -[[package]] -name = "unwrappable" -version = "0.0.0" -dependencies = [ - "multiversx-sc", -] - -[[package]] -name = "utils" -version = "0.0.0" -dependencies = [ - "common_structs", - "fixed-supply-token", - "mergeable", - "multiversx-sc", -] - [[package]] name = "version_check" version = "0.9.4" @@ -412,26 +250,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "week-timekeeping" -version = "0.0.0" -dependencies = [ - "common-types", - "multiversx-sc", -] - -[[package]] -name = "weekly-rewards-splitting" -version = "0.0.0" -dependencies = [ - "common-types", - "energy-query", - "math", - "multiversx-sc", - "unwrappable", - "week-timekeeping", -] - [[package]] name = "winapi" version = "0.3.9" diff --git a/energy-integration/governance-v2/wasm/src/lib.rs b/energy-integration/governance-v2/wasm/src/lib.rs index e70fd2cb9..98ea5cb27 100644 --- a/energy-integration/governance-v2/wasm/src/lib.rs +++ b/energy-integration/governance-v2/wasm/src/lib.rs @@ -5,9 +5,9 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 27 +// Endpoints: 19 // Async Callback (empty): 1 -// Total number of exported functions: 29 +// Total number of exported functions: 21 #![no_std] #![feature(alloc_error_handler, lang_items)] @@ -22,12 +22,10 @@ multiversx_sc_wasm_adapter::endpoints! { vote cancel withdrawDeposit - changeMinEnergyForProposal changeMinFeeForProposal - changeQuorum + changeQuorumPercentage changeVotingDelayInBlocks changeVotingPeriodInBlocks - getMinEnergyForPropose getMinFeeForPropose getQuorum getVotingDelayInBlocks @@ -38,13 +36,7 @@ multiversx_sc_wasm_adapter::endpoints! { getUserVotedProposals getProposalVotes getProposalStatus - getFeesCollectorAddress - setEnergyFactoryAddress - getEnergyFactoryAddress - addAdmin - removeAdmin - updateOwnerOrAdmin - getPermissions + getProposalRootHash ) } From c26fa5ad97b4e33b0a3f986c579e722cb65bd421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Fri, 28 Jul 2023 10:29:17 +0300 Subject: [PATCH 07/12] Governance-v2: only_owner to propose + tests fix --- energy-integration/governance-v2/src/lib.rs | 2 +- energy-integration/governance-v2/src/views.rs | 7 +++---- .../governance-v2/tests/gov_test_setup/mod.rs | 12 ++++++++---- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/energy-integration/governance-v2/src/lib.rs b/energy-integration/governance-v2/src/lib.rs index b40cd102b..41ebd8fa8 100644 --- a/energy-integration/governance-v2/src/lib.rs +++ b/energy-integration/governance-v2/src/lib.rs @@ -65,6 +65,7 @@ pub trait GovernanceV2: /// The proposer's quorum is NOT automatically used for voting. A separate vote is needed. /// /// Returns the ID of the newly created proposal. + #[only_owner] #[payable("*")] #[endpoint] fn propose( @@ -204,7 +205,6 @@ pub trait GovernanceV2: self.abstain_vote_cast_event(&voter, proposal_id, &voting_power, &user_quorum); } } - self.user_voted_proposals(&voter).insert(proposal_id); } /// Cancel a proposed action. This can be done: diff --git a/energy-integration/governance-v2/src/views.rs b/energy-integration/governance-v2/src/views.rs index e027f2365..700d97ffc 100644 --- a/energy-integration/governance-v2/src/views.rs +++ b/energy-integration/governance-v2/src/views.rs @@ -91,17 +91,16 @@ pub trait ViewsModule: fn quorum_reached(&self, proposal_id: ProposalId) -> bool { let proposal = self.proposals().get(proposal_id); - let total_quorum_for_proposal = proposal.total_quorum; + let total_quorum = proposal.total_quorum; - if total_quorum_for_proposal == 0u64 { + if total_quorum == 0u64 { return false; } let required_minimum_percentage = proposal.minimum_quorum; let current_quorum = self.proposal_votes(proposal_id).get().quorum; - let current_quorum_percentage = - current_quorum * FULL_PERCENTAGE / total_quorum_for_proposal; + let current_quorum_percentage = current_quorum * FULL_PERCENTAGE / total_quorum; current_quorum_percentage >= required_minimum_percentage } diff --git a/energy-integration/governance-v2/tests/gov_test_setup/mod.rs b/energy-integration/governance-v2/tests/gov_test_setup/mod.rs index 5e74a9f54..19553910e 100644 --- a/energy-integration/governance-v2/tests/gov_test_setup/mod.rs +++ b/energy-integration/governance-v2/tests/gov_test_setup/mod.rs @@ -23,8 +23,10 @@ pub const LOCKING_PERIOD_BLOCKS: u64 = 30; pub const WITHDRAW_PERCENTAGE: u64 = 5_000; // 50% pub const WXMEX_TOKEN_ID: &[u8] = b"WXMEX-123456"; pub const DECIMALS_CONST: u64 = 1_000_000_000_000_000_000; -pub const QUORUM: u64 = 217_433_990_694; -pub const GAS_LIMIT: u64 = 1_000_000; +pub const GAS_LIMIT: u64 = 1_000_000u64; +pub const FIRST_USER_QUORUM: u64 = 217_433_990_694u64; +pub const SECOND_USER_QUORUM: u64 = 59_024_824_840u64; +pub const THIRD_USER_QUORUM: u64 = 40_000_000_000u64; #[derive(Clone)] pub struct Payment { @@ -136,10 +138,12 @@ where ) .into(), ); - + let total_quorum = managed_biguint!(FIRST_USER_QUORUM).pow(2) + + managed_biguint!(SECOND_USER_QUORUM).pow(2) + + managed_biguint!(THIRD_USER_QUORUM).pow(2); proposal_id = sc.propose( root_hash, - managed_biguint!(QUORUM), + total_quorum, managed_buffer!(b"changeTODO"), actions, ); From 68a6f4614964129835c8d6dcca54e3f63a58252a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Fri, 28 Jul 2023 17:44:36 +0300 Subject: [PATCH 08/12] Governanace-v2: Minor fix Fix verify_merkle_proof() in vote endpoint. --- energy-integration/governance-v2/src/lib.rs | 2 +- .../governance-v2/tests/gov_test_setup/mod.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/energy-integration/governance-v2/src/lib.rs b/energy-integration/governance-v2/src/lib.rs index 41ebd8fa8..b0d45a3b3 100644 --- a/energy-integration/governance-v2/src/lib.rs +++ b/energy-integration/governance-v2/src/lib.rs @@ -169,7 +169,7 @@ pub trait GovernanceV2: } OptionalValue::Some(root_hash) => { require!( - self.verify_merkle_proof(voting_power.clone(), proof, root_hash), + self.verify_merkle_proof(user_quorum.clone(), proof, root_hash), INVALID_MERKLE_PROOF ); } diff --git a/energy-integration/governance-v2/tests/gov_test_setup/mod.rs b/energy-integration/governance-v2/tests/gov_test_setup/mod.rs index 19553910e..cc2edc2dd 100644 --- a/energy-integration/governance-v2/tests/gov_test_setup/mod.rs +++ b/energy-integration/governance-v2/tests/gov_test_setup/mod.rs @@ -138,9 +138,9 @@ where ) .into(), ); - let total_quorum = managed_biguint!(FIRST_USER_QUORUM).pow(2) - + managed_biguint!(SECOND_USER_QUORUM).pow(2) - + managed_biguint!(THIRD_USER_QUORUM).pow(2); + let total_quorum = managed_biguint!(FIRST_USER_QUORUM) + + managed_biguint!(SECOND_USER_QUORUM) + + managed_biguint!(THIRD_USER_QUORUM); proposal_id = sc.propose( root_hash, total_quorum, @@ -425,15 +425,15 @@ where } pub fn get_first_user_voting_power(&self) -> BigUint { - BigUint::from(217_433_990_694u64).pow(2) + BigUint::from(217_433_990_694u64) } pub fn get_second_user_voting_power(&self) -> BigUint { - BigUint::from(59_024_824_840u64).pow(2) + BigUint::from(59_024_824_840u64) } pub fn get_third_user_voting_power(&self) -> BigUint { - BigUint::from(40_000_000_000u64).pow(2) + BigUint::from(40_000_000_000u64) } pub fn get_merkle_root_hash(&self) -> ManagedByteArray { From 1183f45401326c6576a10d2436e221d13373553e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Mon, 7 Aug 2023 15:13:45 +0300 Subject: [PATCH 09/12] Governance-v2: voting_power = user_quorum --- energy-integration/governance-v2/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/energy-integration/governance-v2/src/lib.rs b/energy-integration/governance-v2/src/lib.rs index b0d45a3b3..efaf6cdd1 100644 --- a/energy-integration/governance-v2/src/lib.rs +++ b/energy-integration/governance-v2/src/lib.rs @@ -161,7 +161,7 @@ pub trait GovernanceV2: let new_user = self.user_voted_proposals(&voter).insert(proposal_id); require!(new_user, ALREADY_VOTED_ERR_MSG); - let voting_power = user_quorum.sqrt(); + let voting_power = user_quorum; match self.get_root_hash(proposal_id) { OptionalValue::None => { From 8cc77d61ce431455fd616716909b1a4ae6f32d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Mon, 7 Aug 2023 15:23:12 +0300 Subject: [PATCH 10/12] Governance-v2: Fix clippy issues --- energy-integration/governance-v2/src/lib.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/energy-integration/governance-v2/src/lib.rs b/energy-integration/governance-v2/src/lib.rs index efaf6cdd1..c914e3a95 100644 --- a/energy-integration/governance-v2/src/lib.rs +++ b/energy-integration/governance-v2/src/lib.rs @@ -161,7 +161,7 @@ pub trait GovernanceV2: let new_user = self.user_voted_proposals(&voter).insert(proposal_id); require!(new_user, ALREADY_VOTED_ERR_MSG); - let voting_power = user_quorum; + let voting_power = &user_quorum; match self.get_root_hash(proposal_id) { OptionalValue::None => { @@ -178,31 +178,31 @@ pub trait GovernanceV2: match vote { VoteType::UpVote => { self.proposal_votes(proposal_id).update(|proposal_votes| { - proposal_votes.up_votes += &voting_power.clone(); + proposal_votes.up_votes += voting_power.clone(); proposal_votes.quorum += &user_quorum.clone(); }); - self.up_vote_cast_event(&voter, proposal_id, &voting_power, &user_quorum); + self.up_vote_cast_event(&voter, proposal_id, voting_power, &user_quorum); } VoteType::DownVote => { self.proposal_votes(proposal_id).update(|proposal_votes| { - proposal_votes.down_votes += &voting_power.clone(); + proposal_votes.down_votes += voting_power.clone(); proposal_votes.quorum += &user_quorum.clone(); }); - self.down_vote_cast_event(&voter, proposal_id, &voting_power, &user_quorum); + self.down_vote_cast_event(&voter, proposal_id, voting_power, &user_quorum); } VoteType::DownVetoVote => { self.proposal_votes(proposal_id).update(|proposal_votes| { - proposal_votes.down_veto_votes += &voting_power.clone(); + proposal_votes.down_veto_votes += voting_power.clone(); proposal_votes.quorum += &user_quorum.clone(); }); - self.down_veto_vote_cast_event(&voter, proposal_id, &voting_power, &user_quorum); + self.down_veto_vote_cast_event(&voter, proposal_id, voting_power, &user_quorum); } VoteType::AbstainVote => { self.proposal_votes(proposal_id).update(|proposal_votes| { - proposal_votes.abstain_votes += &voting_power.clone(); + proposal_votes.abstain_votes += voting_power.clone(); proposal_votes.quorum += &user_quorum.clone(); }); - self.abstain_vote_cast_event(&voter, proposal_id, &voting_power, &user_quorum); + self.abstain_vote_cast_event(&voter, proposal_id, voting_power, &user_quorum); } } } From 78c8db5baa26cb562d43ba182f83abb0f25f79e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Mon, 7 Aug 2023 16:16:54 +0300 Subject: [PATCH 11/12] Governance-v2: Fix typos --- energy-integration/governance-v2/src/errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/energy-integration/governance-v2/src/errors.rs b/energy-integration/governance-v2/src/errors.rs index f1676ff79..2a8f3bf1f 100644 --- a/energy-integration/governance-v2/src/errors.rs +++ b/energy-integration/governance-v2/src/errors.rs @@ -8,7 +8,7 @@ pub const INVALID_ROOT_HASH: &[u8] = b"Invalid root hash provided"; pub const PROPOSAL_NO_ACTION: &[u8] = b"Proposal has no actions"; pub const EXEEDED_MAX_ACTIONS: &[u8] = b"Exceeded max actions per proposal"; pub const ONLY_PROPOSER_CANCEL: &[u8] = b"Only original proposer may cancel a pending proposal"; -pub const ONLY_PROPOSER_WITHDRAW: &[u8] = b"Only original proposer may cancel a pending proposal"; +pub const ONLY_PROPOSER_WITHDRAW: &[u8] = b"Only original proposer may withdraw a pending proposal"; pub const NO_PROPOSAL: &[u8] = b"Proposal does not exist"; pub const WITHDRAW_NOT_ALLOWED: &[u8] = b"You may not withdraw funds from this proposal!"; pub const INVALID_MERKLE_PROOF: &[u8] = b"Invalid merkle proof provided"; From 1a9a40ad1e33e6f42069717e0b5a28b0c323a2a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Mon, 7 Aug 2023 16:22:38 +0300 Subject: [PATCH 12/12] Governance-v2: Fix tests; MIN_FEE = 1 --- energy-integration/governance-v2/src/configurable.rs | 2 +- energy-integration/governance-v2/tests/gov_rust_test.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/energy-integration/governance-v2/src/configurable.rs b/energy-integration/governance-v2/src/configurable.rs index 11235c71b..3df438fef 100644 --- a/energy-integration/governance-v2/src/configurable.rs +++ b/energy-integration/governance-v2/src/configurable.rs @@ -35,7 +35,7 @@ const MIN_VOTING_PERIOD: u64 = 14_400; // 24 Hours const MAX_VOTING_PERIOD: u64 = 201_600; // 2 Weeks const MIN_QUORUM: u64 = 1_000; // 10% const MAX_QUORUM: u64 = 6_000; // 60% -const MIN_MIN_FEE_FOR_PROPOSE: u64 = 2_000_000; +const MIN_MIN_FEE_FOR_PROPOSE: u64 = 1; const MAX_MIN_FEE_FOR_PROPOSE: u64 = 200_000_000_000; const DECIMALS_CONST: u64 = 1_000_000_000_000_000_000; diff --git a/energy-integration/governance-v2/tests/gov_rust_test.rs b/energy-integration/governance-v2/tests/gov_rust_test.rs index f8b443b41..f2cc5bf9e 100644 --- a/energy-integration/governance-v2/tests/gov_rust_test.rs +++ b/energy-integration/governance-v2/tests/gov_rust_test.rs @@ -470,7 +470,7 @@ fn gov_withdraw_defeated_proposal_test() { // Other user (not proposer) try to withdraw the fee -> Fail gov_setup .withdraw_after_defeated(&third_user_addr, proposal_id) - .assert_error(4, "Only original proposer may cancel a pending proposal"); + .assert_error(4, "Only original proposer may withdraw a pending proposal"); // Proposer withdraw gov_setup @@ -562,7 +562,7 @@ fn gov_modify_withdraw_defeated_proposal_test() { // Other user (not proposer) try to withdraw the fee -> Fail gov_setup .withdraw_after_defeated(&third_user_addr, proposal_id) - .assert_error(4, "Only original proposer may cancel a pending proposal"); + .assert_error(4, "Only original proposer may withdraw a pending proposal"); // Proposer withdraw gov_setup @@ -650,7 +650,7 @@ fn gov_withdraw_no_with_veto_defeated_proposal_test() { // Other user (not proposer) try to withdraw the fee -> Fail gov_setup .withdraw_after_defeated(&third_user_addr, proposal_id) - .assert_error(4, "Only original proposer may cancel a pending proposal"); + .assert_error(4, "Only original proposer may withdraw a pending proposal"); // Proposer withdraw gov_setup