diff --git a/dex/farm/tests/farm_setup/single_user_farm_setup.rs b/dex/farm/tests/farm_setup/single_user_farm_setup.rs index 1e23f999b..4fb48c955 100644 --- a/dex/farm/tests/farm_setup/single_user_farm_setup.rs +++ b/dex/farm/tests/farm_setup/single_user_farm_setup.rs @@ -2,7 +2,7 @@ #![allow(deprecated)] use common_structs::FarmTokenAttributes; -use multiversx_sc::codec::multi_types::OptionalValue; +use multiversx_sc::codec::multi_types::{MultiValue3, OptionalValue}; use multiversx_sc::storage::mappers::StorageTokenWrapper; use multiversx_sc::types::{Address, EsdtLocalRole, ManagedAddress, MultiValueEncoded}; use multiversx_sc_scenario::whitebox_legacy::{TxContextStack, TxTokenTransfer}; @@ -17,9 +17,12 @@ use farm::exit_penalty::ExitPenaltyModule; use farm::*; use farm_boosted_yields::boosted_yields_factors::BoostedYieldsFactorsModule; use farm_token::FarmTokenModule; +use pair::pair_actions::add_liq::AddLiquidityModule as _; +use pair::{config::ConfigModule as OtherConfigModule, Pair}; use pausable::{PausableModule, State}; pub const FARM_WASM_PATH: &str = "farm/output/farm.wasm"; +pub const PAIR_WASM_PATH: &str = "pair/output/pair.wasm"; pub const WEGLD_TOKEN_ID: &[u8] = b"WEGLD-abcdef"; pub const MEX_TOKEN_ID: &[u8] = b"MEX-abcdef"; // reward token ID @@ -36,25 +39,74 @@ pub const USER_REWARDS_ENERGY_CONST: u64 = 3; pub const USER_REWARDS_FARM_CONST: u64 = 2; pub const MIN_ENERGY_AMOUNT_FOR_BOOSTED_YIELDS: u64 = 1; pub const MIN_FARM_AMOUNT_FOR_BOOSTED_YIELDS: u64 = 1; +pub const LOCKED_TOKEN_ID: &[u8] = b"XMEX-123456"; +pub const LOCKED_LP_TOKEN_ID: &[u8] = b"LKLP-123456"; +pub const FARM_PROXY_TOKEN_ID: &[u8] = b"PROXY-123456"; -pub struct SingleUserFarmSetup +pub struct SingleUserFarmSetup where FarmObjBuilder: 'static + Copy + Fn() -> farm::ContractObj, + PairObjBuilder: 'static + Copy + Fn() -> pair::ContractObj, { pub blockchain_wrapper: BlockchainStateWrapper, pub owner_address: Address, pub user_address: Address, pub farm_wrapper: ContractObjWrapper, FarmObjBuilder>, + pub pair_wrapper: ContractObjWrapper, PairObjBuilder>, } -impl SingleUserFarmSetup +impl SingleUserFarmSetup where FarmObjBuilder: 'static + Copy + Fn() -> farm::ContractObj, + PairObjBuilder: 'static + Copy + Fn() -> pair::ContractObj, { - pub fn new(farm_builder: FarmObjBuilder) -> Self { + pub fn new(farm_builder: FarmObjBuilder, pair_builder: PairObjBuilder) -> Self { let rust_zero = rust_biguint!(0u64); let mut blockchain_wrapper = BlockchainStateWrapper::new(); let owner_addr = blockchain_wrapper.create_user_account(&rust_zero); + + let pair_wrapper = blockchain_wrapper.create_sc_account( + &rust_zero, + Some(&owner_addr), + pair_builder, + PAIR_WASM_PATH, + ); + + // init pair contract + blockchain_wrapper + .execute_tx(&owner_addr, &pair_wrapper, &rust_zero, |sc| { + let first_token_id = managed_token_id!(WEGLD_TOKEN_ID); + let second_token_id = managed_token_id!(MEX_TOKEN_ID); + let router_address = managed_address!(&owner_addr); + let router_owner_address = managed_address!(&owner_addr); + let total_fee_percent = 300u64; + let special_fee_percent = 50u64; + + sc.init( + first_token_id, + second_token_id, + router_address, + router_owner_address, + total_fee_percent, + special_fee_percent, + ManagedAddress::::zero(), + MultiValueEncoded::>::new(), + ); + + let lp_token_id = managed_token_id!(LP_TOKEN_ID); + sc.lp_token_identifier().set(&lp_token_id); + + sc.state().set(State::Active); + }) + .assert_ok(); + + let lp_token_roles = [EsdtLocalRole::Mint, EsdtLocalRole::Burn]; + blockchain_wrapper.set_esdt_local_roles( + pair_wrapper.address_ref(), + LP_TOKEN_ID, + &lp_token_roles[..], + ); + let farm_wrapper = blockchain_wrapper.create_sc_account( &rust_zero, Some(&owner_addr), @@ -142,9 +194,52 @@ where owner_address: owner_addr, user_address: user_addr, farm_wrapper, + pair_wrapper, } } + #[allow(clippy::too_many_arguments)] + pub fn add_liquidity( + &mut self, + first_token_amount: u64, + first_token_min: u64, + second_token_amount: u64, + second_token_min: u64, + ) { + let payments = vec![ + TxTokenTransfer { + token_identifier: WEGLD_TOKEN_ID.to_vec(), + nonce: 0, + value: rust_biguint!(first_token_amount), + }, + TxTokenTransfer { + token_identifier: LOCKED_TOKEN_ID.to_vec(), + nonce: 0, + value: rust_biguint!(second_token_amount), + }, + ]; + + self.blockchain_wrapper + .execute_esdt_multi_transfer(&self.user_address, &self.pair_wrapper, &payments, |sc| { + let MultiValue3 { 0: payments } = sc.add_liquidity( + managed_biguint!(first_token_min), + managed_biguint!(second_token_min), + ); + + assert_eq!(payments.0.token_identifier, managed_token_id!(LP_TOKEN_ID)); + + assert_eq!( + payments.1.token_identifier, + managed_token_id!(WEGLD_TOKEN_ID) + ); + assert_eq!( + payments.2.token_identifier, + managed_token_id!(LOCKED_TOKEN_ID) + ); + }) + .assert_ok(); + } + pub fn enter_farm( &mut self, farm_in_amount: u64, diff --git a/dex/farm/tests/farm_single_user_test.rs b/dex/farm/tests/farm_single_user_test.rs index c3df21b83..6ff0a3d3a 100644 --- a/dex/farm/tests/farm_single_user_test.rs +++ b/dex/farm/tests/farm_single_user_test.rs @@ -4,21 +4,22 @@ mod farm_setup; use config::ConfigModule; use farm_setup::single_user_farm_setup::*; -use multiversx_sc::types::EsdtLocalRole; +use multiversx_sc::{codec::multi_types::OptionalValue, types::EsdtLocalRole}; use multiversx_sc_scenario::{ - managed_address, managed_biguint, managed_token_id, rust_biguint, + managed_address, managed_biguint, managed_token_id, managed_token_id_wrapped, rust_biguint, whitebox_legacy::TxTokenTransfer, DebugApi, }; use sc_whitelist_module::SCWhitelistModule; +use simple_lock::locked_token::LockedTokenAttributes; #[test] fn test_farm_setup() { - let _ = SingleUserFarmSetup::new(farm::contract_obj); + let _ = SingleUserFarmSetup::new(farm::contract_obj, pair::contract_obj); } #[test] fn test_enter_farm() { - let mut farm_setup = SingleUserFarmSetup::new(farm::contract_obj); + let mut farm_setup = SingleUserFarmSetup::new(farm::contract_obj, pair::contract_obj); let farm_in_amount = 100_000_000; let expected_farm_token_nonce = 1; @@ -28,7 +29,7 @@ fn test_enter_farm() { #[test] fn test_exit_farm() { - let mut farm_setup = SingleUserFarmSetup::new(farm::contract_obj); + let mut farm_setup = SingleUserFarmSetup::new(farm::contract_obj, pair::contract_obj); let farm_in_amount = 100_000_000; let expected_farm_token_nonce = 1; @@ -53,7 +54,7 @@ fn test_exit_farm() { #[test] fn test_exit_farm_with_penalty() { - let mut farm_setup = SingleUserFarmSetup::new(farm::contract_obj); + let mut farm_setup = SingleUserFarmSetup::new(farm::contract_obj, pair::contract_obj); let farm_in_amount = 100_000_000; let expected_farm_token_nonce = 1; @@ -81,7 +82,7 @@ fn test_exit_farm_with_penalty() { #[test] fn test_claim_rewards() { - let mut farm_setup = SingleUserFarmSetup::new(farm::contract_obj); + let mut farm_setup = SingleUserFarmSetup::new(farm::contract_obj, pair::contract_obj); let farm_in_amount = 100_000_000; let expected_farm_token_nonce = 1; @@ -106,13 +107,15 @@ fn test_claim_rewards() { farm_setup.check_farm_token_supply(farm_in_amount); } -fn steps_enter_farm_twice( +fn steps_enter_farm_twice( farm_builder: FarmObjBuilder, -) -> SingleUserFarmSetup + pair_builder: PairObjBuilder, +) -> SingleUserFarmSetup where FarmObjBuilder: 'static + Copy + Fn() -> farm::ContractObj, + PairObjBuilder: 'static + Copy + Fn() -> pair::ContractObj, { - let mut farm_setup = SingleUserFarmSetup::new(farm_builder); + let mut farm_setup = SingleUserFarmSetup::new(farm_builder, pair_builder); let farm_in_amount = 100_000_000; let expected_farm_token_nonce = 1; @@ -155,12 +158,12 @@ where #[test] fn test_enter_farm_twice() { - let _ = steps_enter_farm_twice(farm::contract_obj); + let _ = steps_enter_farm_twice(farm::contract_obj, pair::contract_obj); } #[test] fn test_exit_farm_after_enter_twice() { - let mut farm_setup = steps_enter_farm_twice(farm::contract_obj); + let mut farm_setup = steps_enter_farm_twice(farm::contract_obj, pair::contract_obj); let farm_in_amount = 100_000_000; let second_farm_in_amount = 200_000_000; let total_farm_token = farm_in_amount + second_farm_in_amount; @@ -211,7 +214,7 @@ fn test_farm_through_simple_lock() { DebugApi::dummy(); let rust_zero = rust_biguint!(0); - let mut farm_setup = SingleUserFarmSetup::new(farm::contract_obj); + let mut farm_setup = SingleUserFarmSetup::new(farm::contract_obj, pair::contract_obj); let b_mock = &mut farm_setup.blockchain_wrapper; // setup simple lock SC @@ -615,3 +618,261 @@ fn test_farm_through_simple_lock() { Some(&lp_proxy_token_attributes), ); } + +#[test] +fn test_destroy_farm_through_simple_lock() { + use multiversx_sc::storage::mappers::StorageTokenWrapper; + use simple_lock::locked_token::LockedTokenModule; + use simple_lock::proxy_farm::ProxyFarmModule; + use simple_lock::proxy_farm::*; + use simple_lock::proxy_lp::{LpProxyTokenAttributes, ProxyLpModule}; + use simple_lock::SimpleLock; + + DebugApi::dummy(); + let rust_zero = rust_biguint!(0); + let mut farm_setup = SingleUserFarmSetup::new(farm::contract_obj, pair::contract_obj); + let b_mock = &mut farm_setup.blockchain_wrapper; + let user_addr = farm_setup.user_address.clone(); + + // setup simple lock SC + let lock_wrapper = b_mock.create_sc_account( + &rust_zero, + Some(&farm_setup.owner_address), + simple_lock::contract_obj, + "Simple Lock Path", + ); + + let farm_addr = farm_setup.farm_wrapper.address_ref().clone(); + let pair_addr = farm_setup.pair_wrapper.address_ref().clone(); + b_mock + .execute_tx(&farm_setup.owner_address, &lock_wrapper, &rust_zero, |sc| { + sc.init(); + sc.locked_token() + .set_token_id(managed_token_id!(LOCKED_TOKEN_ID)); + sc.lp_proxy_token() + .set_token_id(managed_token_id!(LOCKED_LP_TOKEN_ID)); + sc.farm_proxy_token() + .set_token_id(managed_token_id!(FARM_PROXY_TOKEN_ID)); + sc.add_farm_to_whitelist( + managed_address!(&farm_addr), + managed_token_id!(LP_TOKEN_ID), + FarmType::SimpleFarm, + ); + sc.add_lp_to_whitelist( + managed_address!(&pair_addr), + managed_token_id!(WEGLD_TOKEN_ID), + managed_token_id!(MEX_TOKEN_ID), + ); + }) + .assert_ok(); + + // change farming token for farm + whitelist simple lock contract + b_mock + .execute_tx( + &farm_setup.owner_address, + &farm_setup.farm_wrapper, + &rust_zero, + |sc| { + sc.farming_token_id().set(&managed_token_id!(LP_TOKEN_ID)); + sc.add_sc_address_to_whitelist(managed_address!(lock_wrapper.address_ref())); + }, + ) + .assert_ok(); + + b_mock.set_esdt_local_roles( + lock_wrapper.address_ref(), + LOCKED_TOKEN_ID, + &[ + EsdtLocalRole::NftCreate, + EsdtLocalRole::NftAddQuantity, + EsdtLocalRole::NftBurn, + ], + ); + b_mock.set_esdt_local_roles( + lock_wrapper.address_ref(), + LOCKED_LP_TOKEN_ID, + &[ + EsdtLocalRole::NftCreate, + EsdtLocalRole::NftAddQuantity, + EsdtLocalRole::NftBurn, + ], + ); + b_mock.set_esdt_local_roles( + lock_wrapper.address_ref(), + FARM_PROXY_TOKEN_ID, + &[ + EsdtLocalRole::NftCreate, + EsdtLocalRole::NftAddQuantity, + EsdtLocalRole::NftBurn, + ], + ); + + b_mock.set_esdt_balance(&user_addr, WEGLD_TOKEN_ID, &rust_biguint!(10_000_000)); + b_mock.set_esdt_balance(&user_addr, MEX_TOKEN_ID, &rust_biguint!(10_000_000)); + + b_mock + .execute_esdt_transfer( + &user_addr, + &lock_wrapper, + MEX_TOKEN_ID, + 0, + &rust_biguint!(10_000_000), + |sc| { + sc.lock_tokens_endpoint(15, OptionalValue::None); + }, + ) + .assert_ok(); + + b_mock.check_nft_balance( + &user_addr, + LOCKED_TOKEN_ID, + 1, + &rust_biguint!(10_000_000), + Some(&LockedTokenAttributes:: { + original_token_id: managed_token_id_wrapped!(MEX_TOKEN_ID), + original_token_nonce: 0, + unlock_epoch: 15, + }), + ); + + b_mock.set_block_epoch(5); + + // add liquidity through simple-lock SC - one locked (XMEX) token, one unlocked (WEGLD) + let transfers = vec![ + TxTokenTransfer { + token_identifier: WEGLD_TOKEN_ID.to_vec(), + nonce: 0, + value: rust_biguint!(10_000_000), + }, + TxTokenTransfer { + token_identifier: LOCKED_TOKEN_ID.to_vec(), + nonce: 1, + value: rust_biguint!(10_000_000), + }, + ]; + b_mock + .execute_esdt_multi_transfer(&user_addr, &lock_wrapper, &transfers[..], |sc| { + let (dust_first_token, dust_second_token, lp_proxy_payment) = sc + .add_liquidity_locked_token(managed_biguint!(1), managed_biguint!(1)) + .into_tuple(); + + assert_eq!( + dust_first_token.token_identifier, + managed_token_id!(WEGLD_TOKEN_ID) + ); + assert_eq!(dust_first_token.token_nonce, 0); + assert_eq!(dust_first_token.amount, managed_biguint!(0)); + + assert_eq!( + dust_second_token.token_identifier, + managed_token_id!(MEX_TOKEN_ID) + ); + assert_eq!(dust_second_token.token_nonce, 0); + assert_eq!(dust_second_token.amount, managed_biguint!(0)); + + assert_eq!( + lp_proxy_payment.token_identifier, + managed_token_id!(LOCKED_LP_TOKEN_ID) + ); + assert_eq!(lp_proxy_payment.token_nonce, 1); + assert_eq!(lp_proxy_payment.amount, managed_biguint!(9_999_000)); + }) + .assert_ok(); + + b_mock.check_nft_balance( + &user_addr, + LOCKED_LP_TOKEN_ID, + 1, + &rust_biguint!(9_999_000), + Some(&LpProxyTokenAttributes:: { + lp_token_id: managed_token_id!(LP_TOKEN_ID), + first_token_id: managed_token_id!(WEGLD_TOKEN_ID), + first_token_locked_nonce: 0, + second_token_id: managed_token_id!(MEX_TOKEN_ID), + second_token_locked_nonce: 1, + }), + ); + + b_mock.check_esdt_balance( + lock_wrapper.address_ref(), + LP_TOKEN_ID, + &rust_biguint!(9_999_000), + ); + + // user enter farm + b_mock + .execute_esdt_transfer( + &user_addr, + &lock_wrapper, + LOCKED_LP_TOKEN_ID, + 1, + &rust_biguint!(9_999_000), + |sc| { + let enter_farm_result = sc.enter_farm_locked_token(FarmType::SimpleFarm); + let (out_farm_token, _reward_token) = enter_farm_result.into_tuple(); + assert_eq!( + out_farm_token.token_identifier, + managed_token_id!(FARM_PROXY_TOKEN_ID) + ); + assert_eq!(out_farm_token.token_nonce, 1); + assert_eq!(out_farm_token.amount, managed_biguint!(9_999_000)); + }, + ) + .assert_ok(); + + b_mock.check_nft_balance( + &user_addr, + FARM_PROXY_TOKEN_ID, + 1, + &rust_biguint!(9_999_000), + Some(&FarmProxyTokenAttributes:: { + farm_type: FarmType::SimpleFarm, + farm_token_id: managed_token_id!(FARM_TOKEN_ID), + farm_token_nonce: 1, + farming_token_id: managed_token_id!(LP_TOKEN_ID), + farming_token_locked_nonce: 1, + }), + ); + + // user claim farm rewards + // b_mock.set_block_nonce(10); + b_mock.set_block_epoch(10); + + b_mock + .execute_esdt_transfer( + &user_addr, + &lock_wrapper, + FARM_PROXY_TOKEN_ID, + 1, + &rust_biguint!(9_999_000), + |sc| { + let claim_result = + sc.destroy_farm_locked_tokens(managed_biguint!(1), managed_biguint!(1)); + + assert_eq!( + claim_result.first_payment.token_identifier, + managed_token_id!(WEGLD_TOKEN_ID) + ); + assert_eq!( + claim_result.first_payment.amount, + managed_biguint!(9_999_000) + ); + + assert_eq!( + claim_result.second_payment.token_identifier, + managed_token_id!(LOCKED_TOKEN_ID) + ); + assert_eq!( + claim_result.second_payment.amount, + managed_biguint!(9_999_000) + ); + + assert_eq!( + claim_result.farm_rewards.token_identifier, + managed_token_id!(MEX_TOKEN_ID) + ); + assert_eq!(claim_result.farm_rewards.amount, managed_biguint!(0)); + }, + ) + .assert_ok(); +} diff --git a/energy-integration/governance-v2/src/configurable.rs b/energy-integration/governance-v2/src/configurable.rs index a6e5891b8..12751ce7f 100644 --- a/energy-integration/governance-v2/src/configurable.rs +++ b/energy-integration/governance-v2/src/configurable.rs @@ -135,7 +135,8 @@ pub trait ConfigurablePropertiesModule: "Not valid value for withdraw percentage if defeated!" ); - self.withdraw_percentage_defeated().set(new_withdraw_percentage); + self.withdraw_percentage_defeated() + .set(new_withdraw_percentage); } fn try_change_fee_token_id(&self, fee_token_id: TokenIdentifier) { diff --git a/energy-integration/governance-v2/tests/gov_rust_test.rs b/energy-integration/governance-v2/tests/gov_rust_test.rs index d5f371bc2..342655adf 100644 --- a/energy-integration/governance-v2/tests/gov_rust_test.rs +++ b/energy-integration/governance-v2/tests/gov_rust_test.rs @@ -7,7 +7,7 @@ use governance_v2::{ configurable::ConfigurablePropertiesModule, proposal::GovernanceProposalStatus, proposal_storage::ProposalStorageModule, views::ViewsModule, }; -use multiversx_sc::{types::ManagedVec}; +use multiversx_sc::types::ManagedVec; use multiversx_sc_scenario::{managed_buffer, rust_biguint}; #[test] @@ -71,7 +71,7 @@ fn gov_propose_test() { .b_mock .execute_query(&gov_setup.gov_wrapper, |sc| { let proposal = sc.proposals().get(1); - let action = proposal.actions.get(0).unwrap(); + let action = proposal.actions.first().unwrap(); let mut args_managed = ManagedVec::new(); args_managed.push(managed_buffer!(&1_000u64.to_be_bytes())); diff --git a/energy-integration/governance-v2/tests/gov_test_setup/mod.rs b/energy-integration/governance-v2/tests/gov_test_setup/mod.rs index 95b03ecb8..489fec3b3 100644 --- a/energy-integration/governance-v2/tests/gov_test_setup/mod.rs +++ b/energy-integration/governance-v2/tests/gov_test_setup/mod.rs @@ -182,15 +182,8 @@ where }) .assert_ok(); - let vote_nft_roles = [ - EsdtLocalRole::Mint, - EsdtLocalRole::Burn, - ]; - b_mock.set_esdt_local_roles( - gov_wrapper.address_ref(), - MEX_TOKEN_ID, - &vote_nft_roles[..], - ); + let vote_nft_roles = [EsdtLocalRole::Mint, EsdtLocalRole::Burn]; + b_mock.set_esdt_local_roles(gov_wrapper.address_ref(), MEX_TOKEN_ID, &vote_nft_roles[..]); Self { b_mock, @@ -288,7 +281,8 @@ where pub fn change_min_energy(&mut self, min_energy_for_propose: usize) -> TxResult { self.b_mock .execute_tx(&self.owner, &self.gov_wrapper, &rust_biguint!(0), |sc| { - sc.min_energy_for_propose().set(&managed_biguint!(min_energy_for_propose)); + sc.min_energy_for_propose() + .set(&managed_biguint!(min_energy_for_propose)); }) } diff --git a/farm-staking/farm-staking/src/custom_rewards.rs b/farm-staking/farm-staking/src/custom_rewards.rs index f62ec0cb7..4d07dd5a4 100644 --- a/farm-staking/farm-staking/src/custom_rewards.rs +++ b/farm-staking/farm-staking/src/custom_rewards.rs @@ -10,7 +10,8 @@ use crate::base_impl_wrapper::FarmStakingWrapper; pub const MAX_PERCENT: u64 = 10_000; pub const BLOCKS_IN_YEAR: u64 = 31_536_000 / 6; // seconds_in_year / 6_seconds_per_block pub const MAX_MIN_UNBOND_EPOCHS: u64 = 30; -pub const WITHDRAW_AMOUNT_TOO_HIGH: &str = "Withdraw amount is higher than the remaining uncollected rewards!"; +pub const WITHDRAW_AMOUNT_TOO_HIGH: &str = + "Withdraw amount is higher than the remaining uncollected rewards!"; #[multiversx_sc::module] pub trait CustomRewardsModule: @@ -55,7 +56,10 @@ pub trait CustomRewardsModule: let reward_capacity_mapper = self.reward_capacity(); let accumulated_rewards_mapper = self.accumulated_rewards(); let remaining_rewards = reward_capacity_mapper.get() - accumulated_rewards_mapper.get(); - require!(withdraw_amount <= remaining_rewards, WITHDRAW_AMOUNT_TOO_HIGH); + require!( + withdraw_amount <= remaining_rewards, + WITHDRAW_AMOUNT_TOO_HIGH + ); reward_capacity_mapper.update(|rewards| { require!( diff --git a/farm-staking/farm-staking/src/lib.rs b/farm-staking/farm-staking/src/lib.rs index ac1f23727..33f5bbd1a 100644 --- a/farm-staking/farm-staking/src/lib.rs +++ b/farm-staking/farm-staking/src/lib.rs @@ -123,7 +123,7 @@ pub trait FarmStaking: (merged_farm_token, boosted_rewards_payment).into() } - + #[view(calculateRewardsForGivenPosition)] fn calculate_rewards_for_given_position( &self, diff --git a/farm-staking/farm-staking/tests/farm_staking_setup/mod.rs b/farm-staking/farm-staking/tests/farm_staking_setup/mod.rs index 0ba2b2bc5..d8cfc9a46 100644 --- a/farm-staking/farm-staking/tests/farm_staking_setup/mod.rs +++ b/farm-staking/farm-staking/tests/farm_staking_setup/mod.rs @@ -43,8 +43,8 @@ pub const USER_REWARDS_ENERGY_CONST: u64 = 3; pub const USER_REWARDS_FARM_CONST: u64 = 2; pub const MIN_ENERGY_AMOUNT_FOR_BOOSTED_YIELDS: u64 = 1; pub const MIN_FARM_AMOUNT_FOR_BOOSTED_YIELDS: u64 = 1; -pub const WITHDRAW_AMOUNT_TOO_HIGH: &str = "Withdraw amount is higher than the remaining uncollected rewards!"; - +pub const WITHDRAW_AMOUNT_TOO_HIGH: &str = + "Withdraw amount is higher than the remaining uncollected rewards!"; pub struct FarmStakingSetup where @@ -518,7 +518,12 @@ where .assert_ok(); } - pub fn withdraw_rewards_with_error(&mut self, withdraw_amount: &RustBigUint, expected_status: u64, expected_message: &str) { + pub fn withdraw_rewards_with_error( + &mut self, + withdraw_amount: &RustBigUint, + expected_status: u64, + expected_message: &str, + ) { self.b_mock .execute_tx( &self.owner_address, diff --git a/farm-staking/farm-staking/tests/farm_staking_test.rs b/farm-staking/farm-staking/tests/farm_staking_test.rs index a8a6abb3a..89192a6a1 100644 --- a/farm-staking/farm-staking/tests/farm_staking_test.rs +++ b/farm-staking/farm-staking/tests/farm_staking_test.rs @@ -270,7 +270,8 @@ fn test_withdraw_after_produced_rewards() { let expected_reward_token_out = 40; - let withdraw_amount = rust_biguint!(TOTAL_REWARDS_AMOUNT) - rust_biguint!(expected_reward_token_out); + let withdraw_amount = + rust_biguint!(TOTAL_REWARDS_AMOUNT) - rust_biguint!(expected_reward_token_out); farm_setup.withdraw_rewards(&withdraw_amount); // Only the user's rewards will remain diff --git a/locked-asset/lkmex-transfer/tests/lkmex_transfer_tests.rs b/locked-asset/lkmex-transfer/tests/lkmex_transfer_tests.rs index e1c9dce95..4231daecf 100644 --- a/locked-asset/lkmex-transfer/tests/lkmex_transfer_tests.rs +++ b/locked-asset/lkmex-transfer/tests/lkmex_transfer_tests.rs @@ -785,7 +785,7 @@ fn transfer_locked_token_after_unlock_period_test() { // check first user energy b_mock .execute_query(&factory_sc_wrapper, |sc| { - let unlock_epoch = sc.unlock_epoch_to_start_of_month(5 + LOCK_OPTIONS[0]); + let unlock_epoch = sc.unlock_epoch_to_start_of_month(5 + LOCK_OPTIONS[0]); let lock_epochs = unlock_epoch as i64 - current_epoch as i64; let expected_energy_amount = BigInt::from((USER_BALANCE / 2) as i64) * BigInt::from(lock_epochs); diff --git a/locked-asset/proxy_dex/src/lib.rs b/locked-asset/proxy_dex/src/lib.rs index d81055288..f74f69303 100644 --- a/locked-asset/proxy_dex/src/lib.rs +++ b/locked-asset/proxy_dex/src/lib.rs @@ -9,11 +9,11 @@ pub mod energy_update; pub mod events; pub mod external_merging; pub mod farm_interactions; +pub mod other_sc_whitelist; pub mod pair_interactions; pub mod proxy_common; pub mod proxy_farm; pub mod proxy_pair; -pub mod other_sc_whitelist; pub mod wrapped_farm_attributes; pub mod wrapped_farm_token_merge; pub mod wrapped_lp_attributes; diff --git a/locked-asset/proxy_dex/src/proxy_farm.rs b/locked-asset/proxy_dex/src/proxy_farm.rs index 1d15c7528..1064a1708 100644 --- a/locked-asset/proxy_dex/src/proxy_farm.rs +++ b/locked-asset/proxy_dex/src/proxy_farm.rs @@ -22,6 +22,13 @@ pub type EnterFarmProxyResultType = MultiValue2, EsdtToke pub type ExitFarmProxyResultType = MultiValue2, EsdtTokenPayment>; pub type ClaimRewardsFarmProxyResultType = MultiValue2, EsdtTokenPayment>; +#[derive(TypeAbi, TopEncode, TopDecode, NestedEncode, NestedDecode)] +pub struct DestroyFarmResultType { + pub first_payment: EsdtTokenPayment, + pub second_payment: EsdtTokenPayment, + pub farm_rewards: EsdtTokenPayment, +} + #[multiversx_sc::module] pub trait ProxyFarmModule: crate::proxy_common::ProxyCommonModule @@ -234,6 +241,85 @@ pub trait ProxyFarmModule: (initial_proxy_farming_tokens, exit_result.reward_tokens).into() } + #[payable("*")] + #[endpoint(destroyFarmProxy)] + fn destroy_farm_proxy( + &self, + farm_address: ManagedAddress, + pair_address: ManagedAddress, + first_token_amount_min: BigUint, + second_token_amount_min: BigUint, + opt_original_caller: OptionalValue, + ) -> DestroyFarmResultType { + self.require_is_intermediated_farm(&farm_address); + self.require_is_intermediated_pair(&pair_address); + self.require_wrapped_farm_token_id_not_empty(); + self.require_wrapped_lp_token_id_not_empty(); + + let wrapped_farm_token_mapper = self.wrapped_farm_token(); + let payment = self.call_value().single_esdt(); + wrapped_farm_token_mapper.require_same_token(&payment.token_identifier); + + let full_wrapped_farm_attributes: WrappedFarmTokenAttributes = self + .blockchain() + .get_token_attributes(&payment.token_identifier, payment.token_nonce); + + let wrapped_farm_attributes_for_exit: WrappedFarmTokenAttributes = + full_wrapped_farm_attributes.into_part(&payment.amount); + + let caller = self.blockchain().get_caller(); + let original_caller = self.get_orig_caller_from_opt(&caller, opt_original_caller); + + let exit_result = self.call_exit_farm( + original_caller.clone(), + farm_address.clone(), + wrapped_farm_attributes_for_exit.farm_token.clone(), + ); + + self.burn_if_base_asset(&exit_result.farming_tokens); + + let wrapped_farm_tokens_for_initial_tokens = WrappedFarmToken { + payment: payment.clone(), + attributes: wrapped_farm_attributes_for_exit.clone(), + }; + + let initial_proxy_farming_tokens = self + .handle_farm_penalty_and_get_output_proxy_farming_token( + &original_caller, + wrapped_farm_tokens_for_initial_tokens, + exit_result.farming_tokens.amount, + ); + + let mut remove_liquidity_result = self.remove_liquidity_proxy_common( + initial_proxy_farming_tokens.clone(), + pair_address, + first_token_amount_min, + second_token_amount_min, + ); + + // Burn farm token + wrapped_farm_token_mapper.nft_burn(payment.token_nonce, &payment.amount); + + // Push farm rewards + remove_liquidity_result.push(exit_result.reward_tokens.clone()); + + self.send_multiple_tokens_if_not_zero(&caller, &remove_liquidity_result); + + self.emit_exit_farm_proxy_event( + &original_caller, + &farm_address, + payment, + wrapped_farm_attributes_for_exit, + exit_result.reward_tokens.clone(), + ); + + DestroyFarmResultType { + first_payment: remove_liquidity_result.get(0), + second_payment: remove_liquidity_result.get(1), + farm_rewards: exit_result.reward_tokens, + } + } + fn handle_farm_penalty_and_get_output_proxy_farming_token( &self, caller: &ManagedAddress, @@ -324,6 +410,9 @@ pub trait ProxyFarmModule: self.send_payment_non_zero(&caller, &new_wrapped_token); self.send_payment_non_zero(&caller, &claim_result.rewards); + // Burn farm token + wrapped_farm_token_mapper.nft_burn(payment.token_nonce, &payment.amount); + self.emit_claim_rewards_farm_proxy_event( &original_caller, &farm_address, diff --git a/locked-asset/proxy_dex/src/proxy_pair.rs b/locked-asset/proxy_dex/src/proxy_pair.rs index 1536f41cb..79542f06a 100644 --- a/locked-asset/proxy_dex/src/proxy_pair.rs +++ b/locked-asset/proxy_dex/src/proxy_pair.rs @@ -143,12 +143,32 @@ pub trait ProxyPairModule: self.require_wrapped_lp_token_id_not_empty(); let payment = self.call_value().single_esdt(); + + let output_payments = self.remove_liquidity_proxy_common( + payment, + pair_address, + first_token_amount_min, + second_token_amount_min, + ); + let caller = self.blockchain().get_caller(); + self.send_multiple_tokens_if_not_zero(&caller, &output_payments); + + output_payments.into() + } + + fn remove_liquidity_proxy_common( + &self, + input_payment: EsdtTokenPayment, + pair_address: ManagedAddress, + first_token_amount_min: BigUint, + second_token_amount_min: BigUint, + ) -> ManagedVec { let wrapped_lp_mapper = self.wrapped_lp_token(); - wrapped_lp_mapper.require_same_token(&payment.token_identifier); + wrapped_lp_mapper.require_same_token(&input_payment.token_identifier); let caller = self.blockchain().get_caller(); let attributes: WrappedLpTokenAttributes = - self.get_attributes_as_part_of_fixed_supply(&payment, &wrapped_lp_mapper); + self.get_attributes_as_part_of_fixed_supply(&input_payment, &wrapped_lp_mapper); let remove_liq_result = self.call_remove_liquidity( pair_address.clone(), @@ -206,20 +226,18 @@ pub trait ProxyPairModule: let other_tokens = received_token_refs.other_token_ref.clone(); output_payments.push(other_tokens); - wrapped_lp_mapper.nft_burn(payment.token_nonce, &payment.amount); - - self.send_multiple_tokens_if_not_zero(&caller, &output_payments); + wrapped_lp_mapper.nft_burn(input_payment.token_nonce, &input_payment.amount); self.emit_remove_liquidity_proxy_event( &caller, &pair_address, - payment, + input_payment, attributes, remove_liq_result.first_token_received, remove_liq_result.second_token_received, ); - output_payments.into() + output_payments } #[payable("*")] diff --git a/locked-asset/proxy_dex/tests/proxy_farm_test.rs b/locked-asset/proxy_dex/tests/proxy_farm_test.rs index 4dc879dba..3bc24e494 100644 --- a/locked-asset/proxy_dex/tests/proxy_farm_test.rs +++ b/locked-asset/proxy_dex/tests/proxy_farm_test.rs @@ -17,10 +17,7 @@ use multiversx_sc_scenario::{ }; use num_traits::ToPrimitive; use proxy_dex::{ - proxy_farm::ProxyFarmModule, proxy_pair::ProxyPairModule, - wrapped_farm_attributes::WrappedFarmTokenAttributes, - wrapped_farm_token_merge::WrappedFarmTokenMerge, - wrapped_lp_attributes::WrappedLpTokenAttributes, + proxy_farm::ProxyFarmModule, proxy_pair::ProxyPairModule, wrapped_farm_attributes::WrappedFarmTokenAttributes, wrapped_farm_token_merge::WrappedFarmTokenMerge, wrapped_lp_attributes::WrappedLpTokenAttributes }; use proxy_dex_test_setup::*; use simple_lock::locked_token::LockedTokenAttributes; @@ -1419,3 +1416,230 @@ fn increase_proxy_farm_proxy_lp_energy() { }), ); } + +#[test] +fn destroy_farm_locked_tokens_test() { + let mut setup = ProxySetup::new( + proxy_dex::contract_obj, + pair::contract_obj, + farm_with_locked_rewards::contract_obj, + energy_factory::contract_obj, + ); + + setup + .b_mock + .execute_tx( + &setup.owner, + &setup.farm_locked_wrapper, + &rust_biguint!(0), + |sc| { + sc.farming_token_id().set(&managed_token_id!(LP_TOKEN_ID)); + + // set produce rewards to false for easier calculation + sc.produce_rewards_enabled().set(false); + }, + ) + .assert_ok(); + + setup.b_mock.set_esdt_local_roles( + setup.farm_locked_wrapper.address_ref(), + LP_TOKEN_ID, + &[EsdtLocalRole::Burn], + ); + + let first_user = setup.first_user.clone(); + let locked_token_amount = rust_biguint!(1_000_000_000); + let other_token_amount = rust_biguint!(500_000_000); + let expected_lp_token_amount = rust_biguint!(499_999_000); + + // set the price to 1 EGLD = 2 MEX + let payments = vec![ + TxTokenTransfer { + token_identifier: LOCKED_TOKEN_ID.to_vec(), + nonce: 1, + value: locked_token_amount.clone(), + }, + TxTokenTransfer { + token_identifier: WEGLD_TOKEN_ID.to_vec(), + nonce: 0, + value: other_token_amount.clone(), + }, + ]; + + // add liquidity + let pair_addr = setup.pair_wrapper.address_ref().clone(); + setup + .b_mock + .execute_esdt_multi_transfer(&first_user, &setup.proxy_wrapper, &payments, |sc| { + sc.add_liquidity_proxy( + managed_address!(&pair_addr), + managed_biguint!(locked_token_amount.to_u64().unwrap()), + managed_biguint!(other_token_amount.to_u64().unwrap()), + ); + }) + .assert_ok(); + + setup.b_mock.check_nft_balance( + &first_user, + WRAPPED_LP_TOKEN_ID, + 1, + &expected_lp_token_amount, + Some(&WrappedLpTokenAttributes:: { + locked_tokens: EsdtTokenPayment { + token_identifier: managed_token_id!(LOCKED_TOKEN_ID), + token_nonce: 1, + amount: managed_biguint!(locked_token_amount.to_u64().unwrap()), + }, + lp_token_id: managed_token_id!(LP_TOKEN_ID), + lp_token_amount: managed_biguint!(expected_lp_token_amount.to_u64().unwrap()), + }), + ); + + let block_epoch = 1u64; + let user_balance = USER_BALANCE; + setup + .b_mock + .execute_query(&setup.simple_lock_wrapper, |sc| { + let unlock_epoch = LOCK_OPTIONS[0]; + let lock_epochs = unlock_epoch - block_epoch; + let expected_energy_amount = + BigInt::from((user_balance) as i64) * BigInt::from(lock_epochs as i64); + let expected_energy = Energy::new( + expected_energy_amount, + block_epoch, + managed_biguint!(user_balance), + ); + let actual_energy = sc.user_energy(&managed_address!(&first_user)).get(); + assert_eq!(expected_energy, actual_energy); + }) + .assert_ok(); + + let farm_locked_addr = setup.farm_locked_wrapper.address_ref().clone(); + + //////////////////////////////////////////// ENTER FARM ///////////////////////////////////// + + let mut current_epoch = 5; + setup.b_mock.set_block_epoch(current_epoch); + + setup + .b_mock + .execute_esdt_transfer( + &first_user, + &setup.proxy_wrapper, + WRAPPED_LP_TOKEN_ID, + 1, + &expected_lp_token_amount, + |sc| { + sc.enter_farm_proxy_endpoint( + managed_address!(&farm_locked_addr), + OptionalValue::None, + ); + }, + ) + .assert_ok(); + + let expected_energy = rust_biguint!(LOCK_OPTIONS[0] - current_epoch) * USER_BALANCE; + setup + .b_mock + .execute_query(&setup.simple_lock_wrapper, |sc| { + let managed_result = sc.get_energy_amount_for_user(managed_address!(&first_user)); + let result = to_rust_biguint(managed_result); + assert_eq!(result, expected_energy); + }) + .assert_ok(); + + // check user balance + setup.b_mock.check_nft_balance( + &first_user, + WRAPPED_FARM_TOKEN_ID, + 1, + &expected_lp_token_amount, + Some(&WrappedFarmTokenAttributes:: { + proxy_farming_token: EsdtTokenPayment { + token_identifier: managed_token_id!(WRAPPED_LP_TOKEN_ID), + token_nonce: 1, + amount: managed_biguint!(expected_lp_token_amount.to_u64().unwrap()), + }, + farm_token: EsdtTokenPayment { + token_identifier: managed_token_id!(FARM_LOCKED_TOKEN_ID), + token_nonce: 1, + amount: managed_biguint!(expected_lp_token_amount.to_u64().unwrap()), + }, + }), + ); + + // check proxy balance + setup + .b_mock + .check_nft_balance::>( + setup.proxy_wrapper.address_ref(), + FARM_LOCKED_TOKEN_ID, + 1, + &expected_lp_token_amount, + None, + ); + + // check farm balance + setup.b_mock.check_esdt_balance( + setup.farm_locked_wrapper.address_ref(), + LP_TOKEN_ID, + &expected_lp_token_amount, + ); + + current_epoch += 5; // applies penalty on exit + setup.b_mock.set_block_epoch(current_epoch); + setup.b_mock.set_block_nonce(100); + + ////////////////////////////////////////////// DESTROY FARM ///////////////////////////////////// + + // should be 500_000_000, but ends up so due to approximations + let removed_locked_token_amount = rust_biguint!(499_999_000); + // should be 250_000_000, but ends up so due to approximations + let removed_other_token_amount = rust_biguint!(249_999_500); + // exit with partial amount + setup + .b_mock + .execute_esdt_transfer( + &first_user, + &setup.proxy_wrapper, + WRAPPED_FARM_TOKEN_ID, + 1, + &(expected_lp_token_amount.clone() / rust_biguint!(2)), + |sc| { + let output_payments = sc.destroy_farm_proxy( + managed_address!(&farm_locked_addr), + managed_address!(&pair_addr), + managed_biguint!(1), + managed_biguint!(1), + OptionalValue::None, + ); + + assert_eq!( + output_payments.first_payment.amount.to_u64().unwrap(), + removed_locked_token_amount.to_u64().unwrap() + ); + assert_eq!( + output_payments.second_payment.amount.to_u64().unwrap(), + removed_other_token_amount.to_u64().unwrap() + ); + assert_eq!(output_payments.farm_rewards.amount.to_u64().unwrap(), 0u64); + }, + ) + .assert_ok(); + + setup.b_mock.check_nft_balance::( + &first_user, + WRAPPED_FARM_TOKEN_ID, + 1, + &(&expected_lp_token_amount / 2u64), + None, + ); + + setup.b_mock.check_nft_balance::( + &first_user, + WRAPPED_LP_TOKEN_ID, + 1, + &rust_biguint!(0u64), + None, + ); +} diff --git a/locked-asset/proxy_dex/wasm/src/lib.rs b/locked-asset/proxy_dex/wasm/src/lib.rs index 29b3ab709..90c1ad26d 100644 --- a/locked-asset/proxy_dex/wasm/src/lib.rs +++ b/locked-asset/proxy_dex/wasm/src/lib.rs @@ -5,9 +5,9 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 31 +// Endpoints: 32 // Async Callback: 1 -// Total number of exported functions: 33 +// Total number of exported functions: 34 #![no_std] #![allow(internal_features)] @@ -42,6 +42,7 @@ multiversx_sc_wasm_adapter::endpoints! { increaseProxyPairTokenEnergy => increase_proxy_pair_token_energy_endpoint enterFarmProxy => enter_farm_proxy_endpoint exitFarmProxy => exit_farm_proxy + destroyFarmProxy => destroy_farm_proxy claimRewardsProxy => claim_rewards_proxy increaseProxyFarmTokenEnergy => increase_proxy_farm_token_energy_endpoint mergeWrappedFarmTokens => merge_wrapped_farm_tokens_endpoint diff --git a/locked-asset/simple-lock-whitelist/wasm/src/lib.rs b/locked-asset/simple-lock-whitelist/wasm/src/lib.rs index d82101ff8..ce5b64928 100644 --- a/locked-asset/simple-lock-whitelist/wasm/src/lib.rs +++ b/locked-asset/simple-lock-whitelist/wasm/src/lib.rs @@ -5,9 +5,9 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 25 +// Endpoints: 26 // Async Callback: 1 -// Total number of exported functions: 27 +// Total number of exported functions: 28 #![no_std] #![allow(internal_features)] @@ -42,6 +42,7 @@ multiversx_sc_wasm_adapter::endpoints! { removeFarmFromWhitelist => remove_farm_from_whitelist enterFarmLockedToken => enter_farm_locked_token exitFarmLockedToken => exit_farm_locked_token + destroyFarmLockedTokens => destroy_farm_locked_tokens farmClaimRewardsLockedToken => farm_claim_rewards_locked_token getKnownFarms => known_farms getFarmProxyTokenId => farm_proxy_token diff --git a/locked-asset/simple-lock/src/farm_interactions.rs b/locked-asset/simple-lock/src/farm_interactions.rs index 4748f8ec5..2579a7531 100644 --- a/locked-asset/simple-lock/src/farm_interactions.rs +++ b/locked-asset/simple-lock/src/farm_interactions.rs @@ -6,7 +6,7 @@ multiversx_sc::derive_imports!(); type EnterFarmResultType = MultiValue2, EsdtTokenPayment>; type ExitFarmResultType = - MultiValue3, EsdtTokenPayment, EsdtTokenPayment>; + MultiValue2, EsdtTokenPayment>; type ClaimRewardsResultType = MultiValue2, EsdtTokenPayment>; diff --git a/locked-asset/simple-lock/src/proxy_farm.rs b/locked-asset/simple-lock/src/proxy_farm.rs index c6ab28659..33184ca3f 100644 --- a/locked-asset/simple-lock/src/proxy_farm.rs +++ b/locked-asset/simple-lock/src/proxy_farm.rs @@ -26,6 +26,13 @@ pub type FarmClaimRewardsThroughProxyResultType = MultiValue2, EsdtTokenPayment>; pub type FarmCompoundRewardsThroughProxyResultType = EsdtTokenPayment; +#[derive(TypeAbi, TopEncode, TopDecode, NestedEncode, NestedDecode)] +pub struct DestroyFarmResultType { + pub first_payment: EsdtTokenPayment, + pub second_payment: EsdtTokenPayment, + pub farm_rewards: EsdtTokenPayment, +} + #[multiversx_sc::module] pub trait ProxyFarmModule: crate::farm_interactions::FarmInteractionsModule @@ -248,6 +255,74 @@ pub trait ProxyFarmModule: (lp_proxy_token_payment, exit_farm_result.reward_tokens).into() } + /// Destroy a farm to the original tokens. + /// + /// Expected payment: Original tokens tokens + /// + /// Output Payments: + /// - original tokens + /// - farm reward tokens + #[payable("*")] + #[endpoint(destroyFarmLockedTokens)] + fn destroy_farm_locked_tokens( + &self, + first_token_min_amount_out: BigUint, + second_token_min_amount_out: BigUint, + ) -> DestroyFarmResultType { + let payment: EsdtTokenPayment = self.call_value().single_esdt(); + + let farm_proxy_token_attributes: FarmProxyTokenAttributes = + self.validate_payment_and_get_farm_proxy_token_attributes(&payment); + + let farm_address = self.try_get_farm_address( + &farm_proxy_token_attributes.farming_token_id, + farm_proxy_token_attributes.farm_type, + ); + let caller = self.blockchain().get_caller(); + let exit_farm_result = self.call_farm_exit( + farm_address, + farm_proxy_token_attributes.farm_token_id, + farm_proxy_token_attributes.farm_token_nonce, + payment.amount.clone(), + caller.clone(), + ); + require!( + exit_farm_result.initial_farming_tokens.token_identifier + == farm_proxy_token_attributes.farming_token_id, + INVALID_PAYMENTS_RECEIVED_FROM_FARM_ERR_MSG + ); + + if exit_farm_result.reward_tokens.amount > 0 { + self.send().direct_esdt( + &caller, + &exit_farm_result.reward_tokens.token_identifier, + exit_farm_result.reward_tokens.token_nonce, + &exit_farm_result.reward_tokens.amount, + ); + } + + let locked_lp_nonce = farm_proxy_token_attributes.farming_token_locked_nonce; + let lp_proxy_token_mapper = self.lp_proxy_token(); + + let (first_payment, second_payment) = self + .remove_liquidity_locked_token_common( + EsdtTokenPayment::new( + lp_proxy_token_mapper.get_token_id(), + locked_lp_nonce, + exit_farm_result.initial_farming_tokens.amount, + ), + first_token_min_amount_out, + second_token_min_amount_out, + ) + .into_tuple(); + + DestroyFarmResultType { + first_payment, + second_payment, + farm_rewards: exit_farm_result.reward_tokens, + } + } + /// Claim rewards from a previously entered farm. /// The FARM_PROXY tokens are burned, and new ones are created. /// This is needed because every farm action changes the farm token nonce @@ -273,7 +348,7 @@ pub trait ProxyFarmModule: farm_address, farm_proxy_token_attributes.farm_token_id.clone(), farm_proxy_token_attributes.farm_token_nonce, - payment.amount, + payment.amount.clone(), caller.clone(), ); require!( diff --git a/locked-asset/simple-lock/src/proxy_lp.rs b/locked-asset/simple-lock/src/proxy_lp.rs index 9d6e4e599..ed16b65d1 100644 --- a/locked-asset/simple-lock/src/proxy_lp.rs +++ b/locked-asset/simple-lock/src/proxy_lp.rs @@ -165,7 +165,7 @@ pub trait ProxyLpModule: ); let add_liq_result = self.call_pair_add_liquidity( - lp_address, + lp_address.clone(), ref_first_payment_unlocked, ref_second_payment_unlocked, first_token_amount_min, @@ -236,12 +236,26 @@ pub trait ProxyLpModule: second_token_amount_min: BigUint, ) -> RemoveLiquidityThroughProxyResultType { let payment: EsdtTokenPayment = self.call_value().single_esdt(); + + self.remove_liquidity_locked_token_common( + payment, + first_token_amount_min, + second_token_amount_min, + ) + } + + fn remove_liquidity_locked_token_common( + &self, + input_payment: EsdtTokenPayment, + first_token_amount_min: BigUint, + second_token_amount_min: BigUint, + ) -> RemoveLiquidityThroughProxyResultType { let lp_proxy_token_mapper = self.lp_proxy_token(); - lp_proxy_token_mapper.require_same_token(&payment.token_identifier); + lp_proxy_token_mapper.require_same_token(&input_payment.token_identifier); let lp_proxy_token_attributes: LpProxyTokenAttributes = - lp_proxy_token_mapper.get_token_attributes(payment.token_nonce); - lp_proxy_token_mapper.nft_burn(payment.token_nonce, &payment.amount); + lp_proxy_token_mapper.get_token_attributes(input_payment.token_nonce); + lp_proxy_token_mapper.nft_burn(input_payment.token_nonce, &input_payment.amount); let lp_address = self .lp_address_for_token_pair( @@ -249,7 +263,7 @@ pub trait ProxyLpModule: &lp_proxy_token_attributes.second_token_id, ) .get(); - let lp_token_amount = payment.amount; + let lp_token_amount = input_payment.amount; let remove_liq_result = self.call_pair_remove_liquidity( lp_address, lp_proxy_token_attributes.lp_token_id, diff --git a/locked-asset/simple-lock/wasm/src/lib.rs b/locked-asset/simple-lock/wasm/src/lib.rs index 4e1b87c7d..ad1446ca6 100644 --- a/locked-asset/simple-lock/wasm/src/lib.rs +++ b/locked-asset/simple-lock/wasm/src/lib.rs @@ -5,9 +5,9 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 20 +// Endpoints: 21 // Async Callback: 1 -// Total number of exported functions: 22 +// Total number of exported functions: 23 #![no_std] #![allow(internal_features)] @@ -37,6 +37,7 @@ multiversx_sc_wasm_adapter::endpoints! { removeFarmFromWhitelist => remove_farm_from_whitelist enterFarmLockedToken => enter_farm_locked_token exitFarmLockedToken => exit_farm_locked_token + destroyFarmLockedTokens => destroy_farm_locked_tokens farmClaimRewardsLockedToken => farm_claim_rewards_locked_token getKnownFarms => known_farms getFarmProxyTokenId => farm_proxy_token diff --git a/locked-asset/tests/distribution_scenario_go_test.rs b/locked-asset/tests/distribution_scenario_go_test.rs index b887a0d42..bedda9fe6 100644 --- a/locked-asset/tests/distribution_scenario_go_test.rs +++ b/locked-asset/tests/distribution_scenario_go_test.rs @@ -85,7 +85,8 @@ fn exit_mex_farm_proxy_after_compound_rewards_go() { #[test] #[ignore] fn exit_mex_farm_proxy_after_compound_rewards_and_epoch_increase_go() { - world().run("scenarios/exit_mex_farm_proxy_after_compound_rewards_and_epoch_increase.scen.json"); + world() + .run("scenarios/exit_mex_farm_proxy_after_compound_rewards_and_epoch_increase.scen.json"); } #[test]