Skip to content

Commit

Permalink
Merge pull request #61 from multiversx/audit-fixes
Browse files Browse the repository at this point in the history
Audit fixes
  • Loading branch information
dorin-iancu authored Mar 20, 2024
2 parents 027030c + 34489d5 commit eafb249
Show file tree
Hide file tree
Showing 15 changed files with 212 additions and 94 deletions.
30 changes: 23 additions & 7 deletions growth-program/output/growth-program.abi.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"contractCrate": {
"name": "growth-program",
"version": "0.0.0",
"gitVersion": "v1.0.2-158-g6a49882"
"gitVersion": "v1.0.2-162-g6750cb9"
},
"framework": {
"name": "multiversx-sc",
Expand All @@ -21,7 +21,10 @@
"constructor": {
"docs": [
"Arguments:",
"min_reward_dollars_per_energy: Scaled to PRECISION const.",
"min_reward_dollars_per_energy is a value scaled to PRECISION*PRECISION.",
"For example, if the desired RDPE is that 10^18 units of energy give 10^{-15} dollars of rewards,",
"then we should provide the argument 10^{-15}*10^{-18}*PRECISION*PRECISION = 10^3.",
"",
"alpha: Percentage, scaled to MAX_PERCENTAGE const.",
"beta: Percentage, scaled to MAX_PERCENTAGE const."
],
Expand Down Expand Up @@ -188,10 +191,6 @@
"name": "end_week",
"type": "u32"
},
{
"name": "initial_rewards_dollar_per_energy",
"type": "BigUint"
},
{
"name": "signer",
"type": "Address"
Expand Down Expand Up @@ -261,6 +260,11 @@
"outputs": []
},
{
"docs": [
"min_reward_dollars_per_energy is a value scaled to PRECISION*PRECISION.",
"For example, if the desired RDPE is that 10^18 units of energy give 10^{-15} dollars of rewards,",
"then we should provide the argument 10^{-15}*10^{-18}*PRECISION*PRECISION = 10^3."
],
"name": "setMinRewardDollarsPerEnergy",
"onlyOwner": true,
"mutability": "mutable",
Expand All @@ -272,6 +276,18 @@
],
"outputs": []
},
{
"name": "setInitialRdpeFromApr",
"onlyOwner": true,
"mutability": "mutable",
"inputs": [
{
"name": "apr",
"type": "BigUint"
}
],
"outputs": []
},
{
"name": "setNextWeekRewardDollarsPerEnergy",
"onlyOwner": true,
Expand All @@ -282,7 +298,7 @@
"type": "u32"
},
{
"name": "new_min",
"name": "rew_dollars_per_energy",
"type": "BigUint"
}
],
Expand Down
32 changes: 24 additions & 8 deletions growth-program/output/growth-program.mxsc.json

Large diffs are not rendered by default.

Binary file modified growth-program/output/growth-program.wasm
Binary file not shown.
6 changes: 5 additions & 1 deletion growth-program/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub const MAX_PERCENTAGE: u32 = 100_000;
pub const HOUR_IN_SECONDS: Timestamp = 60 * 60;
pub const DAY_IN_SECONDS: Timestamp = 24 * 60 * 60;
pub const WEEK_IN_SECONDS: Timestamp = 7 * DAY_IN_SECONDS;
pub const WEEKS_PER_YEAR: u32 = 52;
pub const PRECISION: u64 = 1_000_000_000_000_000_000;

