diff --git a/farm-staking/farm-staking-nft/src/farm_token_roles.rs b/farm-staking/farm-staking-nft/src/common/farm_token_roles.rs similarity index 100% rename from farm-staking/farm-staking-nft/src/farm_token_roles.rs rename to farm-staking/farm-staking-nft/src/common/farm_token_roles.rs diff --git a/farm-staking/farm-staking-nft/src/common/mod.rs b/farm-staking/farm-staking-nft/src/common/mod.rs new file mode 100644 index 000000000..54b8059b5 --- /dev/null +++ b/farm-staking/farm-staking-nft/src/common/mod.rs @@ -0,0 +1,4 @@ +pub mod farm_token_roles; +pub mod result_types; +pub mod token_attributes; +pub mod token_info; diff --git a/farm-staking/farm-staking-nft/src/result_types.rs b/farm-staking/farm-staking-nft/src/common/result_types.rs similarity index 85% rename from farm-staking/farm-staking-nft/src/result_types.rs rename to farm-staking/farm-staking-nft/src/common/result_types.rs index 6cb18e7c2..8403a0b0c 100644 --- a/farm-staking/farm-staking-nft/src/result_types.rs +++ b/farm-staking/farm-staking-nft/src/common/result_types.rs @@ -1,3 +1,5 @@ +use common_structs::PaymentsVec; + multiversx_sc::imports!(); multiversx_sc::derive_imports!(); @@ -29,3 +31,8 @@ pub struct UnstakeRewardsResultType { pub unbond_farm_token: EsdtTokenPayment, pub reward_payment: EsdtTokenPayment, } + +#[derive(TypeAbi, TopEncode, TopDecode)] +pub struct UnbondResultType { + pub farming_tokens: PaymentsVec, +} diff --git a/farm-staking/farm-staking-nft/src/token_attributes.rs b/farm-staking/farm-staking-nft/src/common/token_attributes.rs similarity index 95% rename from farm-staking/farm-staking-nft/src/token_attributes.rs rename to farm-staking/farm-staking-nft/src/common/token_attributes.rs index 603ea21d1..7fa8b62ae 100644 --- a/farm-staking/farm-staking-nft/src/token_attributes.rs +++ b/farm-staking/farm-staking-nft/src/common/token_attributes.rs @@ -79,9 +79,9 @@ impl Mergeable for PartialStakingFarmNftTokenAttributes } #[derive(TypeAbi, TopEncode, TopDecode, PartialEq, Debug)] -pub struct UnbondSftAttributes /**/ { +pub struct UnbondSftAttributes { pub unlock_epoch: u64, - // pub farming_token_parts: PaymentsVec, + pub farming_token_parts: PaymentsVec, } #[derive(ManagedVecItem, Clone)] diff --git a/farm-staking/farm-staking-nft/src/token_info.rs b/farm-staking/farm-staking-nft/src/common/token_info.rs similarity index 99% rename from farm-staking/farm-staking-nft/src/token_info.rs rename to farm-staking/farm-staking-nft/src/common/token_info.rs index 1f40cd112..f3a488ca2 100644 --- a/farm-staking/farm-staking-nft/src/token_info.rs +++ b/farm-staking/farm-staking-nft/src/common/token_info.rs @@ -1,7 +1,7 @@ use common_structs::{Nonce, PaymentAttributesPair, PaymentsVec}; use mergeable::Mergeable; -use crate::token_attributes::{ +use super::token_attributes::{ PartialStakingFarmNftTokenAttributes, StakingFarmNftTokenAttributes, }; diff --git a/farm-staking/farm-staking-nft/src/custom_rewards.rs b/farm-staking/farm-staking-nft/src/custom_rewards.rs index 4749621c0..47d493879 100644 --- a/farm-staking/farm-staking-nft/src/custom_rewards.rs +++ b/farm-staking/farm-staking-nft/src/custom_rewards.rs @@ -4,7 +4,7 @@ multiversx_sc::derive_imports!(); use common_structs::{Epoch, Nonce, PaymentsVec}; use contexts::storage_cache::StorageCache; -use crate::token_attributes::{ +use crate::common::token_attributes::{ PartialStakingFarmNftTokenAttributes, StakingFarmNftTokenAttributes, }; diff --git a/farm-staking/farm-staking-nft/src/farm_actions/claim_stake_farm_rewards.rs b/farm-staking/farm-staking-nft/src/farm_actions/claim_stake_farm_rewards.rs index 6c9f38511..cca17e48c 100644 --- a/farm-staking/farm-staking-nft/src/farm_actions/claim_stake_farm_rewards.rs +++ b/farm-staking/farm-staking-nft/src/farm_actions/claim_stake_farm_rewards.rs @@ -7,9 +7,11 @@ use contexts::{ }; use crate::{ + common::result_types::ClaimRewardsResultType, + common::token_attributes::{ + PartialStakingFarmNftTokenAttributes, StakingFarmNftTokenAttributes, + }, farm_hooks::hook_type::FarmHookType, - result_types::ClaimRewardsResultType, - token_attributes::{PartialStakingFarmNftTokenAttributes, StakingFarmNftTokenAttributes}, }; pub struct InternalClaimRewardsResult<'a, C> @@ -50,7 +52,7 @@ pub trait ClaimStakeFarmRewardsModule: + banned_addresses::BannedAddressModule + crate::farm_hooks::change_hooks::ChangeHooksModule + crate::farm_hooks::call_hook::CallHookModule - + crate::token_info::TokenInfoModule + + crate::common::token_info::TokenInfoModule { #[payable("*")] #[endpoint(claimRewards)] diff --git a/farm-staking/farm-staking-nft/src/farm_actions/compound_stake_farm_rewards.rs b/farm-staking/farm-staking-nft/src/farm_actions/compound_stake_farm_rewards.rs index 2c19e98f4..1535ea84e 100644 --- a/farm-staking/farm-staking-nft/src/farm_actions/compound_stake_farm_rewards.rs +++ b/farm-staking/farm-staking-nft/src/farm_actions/compound_stake_farm_rewards.rs @@ -6,9 +6,11 @@ use contexts::{ }; use crate::{ + common::result_types::CompoundRewardsResultType, + common::token_attributes::{ + PartialStakingFarmNftTokenAttributes, StakingFarmNftTokenAttributes, + }, farm_hooks::hook_type::FarmHookType, - result_types::CompoundRewardsResultType, - token_attributes::{PartialStakingFarmNftTokenAttributes, StakingFarmNftTokenAttributes}, }; multiversx_sc::imports!(); @@ -51,7 +53,7 @@ pub trait CompoundStakeFarmRewardsModule: + banned_addresses::BannedAddressModule + crate::farm_hooks::change_hooks::ChangeHooksModule + crate::farm_hooks::call_hook::CallHookModule - + crate::token_info::TokenInfoModule + + crate::common::token_info::TokenInfoModule { #[payable("*")] #[endpoint(compoundRewards)] diff --git a/farm-staking/farm-staking-nft/src/farm_actions/stake_farm.rs b/farm-staking/farm-staking-nft/src/farm_actions/stake_farm.rs index 014118f76..f7132142f 100644 --- a/farm-staking/farm-staking-nft/src/farm_actions/stake_farm.rs +++ b/farm-staking/farm-staking-nft/src/farm_actions/stake_farm.rs @@ -5,8 +5,9 @@ use contexts::{enter_farm_context::EnterFarmContext, storage_cache::StorageCache use farm_base_impl::enter_farm::InternalEnterFarmResult; use crate::{ - farm_hooks::hook_type::FarmHookType, result_types::EnterFarmResultType, - token_attributes::PartialStakingFarmNftTokenAttributes, + common::result_types::EnterFarmResultType, + common::token_attributes::PartialStakingFarmNftTokenAttributes, + farm_hooks::hook_type::FarmHookType, }; #[multiversx_sc::module] @@ -36,7 +37,7 @@ pub trait StakeFarmModule: + banned_addresses::BannedAddressModule + crate::farm_hooks::change_hooks::ChangeHooksModule + crate::farm_hooks::call_hook::CallHookModule - + crate::token_info::TokenInfoModule + + crate::common::token_info::TokenInfoModule { #[payable("*")] #[endpoint(stakeFarm)] diff --git a/farm-staking/farm-staking-nft/src/farm_actions/unbond_farm.rs b/farm-staking/farm-staking-nft/src/farm_actions/unbond_farm.rs index 760945df0..163e3df04 100644 --- a/farm-staking/farm-staking-nft/src/farm_actions/unbond_farm.rs +++ b/farm-staking/farm-staking-nft/src/farm_actions/unbond_farm.rs @@ -2,7 +2,10 @@ multiversx_sc::imports!(); use contexts::storage_cache::StorageCache; -use crate::{farm_hooks::hook_type::FarmHookType, token_attributes::UnbondSftAttributes}; +use crate::{ + common::{result_types::UnbondResultType, token_attributes::UnbondSftAttributes}, + farm_hooks::hook_type::FarmHookType, +}; #[multiversx_sc::module] pub trait UnbondFarmModule: @@ -29,17 +32,17 @@ pub trait UnbondFarmModule: + banned_addresses::BannedAddressModule + crate::farm_hooks::change_hooks::ChangeHooksModule + crate::farm_hooks::call_hook::CallHookModule + + crate::unbond_token::UnbondTokenModule { - // TODO: Fix to actually send the required token parts #[payable("*")] #[endpoint(unbondFarm)] - fn unbond_farm(&self) -> EsdtTokenPayment { + fn unbond_farm(&self) -> UnbondResultType { let storage_cache = StorageCache::new(self); self.validate_contract_state(storage_cache.contract_state, &storage_cache.farm_token_id); - let farm_token_mapper = self.farm_token(); + let unbond_token_mapper = self.unbond_token(); let payment = self.call_value().single_esdt(); - farm_token_mapper.require_same_token(&payment.token_identifier); + unbond_token_mapper.require_same_token(&payment.token_identifier); let caller = self.blockchain().get_caller(); let payments_after_hook = self.call_hook( @@ -50,8 +53,8 @@ pub trait UnbondFarmModule: ); let payment = payments_after_hook.get(0); - let attributes: UnbondSftAttributes = - farm_token_mapper.get_token_attributes(payment.token_nonce); + let attributes: UnbondSftAttributes = + unbond_token_mapper.get_token_attributes(payment.token_nonce); let current_epoch = self.blockchain().get_block_epoch(); require!( @@ -59,20 +62,20 @@ pub trait UnbondFarmModule: "Unbond period not over" ); - farm_token_mapper.nft_burn(payment.token_nonce, &payment.amount); + unbond_token_mapper.nft_burn(payment.token_nonce, &payment.amount); - let farming_tokens = - EsdtTokenPayment::new(storage_cache.farming_token_id.clone(), 0, payment.amount); + let farming_tokens = attributes.farming_token_parts; let output_payments_after_hook = self.call_hook( FarmHookType::AfterUnbond, caller.clone(), - ManagedVec::from_single_item(farming_tokens), + farming_tokens, ManagedVec::new(), ); - let farming_tokens = output_payments_after_hook.get(0); - self.send_payment_non_zero(&caller, &farming_tokens); + self.send_multiple_tokens_if_not_zero(&caller, &output_payments_after_hook); - farming_tokens + UnbondResultType { + farming_tokens: output_payments_after_hook, + } } } diff --git a/farm-staking/farm-staking-nft/src/farm_actions/unstake_farm.rs b/farm-staking/farm-staking-nft/src/farm_actions/unstake_farm.rs index 5deba32d4..7196272e7 100644 --- a/farm-staking/farm-staking-nft/src/farm_actions/unstake_farm.rs +++ b/farm-staking/farm-staking-nft/src/farm_actions/unstake_farm.rs @@ -1,14 +1,29 @@ multiversx_sc::imports!(); -use contexts::{exit_farm_context::ExitFarmContext, storage_cache::StorageCache}; -use farm_base_impl::exit_farm::InternalExitFarmResult; +use common_structs::PaymentsVec; +use contexts::{ + exit_farm_context::ExitFarmContext, + storage_cache::{FarmContracTraitBounds, StorageCache}, +}; use crate::{ + common::result_types::UnstakeRewardsResultType, + common::token_attributes::{StakingFarmNftTokenAttributes, UnbondSftAttributes}, farm_hooks::hook_type::FarmHookType, - result_types::UnstakeRewardsResultType, - token_attributes::{StakingFarmNftTokenAttributes, UnbondSftAttributes}, }; +const NFT_AMOUNT: u32 = 1; + +pub struct InternalExitFarmResult<'a, C> +where + C: FarmContracTraitBounds, +{ + pub context: ExitFarmContext>, + pub storage_cache: StorageCache<'a, C>, + pub token_parts: PaymentsVec, + pub reward_payment: EsdtTokenPayment, +} + #[multiversx_sc::module] pub trait UnstakeFarmModule: crate::custom_rewards::CustomRewardsModule @@ -36,7 +51,8 @@ pub trait UnstakeFarmModule: + banned_addresses::BannedAddressModule + crate::farm_hooks::change_hooks::ChangeHooksModule + crate::farm_hooks::call_hook::CallHookModule - + crate::token_info::TokenInfoModule + + crate::common::token_info::TokenInfoModule + + crate::unbond_token::UnbondTokenModule { #[payable("*")] #[endpoint(unstakeFarm)] @@ -53,10 +69,7 @@ pub trait UnstakeFarmModule: let payment = payments_after_hook.get(0); let mut exit_result = self.exit_farm_base(caller.clone(), payment); - - let unbond_token_amount = exit_result.farming_token_payment.amount; - let farm_token_id = exit_result.storage_cache.farm_token_id.clone(); - let unbond_farm_token = self.create_unbond_tokens(farm_token_id, unbond_token_amount); + let unbond_farm_token = self.create_unbond_tokens(exit_result.token_parts); let mut output_payments = ManagedVec::new(); output_payments.push(unbond_farm_token); @@ -95,27 +108,25 @@ pub trait UnstakeFarmModule: fn create_unbond_tokens( &self, - farm_token_id: TokenIdentifier, - amount: BigUint, + farming_token_parts: PaymentsVec, ) -> EsdtTokenPayment { let min_unbond_epochs = self.min_unbond_epochs().get(); let current_epoch = self.blockchain().get_block_epoch(); - let nft_nonce = self.send().esdt_nft_create_compact( - &farm_token_id, - &amount, + + self.unbond_token().nft_create( + BigUint::from(NFT_AMOUNT), &UnbondSftAttributes { unlock_epoch: current_epoch + min_unbond_epochs, + farming_token_parts, }, - ); - - EsdtTokenPayment::new(farm_token_id, nft_nonce, amount) + ) } fn exit_farm_base( &self, caller: ManagedAddress, payment: EsdtTokenPayment, - ) -> InternalExitFarmResult> { + ) -> InternalExitFarmResult { let mut storage_cache = StorageCache::new(self); self.validate_contract_state(storage_cache.contract_state, &storage_cache.farm_token_id); @@ -144,12 +155,6 @@ pub trait UnstakeFarmModule: self.decrease_user_farm_position(&payment); - let farming_token_amount = token_attributes.current_farm_amount; - let farming_token_payment = EsdtTokenPayment::new( - storage_cache.farming_token_id.clone(), - 0, - farming_token_amount, - ); let reward_payment = EsdtTokenPayment::new(storage_cache.reward_token_id.clone(), 0, reward); @@ -160,11 +165,11 @@ pub trait UnstakeFarmModule: &farm_token_payment.amount, ); - storage_cache.farm_token_supply -= &farming_token_payment.amount; + storage_cache.farm_token_supply -= &token_attributes.current_farm_amount; InternalExitFarmResult { context: exit_farm_context, - farming_token_payment, + token_parts: token_attributes.farming_token_parts, reward_payment, storage_cache, } diff --git a/farm-staking/farm-staking-nft/src/lib.rs b/farm-staking/farm-staking-nft/src/lib.rs index 348ec4255..6c0870ea2 100644 --- a/farm-staking/farm-staking-nft/src/lib.rs +++ b/farm-staking/farm-staking-nft/src/lib.rs @@ -5,19 +5,17 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); +use common::result_types::MergeResultType; +use common::token_attributes::PartialStakingFarmNftTokenAttributes; use contexts::storage_cache::StorageCache; -use result_types::MergeResultType; -use token_attributes::PartialStakingFarmNftTokenAttributes; use crate::custom_rewards::MAX_MIN_UNBOND_EPOCHS; +pub mod common; pub mod custom_rewards; pub mod farm_actions; pub mod farm_hooks; -pub mod farm_token_roles; -pub mod result_types; -pub mod token_attributes; -pub mod token_info; +pub mod unbond_token; #[multiversx_sc::contract] pub trait FarmStaking: @@ -37,7 +35,7 @@ pub trait FarmStaking: + farm_base_impl::compound_rewards::BaseCompoundRewardsModule + farm_base_impl::exit_farm::BaseExitFarmModule + utils::UtilsModule - + farm_token_roles::FarmTokenRolesModule + + common::farm_token_roles::FarmTokenRolesModule + farm_actions::stake_farm::StakeFarmModule + farm_actions::claim_stake_farm_rewards::ClaimStakeFarmRewardsModule + farm_actions::compound_stake_farm_rewards::CompoundStakeFarmRewardsModule @@ -56,7 +54,8 @@ pub trait FarmStaking: + banned_addresses::BannedAddressModule + farm_hooks::change_hooks::ChangeHooksModule + farm_hooks::call_hook::CallHookModule - + token_info::TokenInfoModule + + common::token_info::TokenInfoModule + + unbond_token::UnbondTokenModule { #[init] fn init( diff --git a/farm-staking/farm-staking-nft/src/unbond_token.rs b/farm-staking/farm-staking-nft/src/unbond_token.rs new file mode 100644 index 000000000..438bafdab --- /dev/null +++ b/farm-staking/farm-staking-nft/src/unbond_token.rs @@ -0,0 +1,28 @@ +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait UnbondTokenModule: permissions_module::PermissionsModule { + #[payable("EGLD")] + #[endpoint(registerUnbondToken)] + fn register_unbond_token( + &self, + token_display_name: ManagedBuffer, + token_ticker: ManagedBuffer, + ) { + self.require_caller_has_owner_or_admin_permissions(); + + let payment_amount = self.call_value().egld_value().clone_value(); + self.unbond_token().issue_and_set_all_roles( + EsdtTokenType::NonFungible, + payment_amount, + token_display_name, + token_ticker, + 0, + None, + ); + } + + #[view(getUnbondTokenId)] + #[storage_mapper("unbond_token_id")] + fn unbond_token(&self) -> NonFungibleTokenMapper; +} diff --git a/farm-staking/farm-staking-nft/wasm/src/lib.rs b/farm-staking/farm-staking-nft/wasm/src/lib.rs index 480b91ef6..475894402 100644 --- a/farm-staking/farm-staking-nft/wasm/src/lib.rs +++ b/farm-staking/farm-staking-nft/wasm/src/lib.rs @@ -5,9 +5,9 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 69 +// Endpoints: 71 // Async Callback: 1 -// Total number of exported functions: 71 +// Total number of exported functions: 73 #![no_std] #![allow(internal_features)] @@ -89,6 +89,8 @@ multiversx_sc_wasm_adapter::endpoints! { removeBannedAddress => remove_banned_address addHook => add_hook removeHook => remove_hook + registerUnbondToken => register_unbond_token + getUnbondTokenId => unbond_token ) }