Skip to content

Commit

Permalink
Merge pull request #760 from multiversx/farm-position-functionality
Browse files Browse the repository at this point in the history
farm position functionality
  • Loading branch information
psorinionut authored Oct 2, 2023
2 parents 711aede + 3cf4458 commit 3491557
Show file tree
Hide file tree
Showing 91 changed files with 1,957 additions and 1,581 deletions.
85 changes: 85 additions & 0 deletions common/modules/farm/config/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,89 @@ use common_structs::Nonce;
use pausable::State;

pub const DEFAULT_NFT_DEPOSIT_MAX_LEN: usize = 10;
pub const DEFAULT_FARM_POSITION_MIGRATION_NONCE: u64 = 1;

#[derive(
ManagedVecItem,
TopEncode,
TopDecode,
NestedEncode,
NestedDecode,
TypeAbi,
Clone,
PartialEq,
Debug,
)]
pub struct UserTotalFarmPosition<M: ManagedTypeApi> {
pub total_farm_position: BigUint<M>,
pub allow_external_claim_boosted_rewards: bool,
}

impl<M: ManagedTypeApi> Default for UserTotalFarmPosition<M> {
fn default() -> Self {
Self {
total_farm_position: BigUint::zero(),
allow_external_claim_boosted_rewards: false,
}
}
}

#[multiversx_sc::module]
pub trait ConfigModule: pausable::PausableModule + permissions_module::PermissionsModule {
#[endpoint(allowExternalClaimBoostedRewards)]
fn allow_external_claim_boosted_rewards(&self, allow_external_claim: bool) {
let caller = self.blockchain().get_caller();
let mut user_total_farm_position = self.get_user_total_farm_position(&caller);
user_total_farm_position.allow_external_claim_boosted_rewards = allow_external_claim;
self.user_total_farm_position(&caller)
.set(user_total_farm_position);
}

#[inline]
fn is_active(&self) -> bool {
let state = self.state().get();
state == State::Active
}

fn get_user_total_farm_position(
&self,
user: &ManagedAddress,
) -> UserTotalFarmPosition<Self::Api> {
let user_total_farm_position_mapper = self.user_total_farm_position(user);
if user_total_farm_position_mapper.is_empty() {
UserTotalFarmPosition::default()
} else {
user_total_farm_position_mapper.get()
}
}

fn is_old_farm_position(&self, token_nonce: Nonce) -> bool {
let farm_position_migration_nonce = self.farm_position_migration_nonce().get();
token_nonce > 0 && token_nonce < farm_position_migration_nonce
}

fn try_set_farm_position_migration_nonce(
&self,
farm_token_mapper: NonFungibleTokenMapper<Self::Api>,
) {
if !self.farm_position_migration_nonce().is_empty() {
return;
}

let migration_farm_token_nonce = if farm_token_mapper.get_token_state().is_set() {
let token_identifier = farm_token_mapper.get_token_id_ref();
let current_nonce = self
.blockchain()
.get_current_esdt_nft_nonce(&self.blockchain().get_sc_address(), token_identifier);
current_nonce + DEFAULT_FARM_POSITION_MIGRATION_NONCE
} else {
DEFAULT_FARM_POSITION_MIGRATION_NONCE
};

self.farm_position_migration_nonce()
.set(migration_farm_token_nonce);
}

#[view(getFarmingTokenId)]
#[storage_mapper("farming_token_id")]
fn farming_token_id(&self) -> SingleValueMapper<TokenIdentifier>;
Expand All @@ -38,4 +112,15 @@ pub trait ConfigModule: pausable::PausableModule + permissions_module::Permissio
#[view(getDivisionSafetyConstant)]
#[storage_mapper("division_safety_constant")]
fn division_safety_constant(&self) -> SingleValueMapper<BigUint>;

#[view(getUserTotalFarmPosition)]
#[storage_mapper("userTotalFarmPosition")]
fn user_total_farm_position(
&self,
user: &ManagedAddress,
) -> SingleValueMapper<UserTotalFarmPosition<Self::Api>>;

#[view(getFarmPositionMigrationNonce)]
#[storage_mapper("farm_position_migration_nonce")]
fn farm_position_migration_nonce(&self) -> SingleValueMapper<Nonce>;
}
58 changes: 58 additions & 0 deletions common/modules/farm/farm_base_impl/src/base_traits_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use contexts::storage_cache::StorageCache;
use core::marker::PhantomData;
use fixed_supply_token::FixedSupplyToken;
use mergeable::Mergeable;
use multiversx_sc_modules::transfer_role_proxy::PaymentsVec;
use rewards::RewardsModule;

pub trait AllBaseFarmImplTraits =
Expand Down Expand Up @@ -187,6 +188,63 @@ pub trait FarmContract {
_storage_cache: &StorageCache<Self::FarmSc>,
) {
}

fn check_and_update_user_farm_position(
sc: &Self::FarmSc,
user: &ManagedAddress<<Self::FarmSc as ContractBase>::Api>,
farm_positions: &PaymentsVec<<Self::FarmSc as ContractBase>::Api>,
) {
let farm_token_mapper = sc.farm_token();
for farm_position in farm_positions {
farm_token_mapper.require_same_token(&farm_position.token_identifier);

if sc.is_old_farm_position(farm_position.token_nonce) {
continue;
}

let token_attributes: FarmTokenAttributes<<Self::FarmSc as ContractBase>::Api> =
farm_token_mapper.get_token_attributes(farm_position.token_nonce);

if &token_attributes.original_owner != user {
Self::decrease_user_farm_position(sc, &farm_position);
Self::increase_user_farm_position(sc, user, &farm_position.amount);
}
}
}