pub static GROWTH_SIGNATURE_PREFIX: &[u8] = b"xExchangeGrowthV1TaskCompleted";
Expand All @@ -42,7 +43,10 @@ pub trait GrowthProgram:
+ multiversx_sc_modules::pause::PauseModule
{
/// Arguments:
/// min_reward_dollars_per_energy: Scaled to PRECISION const.
/// min_reward_dollars_per_energy is a value scaled to PRECISION*PRECISION.
/// For example, if the desired RDPE is that 10^18 units of energy give 10^{-15} dollars of rewards,
/// then we should provide the argument 10^{-15}*10^{-18}*PRECISION*PRECISION = 10^3.
///
/// alpha: Percentage, scaled to MAX_PERCENTAGE const.
/// beta: Percentage, scaled to MAX_PERCENTAGE const.
#[init]
Expand Down
2 changes: 1 addition & 1 deletion growth-program/src/price_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub enum PairQueryResponse<M: ManagedTypeApi> {

#[multiversx_sc::module]
pub trait PriceQueryModule {
fn get_dollar_value(
fn get_usdc_value(
&self,
token_id: TokenIdentifier,
amount: BigUint,
Expand Down
5 changes: 4 additions & 1 deletion growth-program/src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub trait ProjectsModule {
#[only_owner]
#[endpoint(setProjectOwner)]
fn set_project_owner(&self, project_id: ProjectId, new_owner: ManagedAddress) {
self.require_valid_project_id(project_id);
self.project_owner(project_id).set(new_owner);
}

Expand All @@ -33,8 +34,10 @@ pub trait ProjectsModule {
}

fn pause_common(&self, project_id: ProjectId, pause_status: bool) {
self.require_valid_project_id(project_id);

let caller = self.blockchain().get_caller();
self.require_is_project_owner(&caller, project_id);
self.require_sc_owner_or_project_owner(&caller, project_id);

self.project_active(project_id).set(pause_status);
}
Expand Down
20 changes: 14 additions & 6 deletions growth-program/src/rewards/claim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ pub trait ClaimRewardsModule:
let current_week = self.get_current_week();
let info_mapper = self.rewards_info(project_id);
let mut rewards_info = info_mapper.get();
require!(
current_week >= rewards_info.start_week,
"Project not started yet"
);
require!(
current_week < rewards_info.end_week,
"May not claim rewards for this project anymore"
Expand Down Expand Up @@ -69,7 +73,11 @@ pub trait ClaimRewardsModule:
let total_rewards = self.rewards_total_amount(project_id, current_week).get();
let user_original_energy = self.get_energy_amount(&caller);

let rew_advertised = total_rewards * &user_original_energy / total_energy;
let rew_advertised = if total_energy != 0 {
total_rewards * &user_original_energy / total_energy
} else {
BigUint::zero()
};
let opt_rewards = match claim_type {
ClaimType::Exemption => {
let claim_exemption_args = ClaimExemptionArgs {
Expand Down Expand Up @@ -103,8 +111,6 @@ pub trait ClaimRewardsModule:
}
};

info_mapper.set(rewards_info);

let total_rewards = match &opt_rewards {
OptionalValue::Some(payment) => payment.amount.clone(),
OptionalValue::None => BigUint::zero(),
Expand Down Expand Up @@ -148,14 +154,15 @@ pub trait ClaimRewardsModule:
}

fn check_signature(&self, args: CheckSignatureArgs<Self::Api>) {
self.require_project_active(args.project_id);

if self
.exempted_participants(args.project_id, args.current_week)
.contains(&args.user_id)
{
return;
}

self.require_project_active(args.project_id);
require!(
args.opt_note_and_signature.is_some(),
"Must provide note and signature"
Expand Down Expand Up @@ -200,7 +207,7 @@ pub trait ClaimRewardsModule:

let rew_available = beta * args.rew_advertised / MAX_PERCENTAGE;
let rew_available_dollar_value =
self.get_dollar_value(args.reward_token_id, rew_available, HOUR_IN_SECONDS);
self.get_usdc_value(args.reward_token_id, rew_available, HOUR_IN_SECONDS);
self.registered_rewards_dollars(args.project_id, args.current_week)
.update(|reg_rew_dollars| *reg_rew_dollars += rew_available_dollar_value);

Expand All @@ -212,6 +219,7 @@ pub trait ClaimRewardsModule:
fn claim_rewards_normal(&self, args: ClaimRewardsArgs<Self::Api>) -> EsdtTokenPayment {
let rem_rewards_mapper = self.rewards_remaining_amount(args.project_id, args.current_week);
let remaining_rewards = rem_rewards_mapper.get();
require!(remaining_rewards > 0, "Not enough rewards");

let rew_available = core::cmp::min(args.rew_advertised, remaining_rewards);
let user_rewards =
Expand All @@ -229,7 +237,7 @@ pub trait ClaimRewardsModule:
.update(|int_energy| *int_energy += &user_adjusted_energy);

let rew_available_dollar_value =
self.get_dollar_value(args.reward_token_id.clone(), rew_available, HOUR_IN_SECONDS);
self.get_usdc_value(args.reward_token_id.clone(), rew_available, HOUR_IN_SECONDS);
self.registered_rewards_dollars(args.project_id, args.current_week)
.update(|reg_rew_dollars| *reg_rew_dollars += rew_available_dollar_value);

Expand Down
28 changes: 23 additions & 5 deletions growth-program/src/rewards/common_rewards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ pub struct RewardsInfo<M: ManagedTypeApi> {
pub end_week: Week,
}

impl<M: ManagedTypeApi> RewardsInfo<M> {
pub fn new(reward_token_id: TokenIdentifier<M>, start_week: Week, end_week: Week) -> Self {
RewardsInfo {
reward_token_id,
undistributed_rewards: BigUint::zero(),
start_week,
last_update_week: start_week,
end_week,
}
}
}

#[multiversx_sc::module]
pub trait CommonRewardsModule: super::week_timekeeping::WeekTimekeepingModule {
#[endpoint(updateRewards)]
Expand All @@ -22,9 +34,8 @@ pub trait CommonRewardsModule: super::week_timekeeping::WeekTimekeepingModule {
project_id: ProjectId,
opt_max_nr_weeks: OptionalValue<Week>,
) {
self.rewards_info(project_id).update(|rewards_info| {
self.update_rewards(project_id, opt_max_nr_weeks, rewards_info);
});
let mut rewards_info = self.rewards_info(project_id).get();
self.update_rewards(project_id, opt_max_nr_weeks, &mut rewards_info);
}

fn update_rewards(
Expand All @@ -35,14 +46,17 @@ pub trait CommonRewardsModule: super::week_timekeeping::WeekTimekeepingModule {
) {
let current_week = self.get_current_week();
if rewards_info.start_week > current_week {
self.rewards_info(project_id).set(rewards_info);
return;
}

if rewards_info.last_update_week >= current_week {
self.rewards_info(project_id).set(rewards_info);
return;
}

if rewards_info.last_update_week == rewards_info.end_week {
self.rewards_info(project_id).set(rewards_info);
return;
}

Expand All @@ -61,14 +75,18 @@ pub trait CommonRewardsModule: super::week_timekeeping::WeekTimekeepingModule {
total_undistributed_rewards += undistributed_rewards;
}

if last_week < rewards_info.end_week - 1 {
if last_week < rewards_info.end_week {
self.rewards_remaining_amount(project_id, last_week)
.update(|rem_rew| *rem_rew += total_undistributed_rewards);
.update(|rem_rew| *rem_rew += &total_undistributed_rewards);
self.rewards_total_amount(project_id, last_week)
.update(|rew_total| *rew_total += total_undistributed_rewards);
} else {
rewards_info.undistributed_rewards += total_undistributed_rewards;
}

rewards_info.last_update_week = last_week;

self.rewards_info(project_id).set(rewards_info);
}

#[storage_mapper("minRewardsPeriod")]
Expand Down
44 changes: 23 additions & 21 deletions growth-program/src/rewards/deposit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use super::week_timekeeping::Week;
use crate::{
project::{ProjectId, PROJECT_UNPAUSED},
rewards::common_rewards::RewardsInfo,
WEEK_IN_SECONDS,
DAY_IN_SECONDS,
};

multiversx_sc::imports!();
Expand All @@ -19,6 +19,7 @@ pub trait DepositRewardsModule:
+ super::week_timekeeping::WeekTimekeepingModule
+ crate::validation::ValidationModule
+ multiversx_sc_modules::pause::PauseModule
+ energy_query::EnergyQueryModule
{
#[only_owner]
#[endpoint(setMinRewardsPeriod)]
Expand All @@ -39,7 +40,6 @@ pub trait DepositRewardsModule:
project_id: ProjectId,
start_week: Week,
end_week: Week,
initial_rewards_dollar_per_energy: BigUint,
signer: ManagedAddress,
) {
require!(
Expand All @@ -53,8 +53,14 @@ pub trait DepositRewardsModule:

self.deposit_rewards_common(project_id, start_week, end_week);

let first_week_rdpe = self.first_week_reward_dollars_per_energy().get();
require!(
first_week_rdpe > 0,
"First week rewards dollar per energy not set"
);

self.rewards_dollars_per_energy(project_id, start_week)
.set(initial_rewards_dollar_per_energy);
.set(first_week_rdpe);
self.signer(project_id).set(signer);
self.project_active(project_id).set(PROJECT_UNPAUSED);
}
Expand Down Expand Up @@ -103,37 +109,35 @@ pub trait DepositRewardsModule:

let week_diff = end_week - start_week;
let rewards_per_week = &payment.amount / week_diff as u32;
let dollar_value = self.get_dollar_value(
let dollar_value = self.get_usdc_value(
payment.token_identifier.clone(),
rewards_per_week.clone(),
WEEK_IN_SECONDS,
DAY_IN_SECONDS,
);
let min_weekly_rewards_value = self.min_weekly_rewards_value().get();
require!(dollar_value >= min_weekly_rewards_value, "Too few rewards");

let info_mapper = self.rewards_info(project_id);
let mut rewards_info = if info_mapper.is_empty() {
RewardsInfo {
reward_token_id: payment.token_identifier.clone(),
undistributed_rewards: BigUint::zero(),
start_week,
last_update_week: start_week,
end_week,
}
} else {
let mut rewards_info = if !info_mapper.is_empty() {
let mut rewards_info = info_mapper.get();
require!(
payment.token_identifier == rewards_info.reward_token_id,
"Invalid payment"
);

rewards_info.last_update_week =
core::cmp::min(rewards_info.last_update_week, start_week);
rewards_info.end_week = core::cmp::max(rewards_info.end_week, end_week);

if current_week < start_week && start_week < rewards_info.start_week {
rewards_info.start_week = start_week;
}

rewards_info
} else {
RewardsInfo::new(payment.token_identifier.clone(), start_week, end_week)
};

require!(
payment.token_identifier == rewards_info.reward_token_id,
"Invalid payment"
);

self.update_rewards(project_id, OptionalValue::None, &mut rewards_info);

for week in start_week..end_week {
Expand All @@ -147,7 +151,5 @@ pub trait DepositRewardsModule:
let surplus_payment = EsdtTokenPayment::new(payment.token_identifier, 0, surplus_amount);
self.send()
.direct_non_zero_esdt_payment(&caller, &surplus_payment);

info_mapper.set(rewards_info);
}
}
Loading

0 comments on commit eafb249

Please sign in to comment.