Skip to content

Commit

Permalink
Merge pull request #12 from multiversx/subscription-sc-audit-fixes
Browse files Browse the repository at this point in the history
Fixes after audit
  • Loading branch information
psorinionut authored Dec 29, 2023
2 parents 661bb63 + 422cc78 commit 8ab1e42
Show file tree
Hide file tree
Showing 52 changed files with 3,774 additions and 2,891 deletions.
1,066 changes: 365 additions & 701 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
members = [
"farm-boosted-rewards-subscriber",
"farm-boosted-rewards-subscriber/meta",
"subscriber",
"subscriber/meta",
"subscription-fee",
"subscription-fee/meta",
]
16 changes: 16 additions & 0 deletions common/common_structs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "common_structs"
version = "0.0.0"
authors = ["MultiversX <[email protected]>"]
edition = "2021"

[lib]
path = "src/lib.rs"

[dependencies.multiversx-sc]
version = "=0.45.2"
features = ["esdt-token-payment-legacy-decode"]

[dependencies.mergeable]
git = "https://github.com/multiversx/mx-exchange-sc"
rev = "1fb9a1d"
8 changes: 8 additions & 0 deletions common/common_structs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![no_std]

multiversx_sc::imports!();
multiversx_sc::derive_imports!();

pub mod unique_payments;

pub use unique_payments::*;
133 changes: 133 additions & 0 deletions common/common_structs/src/unique_payments.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
multiversx_sc::imports!();
multiversx_sc::derive_imports!();

use mergeable::Mergeable;

pub type PaymentsVec<M> = ManagedVec<M, EsdtTokenPayment<M>>;

#[derive(TypeAbi, TopEncode, TopDecode, NestedEncode, NestedDecode, Clone, PartialEq, Debug)]
pub struct UniquePayments<M: ManagedTypeApi> {
payments: PaymentsVec<M>,
}

impl<M: ManagedTypeApi> Default for UniquePayments<M> {
#[inline]
fn default() -> Self {
Self {
payments: PaymentsVec::new(),
}
}
}

impl<M: ManagedTypeApi> UniquePayments<M> {
#[inline]
pub fn new() -> Self {
Self::default()
}

#[inline]
pub fn new_from_unique_payments(payments: PaymentsVec<M>) -> Self {
UniquePayments { payments }
}

pub fn new_from_payments(payments: PaymentsVec<M>) -> Self {
let mut merged_payments = Self::new();
for p in &payments {
merged_payments.add_payment(p);
}

merged_payments
}

pub fn add_payment(&mut self, new_payment: EsdtTokenPayment<M>) {
if new_payment.amount == 0 {
return;
}

let len = self.payments.len();
for i in 0..len {
let mut current_payment = self.payments.get(i);
if !current_payment.can_merge_with(&new_payment) {
continue;
}

current_payment.amount += new_payment.amount;
let _ = self.payments.set(i, &current_payment);

return;
}

self.payments.push(new_payment);
}
#[allow(clippy::result_unit_err)]
pub fn deduct_payment(&mut self, payment: &EsdtTokenPayment<M>) -> Result<(), ()> {
if payment.amount == 0 {
return Result::Ok(());
}

let len = self.payments.len();
for i in 0..len {
let mut current_payment = self.payments.get(i);
if !current_payment.can_merge_with(payment) {
continue;
}

if current_payment.amount < payment.amount {
return Result::Err(());
}

current_payment.amount -= &payment.amount;
let _ = self.payments.set(i, &current_payment);

return Result::Ok(());
}

Result::Err(())
}

#[inline]
pub fn into_payments(self) -> PaymentsVec<M> {
self.payments
}
}

impl<M: ManagedTypeApi> Mergeable<M> for UniquePayments<M> {
#[inline]
fn can_merge_with(&self, _other: &Self) -> bool {
true
}

fn merge_with(&mut self, mut other: Self) {
self.error_if_not_mergeable(&other);

if self.payments.is_empty() {
self.payments = other.payments;
return;
}
if other.payments.is_empty() {
return;
}

let first_len = self.payments.len();
let mut second_len = other.payments.len();
for i in 0..first_len {
let mut current_payment = self.payments.get(i);
for j in 0..second_len {
let other_payment = other.payments.get(j);
if !current_payment.can_merge_with(&other_payment) {
continue;
}

current_payment.amount += other_payment.amount;
let _ = self.payments.set(i, &current_payment);

other.payments.remove(j);
second_len -= 1;

break;
}
}

self.payments.append_vec(other.payments);
}
}
14 changes: 14 additions & 0 deletions common/common_subscriber/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "common_subscriber"
version = "0.0.0"
authors = ["MultiversX <[email protected]>"]
edition = "2021"

[lib]
path = "src/common_subscriber.rs"

[dependencies.subscription-fee]
path = "../../subscription-fee"

[dependencies.multiversx-sc]
version = "=0.45.2"
119 changes: 119 additions & 0 deletions common/common_subscriber/src/common_subscriber.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#![no_std]

use subscription_fee::{
service::ProxyTrait as _,
subtract_payments::{Epoch, ProxyTrait as _, ScResult},
};

multiversx_sc::imports!();
multiversx_sc::derive_imports!();

#[derive(TypeAbi, TopEncode, TopDecode)]
pub struct UserFees<M: ManagedTypeApi> {
pub fees: EsdtTokenPayment<M>,
pub epoch: Epoch,
}

