Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements #7

Merged
merged 10 commits into from
Mar 15, 2024
61 changes: 58 additions & 3 deletions src/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ use crate::{
compensation_cache::{self, CompensationCache},
},
errors::{
ERR_ALREADY_ACTIVE, ERR_ALREADY_INACTIVE, ERR_ALREADY_IN_STORAGE,
ERR_COMPENSATION_NOT_FOUND, ERR_INVALID_PENALTY_VALUE, ERR_INVALID_TIMESTAMP,
ERR_INVALID_TOKEN_IDENTIFIER, ERR_NOT_PRIVILEGED,
ERR_INVALID_TOKEN_IDENTIFIER, ERR_NOT_IN_STORAGE, ERR_NOT_PRIVILEGED,
},
events, only_privileged,
storage::{self, PenaltyType},
Expand All @@ -19,6 +20,22 @@ multiversx_sc::derive_imports!();
pub trait AdminModule:
crate::config::ConfigModule + storage::StorageModule + events::EventsModule
{
#[endpoint(initiateBond)]
fn initiate_bond_for_address(
&self,
address: ManagedAddress,
token_identifier: TokenIdentifier,
nonce: u64,
) {
only_privileged!(self, ERR_NOT_PRIVILEGED);

let bond_id = self
.bonds_ids()
.get_id_or_insert((token_identifier.clone(), nonce));

self.address_bonds(&address).insert(bond_id);
}

#[endpoint(setBlacklist)]
fn add_to_black_list(
&self,
Expand All @@ -35,6 +52,12 @@ pub trait AdminModule:
self.add_to_blacklist_event(&compensation_id, &addresses);

for address in addresses.into_iter() {
if self
.compensation_blacklist(compensation_id)
.contains(&address)
{
sc_panic!(ERR_ALREADY_IN_STORAGE);
}
self.compensation_blacklist(compensation_id).insert(address);
}
}
Expand All @@ -55,6 +78,12 @@ pub trait AdminModule:
self.remove_from_blacklist_event(&compensation_id, &addresses);

for address in addresses.into_iter() {
if !self
.compensation_blacklist(compensation_id)
.contains(&address)
{
sc_panic!(ERR_NOT_IN_STORAGE);
}
self.compensation_blacklist(compensation_id)
.swap_remove(&address);
}
Expand Down Expand Up @@ -90,6 +119,10 @@ pub trait AdminModule:
) {
only_privileged!(self, ERR_NOT_PRIVILEGED);

if penalty != PenaltyType::Custom {
require!(custom_penalty.is_none(), ERR_INVALID_PENALTY_VALUE);
}

let bond_id = self
.bonds_ids()
.get_id_non_zero((token_identifier.clone(), nonce));
Expand Down Expand Up @@ -154,13 +187,21 @@ pub trait AdminModule:
#[endpoint(setContractStateActive)]
fn set_contract_state_active(&self) {
only_privileged!(self, ERR_NOT_PRIVILEGED);
require!(
self.contract_state().get() == State::Inactive,
ERR_ALREADY_ACTIVE
);
self.contract_state().set(State::Active);
self.contract_state_event(State::Active);
}

#[endpoint(setContractStateInactive)]
fn set_contract_state_inactive(&self) {
only_privileged!(self, ERR_NOT_PRIVILEGED);
require!(
self.contract_state().get() == State::Active,
ERR_ALREADY_INACTIVE
);
self.contract_state().set(State::Inactive);
self.contract_state_event(State::Inactive);
}
Expand All @@ -170,6 +211,9 @@ pub trait AdminModule:
only_privileged!(self, ERR_NOT_PRIVILEGED);
self.set_accepted_callers_event(&callers);
for caller in callers.into_iter() {
if self.accepted_callers().contains(&caller) {
sc_panic!(ERR_ALREADY_IN_STORAGE)
}
self.accepted_callers().insert(caller);
}
}
Expand All @@ -179,6 +223,9 @@ pub trait AdminModule:
only_privileged!(self, ERR_NOT_PRIVILEGED);
self.remove_accepted_callers_event(&callers);
for caller in callers.into_iter() {
if !self.accepted_callers().contains(&caller) {
sc_panic!(ERR_NOT_IN_STORAGE)
}
self.accepted_callers().swap_remove(&caller);
}
}
Expand All @@ -194,11 +241,16 @@ pub trait AdminModule:
self.bond_payment_token().set(token_identifier);
}