#[inline]
fn increase_user_farm_position(
sc: &Self::FarmSc,
user: &ManagedAddress<<Self::FarmSc as ContractBase>::Api>,
increase_farm_position_amount: &BigUint<<Self::FarmSc as ContractBase>::Api>,
) {
let mut user_total_farm_position = sc.get_user_total_farm_position(user);
user_total_farm_position.total_farm_position += increase_farm_position_amount;
sc.user_total_farm_position(user)
.set(user_total_farm_position);
}

fn decrease_user_farm_position(
sc: &Self::FarmSc,
farm_position: &EsdtTokenPayment<<Self::FarmSc as ContractBase>::Api>,
) {
if sc.is_old_farm_position(farm_position.token_nonce) {
return;
}

let farm_token_mapper = sc.farm_token();
let token_attributes: FarmTokenAttributes<<Self::FarmSc as ContractBase>::Api> =
farm_token_mapper.get_token_attributes(farm_position.token_nonce);

sc.user_total_farm_position(&token_attributes.original_owner)
.update(|user_total_farm_position| {
if user_total_farm_position.total_farm_position > farm_position.amount {
user_total_farm_position.total_farm_position -= &farm_position.amount;
} else {
user_total_farm_position.total_farm_position = BigUint::zero();
}
});
}
}

pub struct DefaultFarmWrapper<T>
Expand Down
4 changes: 3 additions & 1 deletion common/modules/farm/farm_base_impl/src/claim_rewards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub trait BaseClaimRewardsModule:
self.validate_contract_state(storage_cache.contract_state, &storage_cache.farm_token_id);

let claim_rewards_context = ClaimRewardsContext::<Self::Api, FC::AttributesType>::new(
payments,
payments.clone(),
&storage_cache.farm_token_id,
self.blockchain(),
);
Expand All @@ -81,6 +81,8 @@ pub trait BaseClaimRewardsModule:
);
storage_cache.reward_reserve -= &reward;

FC::check_and_update_user_farm_position(self, &caller, &payments);

let farm_token_mapper = self.farm_token();
let base_attributes = FC::create_claim_rewards_initial_attributes(
self,
Expand Down
8 changes: 6 additions & 2 deletions common/modules/farm/farm_base_impl/src/compound_rewards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub trait BaseCompoundRewardsModule:
);

let compound_rewards_context = CompoundRewardsContext::<Self::Api, FC::AttributesType>::new(
payments,
payments.clone(),
&storage_cache.farm_token_id,
self.blockchain(),
);
Expand All @@ -70,10 +70,12 @@ pub trait BaseCompoundRewardsModule:
storage_cache.reward_reserve -= &reward;
storage_cache.farm_token_supply += &reward;

FC::check_and_update_user_farm_position(self, &caller, &payments);

let farm_token_mapper = self.farm_token();
let base_attributes = FC::create_compound_rewards_initial_attributes(
self,
caller,
caller.clone(),
token_attributes,
storage_cache.reward_per_share.clone(),
&reward,
Expand All @@ -84,6 +86,8 @@ pub trait BaseCompoundRewardsModule:
&farm_token_mapper,
);

FC::increase_user_farm_position(self, &caller, &reward);

let first_farm_token = &compound_rewards_context.first_farm_token.payment;
farm_token_mapper.nft_burn(first_farm_token.token_nonce, &first_farm_token.amount);
self.send()
Expand Down
12 changes: 12 additions & 0 deletions common/modules/farm/farm_base_impl/src/enter_farm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ pub trait BaseEnterFarmModule:
&storage_cache.farm_token_id,
);

// The order is important - first check and update, then increase position
FC::check_and_update_user_farm_position(
self,
&caller,
&enter_farm_context.additional_farm_tokens,
);
FC::increase_user_farm_position(
self,
&caller,
&enter_farm_context.farming_token_payment.amount,
);

FC::generate_aggregated_rewards(self, &mut storage_cache);

storage_cache.farm_token_supply += &enter_farm_context.farming_token_payment.amount;
Expand Down
4 changes: 3 additions & 1 deletion common/modules/farm/farm_base_impl/src/exit_farm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub trait BaseExitFarmModule:
self.validate_contract_state(storage_cache.contract_state, &storage_cache.farm_token_id);

let exit_farm_context = ExitFarmContext::<Self::Api, FC::AttributesType>::new(
payment,
payment.clone(),
&storage_cache.farm_token_id,
self.blockchain(),
);
Expand All @@ -62,6 +62,8 @@ pub trait BaseExitFarmModule:
);
storage_cache.reward_reserve -= &reward;

FC::decrease_user_farm_position(self, &payment);

let farming_token_amount = token_attributes.get_total_supply();
let farming_token_payment = EsdtTokenPayment::new(
storage_cache.farming_token_id.clone(),
Expand Down
3 changes: 0 additions & 3 deletions dex/farm-with-locked-rewards/elrond.json

This file was deleted.

Loading

0 comments on commit 3491557

Please sign in to comment.