diff --git a/dex/farm/tests/farm_single_user_test.rs b/dex/farm/tests/farm_single_user_test.rs index e060fbbdf..6ff0a3d3a 100644 --- a/dex/farm/tests/farm_single_user_test.rs +++ b/dex/farm/tests/farm_single_user_test.rs @@ -4,12 +4,13 @@ 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() { @@ -617,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/locked-asset/proxy_dex/src/proxy_farm.rs b/locked-asset/proxy_dex/src/proxy_farm.rs index b90f00f69..95b96adb9 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, diff --git a/locked-asset/proxy_dex/tests/proxy_farm_test.rs b/locked-asset/proxy_dex/tests/proxy_farm_test.rs index b2acafc94..ad0917915 100644 --- a/locked-asset/proxy_dex/tests/proxy_farm_test.rs +++ b/locked-asset/proxy_dex/tests/proxy_farm_test.rs @@ -1485,3 +1485,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/src/proxy_farm.rs b/locked-asset/simple-lock/src/proxy_farm.rs index 1d1a918d2..c1e5382d1 100644 --- a/locked-asset/simple-lock/src/proxy_farm.rs +++ b/locked-asset/simple-lock/src/proxy_farm.rs @@ -20,6 +20,13 @@ pub struct FarmProxyTokenAttributes { pub farming_token_locked_nonce: u64, } +#[derive(TypeAbi, TopEncode, TopDecode, NestedEncode, NestedDecode)] +pub struct DestroyFarmResultType { + pub first_payment: EsdtTokenPayment, + pub second_payment: EsdtTokenPayment, + pub farm_rewards: EsdtTokenPayment, +} + pub type EnterFarmThroughProxyResultType = MultiValue2, EsdtTokenPayment>; pub type ExitFarmThroughProxyResultType = MultiValue2, EsdtTokenPayment>; pub type FarmClaimRewardsThroughProxyResultType = @@ -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 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