#[endpoint(setPeriodsBonds)]
fn set_lock_periods_with_bonds(&self, args: MultiValueEncoded<MultiValue2<u64, BigUint>>) {
#[endpoint(addPeriodsBonds)]
fn add_lock_periods_with_bonds(&self, args: MultiValueEncoded<MultiValue2<u64, BigUint>>) {
only_privileged!(self, ERR_NOT_PRIVILEGED);
for input in args.into_iter() {
let (lock_period, bond) = input.into_tuple();

if self.lock_periods().contains(&lock_period) {
sc_panic!(ERR_ALREADY_IN_STORAGE);
}

self.set_period_and_bond_event(&lock_period, &bond);
self.lock_periods().insert(lock_period);
self.lock_period_bond_amount(lock_period).set(bond);
Expand All @@ -209,6 +261,9 @@ pub trait AdminModule:
fn remove_lock_periods_with_bonds(&self, lock_periods: MultiValueEncoded<u64>) {
only_privileged!(self, ERR_NOT_PRIVILEGED);
for period in lock_periods.into_iter() {
if !self.lock_periods().contains(&period) {
sc_panic!(ERR_NOT_IN_STORAGE);
}
self.remove_period_and_bond_event(&period, &self.lock_period_bond_amount(period).get());
self.lock_periods().remove(&period);
self.lock_period_bond_amount(period).clear();
Expand Down
53 changes: 44 additions & 9 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{events, storage};
use crate::{errors::ERR_ALREADY_IN_STORAGE, events, storage};

multiversx_sc::imports!();
multiversx_sc::derive_imports!();
Expand Down Expand Up @@ -29,17 +29,16 @@ pub trait ConfigModule: storage::StorageModule + events::EventsModule {
#[endpoint(setAdministrator)]
fn set_administrator(&self, administrator: ManagedAddress) {
self.set_administrator_event(&administrator);

if !self.administrator().is_empty() {
require!(
administrator != self.administrator().get(),
ERR_ALREADY_IN_STORAGE
);
}
self.administrator().set(administrator);
}

#[view(getContractState)]
#[storage_mapper("contract_state")]
fn contract_state(&self) -> SingleValueMapper<State>;

#[view(getAdministrator)]
#[storage_mapper("administrator")]
fn administrator(&self) -> SingleValueMapper<ManagedAddress>;

#[inline]
fn is_contract_owner(&self, address: &ManagedAddress) -> bool {
&(self.blockchain().get_owner_address()) == address
Expand Down Expand Up @@ -81,4 +80,40 @@ pub trait ConfigModule: storage::StorageModule + events::EventsModule {
fn is_state_active(&self, state: State) -> bool {
state == State::Active
}

#[view(getContractState)]
#[storage_mapper("contract_state")]
fn contract_state(&self) -> SingleValueMapper<State>;

#[view(getAdministrator)]
#[storage_mapper("administrator")]
fn administrator(&self) -> SingleValueMapper<ManagedAddress>;

#[view(getAcceptedCallers)]
#[storage_mapper("accepted_callers")]
fn accepted_callers(&self) -> UnorderedSetMapper<ManagedAddress>;

#[view(getBondPaymentToken)]
#[storage_mapper("bond_payment_token")]
fn bond_payment_token(&self) -> SingleValueMapper<TokenIdentifier>;

#[view(getLockPeriods)]
#[storage_mapper("lock_periods")]
fn lock_periods(&self) -> SetMapper<u64>;

#[view(getLockPeriodBondAmount)]
#[storage_mapper("lock_period_bond_amount")]
fn lock_period_bond_amount(&self, lock_period: u64) -> SingleValueMapper<BigUint>;

#[view(getMinimumPenalty)]
#[storage_mapper("minimum_penalty")]
fn minimum_penalty(&self) -> SingleValueMapper<u64>;

#[view(getMaximumPenalty)]
#[storage_mapper("maximum_penalty")]
fn maximum_penalty(&self) -> SingleValueMapper<u64>;

#[view(getWithdrawPenalty)]
#[storage_mapper("withdraw_penalty")]
fn withdraw_penalty(&self) -> SingleValueMapper<u64>;
}
4 changes: 4 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ pub const ERR_INVALID_TIMELINE_TO_REFUND: &str = "Invalid timeline to refund";
pub const ERR_REFUND_NOT_FOUND: &str = "Refund not found";
pub const ERR_INVALID_TIMESTAMP: &str = "Invalid timestamp";
pub const ERR_PENALTIES_EXCEED_WITHDRAWAL_AMOUNT: &str = "Penalties exceed withdrawal amount";
pub const ERR_ALREADY_IN_STORAGE: &str = "Already in storage";
pub const ERR_NOT_IN_STORAGE: &str = "Not in storage";
pub const ERR_ALREADY_ACTIVE: &str = "Already active";
pub const ERR_ALREADY_INACTIVE: &str = "Already inactive";
2 changes: 0 additions & 2 deletions src/events.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// [TO DO] implement events for endpoints

use multiversx_sc::types::MultiValueEncoded;

use crate::{
Expand Down
47 changes: 14 additions & 33 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub trait LifeBondingContract:
original_caller: ManagedAddress,
token_identifier: TokenIdentifier,
nonce: u64,
lock_period: u64, //seconds
lock_period_seconds: u64,
) {
require_contract_ready!(self, ERR_CONTRACT_NOT_READY);
let caller = self.blockchain().get_caller();
Expand All @@ -85,36 +85,27 @@ pub trait LifeBondingContract:
ERR_INVALID_TOKEN_IDENTIFIER
);

// check token_identifier is accepted (not really needed as this endpoint will be called by the minting contract)

require!(
self.lock_periods().contains(&lock_period),
self.lock_periods().contains(&lock_period_seconds),
ERR_INVALID_LOCK_PERIOD
);
require!(
!self.lock_period_bond_amount(lock_period).is_empty(),
!self.lock_period_bond_amount(lock_period_seconds).is_empty(),
ERR_INVALID_LOCK_PERIOD
); // check not really needed
);

let bond_amount = self.lock_period_bond_amount(lock_period).get();
let bond_amount = self.lock_period_bond_amount(lock_period_seconds).get();

require!(payment.amount == bond_amount, ERR_INVALID_AMOUNT);

let current_timestamp = self.blockchain().get_block_timestamp();
let unbound_timestamp = current_timestamp + lock_period;

// let check_bond_id = self.bonds_ids().get_id((token_identifier.clone(), nonce));

// require!(
// !self.bonds_ids().contains_id(check_bond_id),
// ERR_BOND_ALREADY_CREATED
// );
let unbound_timestamp = current_timestamp + lock_period_seconds;

self.bond_address(bond_id).set(original_caller.clone());
self.bond_token_identifier(bond_id)
.set(token_identifier.clone());
self.bond_nonce(bond_id).set(nonce);
self.bond_lock_period(bond_id).set(lock_period);
self.bond_lock_period(bond_id).set(lock_period_seconds);
self.bond_timestamp(bond_id).set(current_timestamp);
self.unbound_timestamp(bond_id).set(unbound_timestamp);
self.bond_amount(bond_id).set(payment.amount.clone());
Expand Down Expand Up @@ -185,10 +176,8 @@ pub trait LifeBondingContract:
0u64,
&bond_cache.remaining_amount,
);
// clear compensations as the entire bond is withdrawn
// compensation_cache.clear();
// self.compensations_ids().remove_by_id(compensation_id);
self.compensations().swap_remove(&compensation_id); // remove from showing if it's withdrawn

self.compensations().swap_remove(&compensation_id);
}

self.withdraw_event(
Expand All @@ -198,11 +187,7 @@ pub trait LifeBondingContract:
&penalty_amount,
);

// Do not clear bond totally as creator can come and bond/renew again
// bond_cache.clear();
// self.bonds_ids().remove_by_id(bond_id);
// self.address_bonds(&caller).swap_remove(&bond_id);
self.bonds().swap_remove(&bond_id); // remove from showing if it's withdrawn
self.bonds().swap_remove(&bond_id);
}

#[endpoint(renew)]
Expand Down Expand Up @@ -281,7 +266,7 @@ pub trait LifeBondingContract:
let current_timestamp = self.blockchain().get_block_timestamp();

require!(
current_timestamp > compensation_cache.end_date + COMPENSATION_SAFE_PERIOD, // 86_400 seconds safe period for black list to be uploaded
current_timestamp > compensation_cache.end_date + COMPENSATION_SAFE_PERIOD,
ERR_INVALID_TIMELINE_TO_REFUND
);

Expand All @@ -297,7 +282,7 @@ pub trait LifeBondingContract:
let address_refund = self.address_refund(&caller, compensation_id).get();

self.send()
.direct_non_zero_esdt_payment(&caller, &address_refund.proof_of_refund); // sending back the nfts
.direct_non_zero_esdt_payment(&caller, &address_refund.proof_of_refund);

compensation_cache.proof_amount -= &address_refund.proof_of_refund.amount;
self.compensation_blacklist(compensation_id)
Expand Down Expand Up @@ -351,14 +336,10 @@ pub trait LifeBondingContract:
self.address_refund(&caller, compensation_id).clear();
}

if compensation_cache.accumulated_amount == BigUint::zero() // remove compensation if there is no more accumulated amount
if compensation_cache.accumulated_amount == BigUint::zero()
&& compensation_cache.proof_amount == BigUint::zero()
{
self.compensations().swap_remove(&compensation_id); // remove from showing if it's empty

// Do not clear compensation totally as creator can come and bond/renew again
// compensation_cache.clear();
// self.compensations_ids().remove_by_id(compensation_id);
self.compensations().swap_remove(&compensation_id);
}
}
}
Loading
Loading