#[multiversx_sc::module]
pub trait CommonSubscriberModule {
fn base_init(&self, fees_contract_address: ManagedAddress) {
require!(
self.blockchain().is_smart_contract(&fees_contract_address),
"Invalid address"
);

self.fees_contract_address().set(fees_contract_address);
}

/// Arguments are MultiValue3 of opt_payment_token, payment_amount and subscription_epochs
#[only_owner]
#[endpoint(registerService)]
fn register_service(
&self,
args: MultiValueEncoded<MultiValue3<Option<TokenIdentifier>, BigUint, Epoch>>,
) {
let wegld_token_id = self.wegld_token_id().get();

for arg in args.clone() {
let (token_id_opt, _, _) = arg.into_tuple();
require!(token_id_opt.is_some(), "Invalid payment token");
require!(
token_id_opt.unwrap() == wegld_token_id,
"Payment token must be WEGLD"
);
}

let mut proxy_instance = self.get_subscription_fee_sc_proxy_instance();
let _: () = proxy_instance
.register_service(args)
.execute_on_dest_context();
}

#[only_owner]
#[endpoint(unregisterService)]
fn unregister_service(&self) {
let mut proxy_instance = self.get_subscription_fee_sc_proxy_instance();
let _: () = proxy_instance
.unregister_service()
.execute_on_dest_context();
}

fn subtract_user_payment(
&self,
fees_contract_address: ManagedAddress,
service_index: usize,
user_id: AddressId,
) {
let fees_mapper = self.user_fees(service_index, user_id);
require!(fees_mapper.is_empty(), "User last fees not processed yet");

let subtract_result =
self.call_subtract_payment(fees_contract_address, service_index, user_id);
if let ScResult::Ok(fees) = subtract_result {
let current_epoch = self.blockchain().get_block_epoch();
let user_fees = UserFees {
fees,
epoch: current_epoch,
};

fees_mapper.set(user_fees);
}
}

fn call_subtract_payment(
&self,
fee_contract_address: ManagedAddress,
service_index: usize,
user_id: AddressId,
) -> ScResult<EsdtTokenPayment, ()> {
self.fee_contract_proxy_obj(fee_contract_address)
.subtract_payment(service_index, user_id)
.execute_on_dest_context()
}

fn get_subscription_fee_sc_proxy_instance(&self) -> subscription_fee::Proxy<Self::Api> {
let fees_contract_address = self.fees_contract_address().get();
self.fee_contract_proxy_obj(fees_contract_address)
}

#[proxy]
fn fee_contract_proxy_obj(
&self,
sc_address: ManagedAddress,
) -> subscription_fee::Proxy<Self::Api>;

#[view(getFeesContractAddress)]
#[storage_mapper("feesContractAddress")]
fn fees_contract_address(&self) -> SingleValueMapper<ManagedAddress>;

#[storage_mapper("wegldTokenId")]
fn wegld_token_id(&self) -> SingleValueMapper<TokenIdentifier>;

#[view(getUserFees)]
#[storage_mapper("userFees")]
fn user_fees(
&self,
service_index: usize,
user_id: AddressId,
) -> SingleValueMapper<UserFees<Self::Api>>;
}
59 changes: 43 additions & 16 deletions farm-boosted-rewards-subscriber/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,50 +1,77 @@
[package]
name = "farm-boosted-rewards-subscriber"
version = "0.0.0"
authors = [ "you",]
authors = ["you"]
edition = "2018"
publish = false

[lib]
path = "src/lib.rs"

[dependencies.multiversx-sc]
version = "=0.43.2"
version = "=0.45.2"

[dependencies.multiversx-sc-modules]
version = "=0.43.2"

[dependencies.auto-farm]
git = "https://github.com/multiversx/mx-exchange-tools-sc"
rev = "39e355f"
version = "=0.45.2"

[dependencies.subscription-fee]
path = "../subscription-fee"

[dependencies.subscriber]
path = "../subscriber"
[dependencies.common_subscriber]
path = "../common/common_subscriber"

[dependencies.common_structs]
path = "../common/common_structs"

[dependencies.energy-query]
git = "https://github.com/multiversx/mx-exchange-sc"
rev = "7f25a72"
rev = "1fb9a1d"

[dependencies.energy-factory]
git = "https://github.com/multiversx/mx-exchange-sc"
rev = "7f25a72"
rev = "1fb9a1d"

[dependencies.pair]
git = "https://github.com/multiversx/mx-exchange-sc"
rev = "7f25a72"
rev = "1fb9a1d"

[dev-dependencies.pausable]
[dependencies.farm-with-locked-rewards]
git = "https://github.com/multiversx/mx-exchange-sc"
rev = "7f25a72"
rev = "1fb9a1d"

[dev-dependencies.multiversx-sc-scenario]
version = "=0.43.2"
[dependencies.config]
git = "https://github.com/multiversx/mx-exchange-sc"
rev = "1fb9a1d"

[dev-dependencies]
num-bigint = "0.4.2"
num-traits = "0.2"
hex = "0.4"
hex-literal = "0.3.4"

[dev-dependencies.farm-boosted-yields]
git = "https://github.com/multiversx/mx-exchange-sc"
rev = "1fb9a1d"

[dev-dependencies.pausable]
git = "https://github.com/multiversx/mx-exchange-sc"
rev = "1fb9a1d"

[dev-dependencies.farm_token]
git = "https://github.com/multiversx/mx-exchange-sc"
rev = "1fb9a1d"

[dev-dependencies.sc_whitelist_module]
git = "https://github.com/multiversx/mx-exchange-sc"
rev = "1fb9a1d"

[dev-dependencies.simple-lock]
git = "https://github.com/multiversx/mx-exchange-sc"
rev = "1fb9a1d"

[dev-dependencies.locking_module]
git = "https://github.com/multiversx/mx-exchange-sc"
rev = "1fb9a1d"

[dev-dependencies.multiversx-sc-scenario]
version = "=0.45.2"
Loading

0 comments on commit 8ab1e42

Please sign in to comment.