From 906e146c540b2165ed1ee0118e2f93114213fd96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Mon, 19 Aug 2024 15:35:30 +0300 Subject: [PATCH] Fixes after review --- .../src/potlock_interactor_main.rs | 16 ----- contracts/potlock/interact-rs/src/proxy.rs | 9 --- contracts/potlock/src/potlock.rs | 2 + .../potlock/src/potlock_admin_interactions.rs | 57 ++++++++++----- contracts/potlock/src/potlock_interactions.rs | 35 +++++++--- contracts/potlock/src/potlock_requirements.rs | 69 +++++++++++++++++++ contracts/potlock/src/potlock_storage.rs | 58 +--------------- contracts/potlock/tests/potlock_proxy.rs | 9 --- contracts/potlock/wasm/src/lib.rs | 2 +- 9 files changed, 136 insertions(+), 121 deletions(-) create mode 100644 contracts/potlock/src/potlock_requirements.rs diff --git a/contracts/potlock/interact-rs/src/potlock_interactor_main.rs b/contracts/potlock/interact-rs/src/potlock_interactor_main.rs index 94b69fb8..69f02b79 100644 --- a/contracts/potlock/interact-rs/src/potlock_interactor_main.rs +++ b/contracts/potlock/interact-rs/src/potlock_interactor_main.rs @@ -39,7 +39,6 @@ async fn main() { "getFeeTokenIdentifier" => interact.fee_token_identifier().await, "getFeeAmount" => interact.fee_amount().await, "feePotPayments" => interact.fee_pot_proposer().await, - "feeAmountAcceptPots" => interact.fee_amount_accepted_pots().await, "potDonations" => interact.pot_donations().await, "projectDonations" => interact.project_donations().await, "isAdmin" => interact.is_admin().await, @@ -400,21 +399,6 @@ impl ContractInteract { println!("Result: {result_value:?}"); } - async fn fee_amount_accepted_pots(&mut self) { - let result_value = self - .interactor - .query() - .to(self.state.current_address()) - .typed(proxy::PotlockProxy) - .fee_amount_accepted_pots() - .returns(ReturnsResultUnmanaged) - .prepare_async() - .run() - .await; - - println!("Result: {result_value:?}"); - } - async fn pot_donations(&mut self) { let project_id = 0u32; diff --git a/contracts/potlock/interact-rs/src/proxy.rs b/contracts/potlock/interact-rs/src/proxy.rs index df8acf2a..7f85577e 100644 --- a/contracts/potlock/interact-rs/src/proxy.rs +++ b/contracts/potlock/interact-rs/src/proxy.rs @@ -279,15 +279,6 @@ where .original_result() } - pub fn fee_amount_accepted_pots( - self, - ) -> TxTypedCall> { - self.wrapped_tx - .payment(NotPayable) - .raw_call("feeAmountAcceptPots") - .original_result() - } - pub fn pot_donations< Arg0: ProxyArg, >( diff --git a/contracts/potlock/src/potlock.rs b/contracts/potlock/src/potlock.rs index 6ea6a936..6d0502d4 100644 --- a/contracts/potlock/src/potlock.rs +++ b/contracts/potlock/src/potlock.rs @@ -4,12 +4,14 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); pub mod potlock_admin_interactions; pub mod potlock_interactions; +pub mod potlock_requirements; pub mod potlock_storage; #[multiversx_sc::contract] pub trait Potlock: potlock_admin_interactions::PotlockAdminInteractions + potlock_interactions::PotlockInteractions + + potlock_requirements::PotlockRequirements + potlock_storage::PotlockStorage + multiversx_sc_modules::only_admin::OnlyAdminModule { diff --git a/contracts/potlock/src/potlock_admin_interactions.rs b/contracts/potlock/src/potlock_admin_interactions.rs index 3c06b251..02fd86a0 100644 --- a/contracts/potlock/src/potlock_admin_interactions.rs +++ b/contracts/potlock/src/potlock_admin_interactions.rs @@ -1,14 +1,18 @@ -use crate::potlock_storage::{self, PotlockId, ProjectId, Status}; +use crate::{ + potlock_requirements::{self, MAX_PERCENTAGE}, + potlock_storage::{self, PotlockId, ProjectId, Status}, +}; multiversx_sc::imports!(); multiversx_sc::derive_imports!(); pub type ProjectPercentage = MultiValue2; -pub const MAX_PERCENTAGE: u64 = 10_000; // 100% #[multiversx_sc::module] pub trait PotlockAdminInteractions: - potlock_storage::PotlockStorage + multiversx_sc_modules::only_admin::OnlyAdminModule + potlock_requirements::PotlockRequirements + + potlock_storage::PotlockStorage + + multiversx_sc_modules::only_admin::OnlyAdminModule { #[only_admin] #[endpoint(changeFeeForPots)] @@ -17,22 +21,17 @@ pub trait PotlockAdminInteractions: token_identifier.is_valid_esdt_identifier(), "Invalid token provided" ); - require!( - token_identifier.is_valid_esdt_identifier() && fee.gt(&BigUint::zero()), - "Invalid token identifier or amount is 0" - ); + require!(fee > 0, "Amount is 0"); self.fee_token_identifier().set(&token_identifier); - self.fee_amount().set(fee); + self.fee_amount().set_if_empty(fee); } #[only_admin] #[endpoint(acceptPot)] fn accept_pot(&self, potlock_id: PotlockId) { self.require_potlock_exists(potlock_id); - let fee_amount = self.fee_amount().get(); + self.require_potlock_is_inactive(potlock_id); - self.fee_amount_accepted_pots() - .update(|amount| *amount += fee_amount); let mut accepted_potlock = self.potlocks().get(potlock_id); accepted_potlock.status = Status::Active; self.potlocks().set(potlock_id, &accepted_potlock); @@ -42,6 +41,7 @@ pub trait PotlockAdminInteractions: #[endpoint(removePot)] fn remove_pot(&self, potlock_id: PotlockId) { self.require_potlock_exists(potlock_id); + self.require_potlock_is_inactive(potlock_id); let potlock_mapper = self.potlocks(); let pot_proposer = potlock_mapper.get(potlock_id).proposer; @@ -60,22 +60,35 @@ pub trait PotlockAdminInteractions: #[endpoint(acceptApplication)] fn accept_application(&self, project_id: ProjectId) { self.require_project_exists(project_id); - let mut accepted_projects = self.projects().get(project_id); - accepted_projects.status = Status::Active; - self.projects().set(project_id, &accepted_projects); + self.require_project_is_inactive(project_id); + + let mut accepted_project = self.projects().get(project_id); + accepted_project.status = Status::Active; + self.projects().set(project_id, &accepted_project); + } + + #[only_admin] + #[endpoint(removeApplication)] + fn remove_application(&self, project_id: ProjectId) { + self.require_project_exists(project_id); + self.require_project_is_active(project_id); + + let mut rejected_project = self.projects().get(project_id); + rejected_project.status = Status::Inactive; + self.projects().set(project_id, &rejected_project); } #[only_admin] #[endpoint(rejectDonation)] fn reject_donation(&self, potlock_id: PotlockId, user: ManagedAddress) { self.require_potlock_exists(potlock_id); - let opt_fee_pot_payments = self.pot_donations(potlock_id).get(&user); + let opt_fee_pot_payment = self.pot_donations(potlock_id).get(&user); - require!(opt_fee_pot_payments.is_some(), "No donation for this user"); - let fee_pot_payments = unsafe { opt_fee_pot_payments.unwrap_unchecked() }; + require!(opt_fee_pot_payment.is_some(), "No donation for this user"); + let fee_pot_payment = unsafe { opt_fee_pot_payment.unwrap_unchecked() }; self.send() - .direct_non_zero_esdt_payment(&user, &fee_pot_payments); + .direct_non_zero_esdt_payment(&user, &fee_pot_payment); self.pot_donations(potlock_id).remove(&user); } @@ -89,9 +102,17 @@ pub trait PotlockAdminInteractions: self.require_potlock_exists(potlock_id); self.require_correct_percentages(project_percentages.clone()); let pot_donations = self.pot_donations(potlock_id); + let all_projects = self.projects(); for pp in project_percentages { let (project_id, percentage) = pp.into_tuple(); + let project = all_projects.get(project_id); + + // The project must previously apply to this Pot + if project.potlock_id != potlock_id { + continue; + } + let mut output_payments = ManagedVec::new(); for (_, donation) in pot_donations.iter() { let project_share_amount = donation.amount * percentage / MAX_PERCENTAGE; diff --git a/contracts/potlock/src/potlock_interactions.rs b/contracts/potlock/src/potlock_interactions.rs index 3873f007..9634eb11 100644 --- a/contracts/potlock/src/potlock_interactions.rs +++ b/contracts/potlock/src/potlock_interactions.rs @@ -1,3 +1,4 @@ +use crate::potlock_requirements; use crate::potlock_storage::{self, Pot, Project}; use crate::potlock_storage::{PotlockId, ProjectId}; @@ -6,7 +7,9 @@ multiversx_sc::derive_imports!(); #[multiversx_sc::module] pub trait PotlockInteractions: - potlock_storage::PotlockStorage + multiversx_sc_modules::only_admin::OnlyAdminModule + potlock_requirements::PotlockRequirements + + potlock_storage::PotlockStorage + + multiversx_sc_modules::only_admin::OnlyAdminModule { #[payable("*")] #[endpoint(addPot)] @@ -33,21 +36,32 @@ pub trait PotlockInteractions: potlock_id: PotlockId, project_name: ManagedBuffer, description: ManagedBuffer, - ) { - let project_id = self.projects().len() + 1; + ) -> usize { let owner = self.blockchain().get_caller(); - let project = Project::new(project_id, potlock_id, project_name, description, owner); - self.projects().push(&project); + let project = Project::new(potlock_id, project_name, description, owner); + self.projects().push(&project) } #[payable("*")] #[endpoint(donateToPot)] fn donate_to_pot(&self, potlock_id: PotlockId) { - let payment = self.call_value().single_esdt(); - let caller = self.blockchain().get_caller(); self.require_potlock_exists(potlock_id); self.require_potlock_is_active(potlock_id); - self.pot_donations(potlock_id).insert(caller, payment); + + let payment = self.call_value().single_esdt(); + let caller = self.blockchain().get_caller(); + let mut pot_donations = self.pot_donations(potlock_id); + + match pot_donations.get(&caller) { + Some(mut previous_payment) => { + // let a = pot_donations.get(&caller).unwrap(); + previous_payment.amount += payment.amount; + pot_donations.insert(caller, previous_payment); + } + None => { + self.pot_donations(potlock_id).insert(caller, payment); + } + } } #[payable("*")] @@ -60,7 +74,7 @@ pub trait PotlockInteractions: let mut donation_mapper = self.project_donations(project_id); if donation_mapper.contains_key(&caller) { - let opt_payment = donation_mapper.remove(&caller); + let opt_payment = donation_mapper.get(&caller); if opt_payment.is_some() { let mut previous_payment = opt_payment.unwrap(); require!( @@ -68,8 +82,7 @@ pub trait PotlockInteractions: "Already made a payment with a different TokenID" ); previous_payment.amount += payment.amount; - self.project_donations(project_id) - .insert(caller, previous_payment); + donation_mapper.insert(caller, previous_payment); } } else { self.project_donations(project_id).insert(caller, payment); diff --git a/contracts/potlock/src/potlock_requirements.rs b/contracts/potlock/src/potlock_requirements.rs new file mode 100644 index 00000000..f923672a --- /dev/null +++ b/contracts/potlock/src/potlock_requirements.rs @@ -0,0 +1,69 @@ +use crate::{ + potlock_admin_interactions::ProjectPercentage, + potlock_storage::{self, PotlockId, ProjectId, Status}, +}; + +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); + +pub const MAX_PERCENTAGE: u64 = 10_000; // 100% + +#[multiversx_sc::module] +pub trait PotlockRequirements: potlock_storage::PotlockStorage { + fn is_valid_potlock_id(&self, potlock_id: PotlockId) -> bool { + potlock_id >= 1 && potlock_id <= self.potlocks().len() + } + + fn require_potlock_exists(&self, potlock_id: PotlockId) { + require!( + self.is_valid_potlock_id(potlock_id) && !self.potlocks().item_is_empty(potlock_id), + "Potlock doesn't exist!", + ) + } + + fn require_potlock_is_active(&self, potlock_id: PotlockId) { + let potlock = self.potlocks().get(potlock_id); + require!(potlock.status == Status::Active, "Pot is not active!",) + } + + fn require_potlock_is_inactive(&self, potlock_id: PotlockId) { + let potlock = self.potlocks().get(potlock_id); + require!(potlock.status != Status::Active, "Pot is active!",) + } + + fn is_valid_project_id(&self, project_id: ProjectId) -> bool { + project_id >= 1 && project_id <= self.projects().len() + } + + fn require_project_exists(&self, project_id: ProjectId) { + require!( + self.is_valid_project_id(project_id) && !self.projects().item_is_empty(project_id), + "Project doesn't exist!", + ) + } + + fn require_project_is_active(&self, project_id: ProjectId) { + let project = self.projects().get(project_id); + require!(project.status == Status::Active, "Project is not active!",) + } + + fn require_project_is_inactive(&self, project_id: ProjectId) { + let project = self.projects().get(project_id); + require!(project.status != Status::Active, "Project is active!",) + } + + fn require_correct_percentages( + &self, + project_percentages: MultiValueEncoded, + ) { + let mut total_perc: u64 = 0; + for pp in project_percentages { + let (_, perc) = pp.into_tuple(); + total_perc += perc; + } + require!( + total_perc <= MAX_PERCENTAGE, + "Total percentages more than 100%" + ); + } +} diff --git a/contracts/potlock/src/potlock_storage.rs b/contracts/potlock/src/potlock_storage.rs index 676bce9f..19b71bdf 100644 --- a/contracts/potlock/src/potlock_storage.rs +++ b/contracts/potlock/src/potlock_storage.rs @@ -1,5 +1,3 @@ -use crate::potlock_admin_interactions::{ProjectPercentage, MAX_PERCENTAGE}; - multiversx_sc::imports!(); multiversx_sc::derive_imports!(); @@ -44,7 +42,6 @@ impl Pot { #[derive(TypeAbi, NestedEncode, NestedDecode, PartialEq, Debug, TopEncode, TopDecode)] pub struct Project { - pub project_id: ProjectId, pub potlock_id: PotlockId, pub name: ManagedBuffer, pub description: ManagedBuffer, @@ -54,14 +51,12 @@ pub struct Project { impl Project { pub fn new( - project_id: ProjectId, potlock_id: PotlockId, name: ManagedBuffer, description: ManagedBuffer, owner: ManagedAddress, ) -> Self { Project { - project_id, potlock_id, name, description, @@ -79,53 +74,6 @@ pub struct UserDonations { #[multiversx_sc::module] pub trait PotlockStorage { - fn is_valid_potlock_id(&self, potlock_id: PotlockId) -> bool { - potlock_id >= 1 && potlock_id <= self.potlocks().len() - } - - fn require_potlock_exists(&self, potlock_id: PotlockId) { - require!( - self.is_valid_potlock_id(potlock_id) && !self.potlocks().item_is_empty(potlock_id), - "Potlock doesn't exist!", - ) - } - - fn require_potlock_is_active(&self, potlock_id: PotlockId) { - let potlock = self.potlocks().get(potlock_id); - require!(potlock.status == Status::Active, "Pot is not active!",) - } - - fn is_valid_project_id(&self, project_id: ProjectId) -> bool { - project_id >= 1 && project_id <= self.projects().len() - } - - fn require_project_exists(&self, project_id: ProjectId) { - require!( - self.is_valid_project_id(project_id) && !self.projects().item_is_empty(project_id), - "Project doesn't exist!", - ) - } - - fn require_project_is_active(&self, project_id: ProjectId) { - let project = self.projects().get(project_id); - require!(project.status == Status::Active, "Project is not active!",) - } - - fn require_correct_percentages( - &self, - project_percentages: MultiValueEncoded, - ) { - let mut total_perc: u64 = 0; - for pp in project_percentages { - let (_, perc) = pp.into_tuple(); - total_perc += perc; - } - require!( - total_perc <= MAX_PERCENTAGE, - "Total percentages more than 100%" - ); - } - #[view(getFeeTokenIdentifier)] #[storage_mapper("feeTokenIdentifier")] fn fee_token_identifier(&self) -> SingleValueMapper; @@ -142,13 +90,9 @@ pub trait PotlockStorage { #[storage_mapper("projects")] fn projects(&self) -> VecMapper>; - #[view(feeAmountAcceptPots)] - #[storage_mapper("feeAmountAcceptedPots")] - fn fee_amount_accepted_pots(&self) -> SingleValueMapper; - #[view(potDonations)] #[storage_mapper("potDonations")] - fn pot_donations(&self, project_id: ProjectId) -> MapMapper; + fn pot_donations(&self, potlock_id: PotlockId) -> MapMapper; #[view(projectDonations)] #[storage_mapper("projectDonations")] diff --git a/contracts/potlock/tests/potlock_proxy.rs b/contracts/potlock/tests/potlock_proxy.rs index df8acf2a..7f85577e 100644 --- a/contracts/potlock/tests/potlock_proxy.rs +++ b/contracts/potlock/tests/potlock_proxy.rs @@ -279,15 +279,6 @@ where .original_result() } - pub fn fee_amount_accepted_pots( - self, - ) -> TxTypedCall> { - self.wrapped_tx - .payment(NotPayable) - .raw_call("feeAmountAcceptPots") - .original_result() - } - pub fn pot_donations< Arg0: ProxyArg, >( diff --git a/contracts/potlock/wasm/src/lib.rs b/contracts/potlock/wasm/src/lib.rs index 99faaf13..8bb6ebda 100644 --- a/contracts/potlock/wasm/src/lib.rs +++ b/contracts/potlock/wasm/src/lib.rs @@ -24,6 +24,7 @@ multiversx_sc_wasm_adapter::endpoints! { acceptPot => accept_pot removePot => remove_pot acceptApplication => accept_application + removeApplication => remove_application rejectDonation => reject_donation distributePotToProjects => distribute_pot_to_projects addPot => add_pot @@ -34,7 +35,6 @@ multiversx_sc_wasm_adapter::endpoints! { getFeeAmount => fee_amount getPotlocks => potlocks getProjects => projects - feeAmountAcceptPots => fee_amount_accepted_pots potDonations => pot_donations projectDonations => project_donations isAdmin => is_admin