From 68f6a9b260a914acb69beb3cb6399a66484c2de0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Mon, 22 Jan 2024 19:18:51 +0200 Subject: [PATCH 01/21] Simple lock: Add endpoints that breaks farm exit_farm_locked_token_to_tokens - will break farm into lp and lp into initial tokens --- locked-asset/simple-lock/src/proxy_farm.rs | 75 +++++++++++++++++++++- locked-asset/simple-lock/src/proxy_lp.rs | 22 +++++-- 2 files changed, 92 insertions(+), 5 deletions(-) diff --git a/locked-asset/simple-lock/src/proxy_farm.rs b/locked-asset/simple-lock/src/proxy_farm.rs index c6ab28659..9fd4e906b 100644 --- a/locked-asset/simple-lock/src/proxy_farm.rs +++ b/locked-asset/simple-lock/src/proxy_farm.rs @@ -1,7 +1,10 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); -use crate::{error_messages::*, proxy_lp::LpProxyTokenAttributes}; +use crate::{ + error_messages::*, + proxy_lp::{LpProxyTokenAttributes, RemoveLiquidityThroughProxyResultType}, +}; #[derive( TypeAbi, TopEncode, TopDecode, NestedEncode, NestedDecode, PartialEq, Debug, Clone, Copy, @@ -248,6 +251,76 @@ pub trait ProxyFarmModule: (lp_proxy_token_payment, exit_farm_result.reward_tokens).into() } + /// Exit a farm previously entered through `enterFarmLockedToken`. + /// + /// Expected payment: FARM_PROXY tokens + /// + /// Output Payments: + /// - original tokens + /// - farm reward tokens + #[payable("*")] + #[endpoint(exitFarmLockedTokenToTokens)] + fn exit_farm_locked_token_to_tokens( + &self, + first_token_min_amount_out: BigUint, + second_token_min_amont_out: BigUint, + ) -> RemoveLiquidityThroughProxyResultType { + 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, + 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 remove_liquidity_result = self.remove_liquidity_locked_token_common( + exit_farm_result.initial_farming_tokens, + first_token_min_amount_out, + second_token_min_amont_out, + ); + + // let lp_proxy_token = self.lp_proxy_token(); + + // let lp_proxy_token_payment = EsdtTokenPayment::new( + // lp_proxy_token.get_token_id(), + // farm_proxy_token_attributes.farming_token_locked_nonce, + // exit_farm_result.initial_farming_tokens.amount, + // ); + // self.send().direct_esdt( + // &caller, + // &lp_proxy_token_payment.token_identifier, + // lp_proxy_token_payment.token_nonce, + // &lp_proxy_token_payment.amount, + // ); + + // (lp_proxy_token_payment, exit_farm_result.reward_tokens).into() + remove_liquidity_result + } + /// 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/src/proxy_lp.rs b/locked-asset/simple-lock/src/proxy_lp.rs index 9d6e4e599..4f85130f6 100644 --- a/locked-asset/simple-lock/src/proxy_lp.rs +++ b/locked-asset/simple-lock/src/proxy_lp.rs @@ -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, From 29f098a0ab392ccfcdeb58cceecbe4f21546312c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Fri, 26 Jan 2024 13:01:04 +0200 Subject: [PATCH 02/21] Destroy farm in simple-lock --- .../simple-lock/src/lp_interactions.rs | 22 ++++++ locked-asset/simple-lock/src/proxy_farm.rs | 67 +++++++++---------- locked-asset/simple-lock/src/proxy_lp.rs | 11 ++- locked-asset/simple-lock/wasm/src/lib.rs | 5 +- 4 files changed, 67 insertions(+), 38 deletions(-) diff --git a/locked-asset/simple-lock/src/lp_interactions.rs b/locked-asset/simple-lock/src/lp_interactions.rs index 4229cca53..86e229a3f 100644 --- a/locked-asset/simple-lock/src/lp_interactions.rs +++ b/locked-asset/simple-lock/src/lp_interactions.rs @@ -123,6 +123,28 @@ pub trait LpInteractionsModule { } } + fn call_pair_remove_liquidity_simple( + &self, + lp_address: ManagedAddress, + lp_token_id: TokenIdentifier, + lp_token_amount: BigUint, + first_token_amount_min: BigUint, + second_token_amount_min: BigUint, + ) -> RemoveLiquidityResultWrapper { + let lp_payments_out: RemoveLiquidityResultType = self + .lp_proxy(lp_address) + .remove_liquidity(first_token_amount_min, second_token_amount_min) + .with_esdt_transfer((lp_token_id, 0, lp_token_amount)) + .execute_on_dest_context(); + + let (first_token_payment_out, second_token_payment_out) = lp_payments_out.into_tuple(); + + RemoveLiquidityResultWrapper { + first_token_payment_out, + second_token_payment_out, + } + } + #[proxy] fn lp_proxy(&self, sc_address: ManagedAddress) -> lp_proxy::Proxy; } diff --git a/locked-asset/simple-lock/src/proxy_farm.rs b/locked-asset/simple-lock/src/proxy_farm.rs index 9fd4e906b..d380179ec 100644 --- a/locked-asset/simple-lock/src/proxy_farm.rs +++ b/locked-asset/simple-lock/src/proxy_farm.rs @@ -1,10 +1,9 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); -use crate::{ - error_messages::*, - proxy_lp::{LpProxyTokenAttributes, RemoveLiquidityThroughProxyResultType}, -}; +use multiversx_sc_modules::transfer_role_proxy::PaymentsVec; + +use crate::{error_messages::*, proxy_lp::LpProxyTokenAttributes}; #[derive( TypeAbi, TopEncode, TopDecode, NestedEncode, NestedDecode, PartialEq, Debug, Clone, Copy, @@ -251,20 +250,20 @@ pub trait ProxyFarmModule: (lp_proxy_token_payment, exit_farm_result.reward_tokens).into() } - /// Exit a farm previously entered through `enterFarmLockedToken`. + /// Destroy a farm to the original tokens. /// - /// Expected payment: FARM_PROXY tokens + /// Expected payment: Original tokens tokens /// /// Output Payments: /// - original tokens /// - farm reward tokens #[payable("*")] - #[endpoint(exitFarmLockedTokenToTokens)] - fn exit_farm_locked_token_to_tokens( + #[endpoint(destroyFarmLockedTokens)] + fn destroy_farm_locked_tokens( &self, first_token_min_amount_out: BigUint, - second_token_min_amont_out: BigUint, - ) -> RemoveLiquidityThroughProxyResultType { + second_token_min_amount_out: BigUint, + ) -> ExitFarmThroughProxyResultType { let payment: EsdtTokenPayment = self.call_value().single_esdt(); let farm_proxy_token_attributes: FarmProxyTokenAttributes = @@ -288,37 +287,35 @@ pub trait ProxyFarmModule: INVALID_PAYMENTS_RECEIVED_FROM_FARM_ERR_MSG ); + let mut output_payments = PaymentsVec::new(); 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, - ); + output_payments.push(exit_farm_result.reward_tokens); } - let remove_liquidity_result = self.remove_liquidity_locked_token_common( - exit_farm_result.initial_farming_tokens, + let initial_farming_tokens = exit_farm_result.initial_farming_tokens; + + let lp_address = self + .lp_address_for_lp(&initial_farming_tokens.token_identifier) + .get(); + + let remove_liq_result = self.call_pair_remove_liquidity_simple( + lp_address, + initial_farming_tokens.token_identifier, + initial_farming_tokens.amount, first_token_min_amount_out, - second_token_min_amont_out, + second_token_min_amount_out, ); - // let lp_proxy_token = self.lp_proxy_token(); - - // let lp_proxy_token_payment = EsdtTokenPayment::new( - // lp_proxy_token.get_token_id(), - // farm_proxy_token_attributes.farming_token_locked_nonce, - // exit_farm_result.initial_farming_tokens.amount, - // ); - // self.send().direct_esdt( - // &caller, - // &lp_proxy_token_payment.token_identifier, - // lp_proxy_token_payment.token_nonce, - // &lp_proxy_token_payment.amount, - // ); - - // (lp_proxy_token_payment, exit_farm_result.reward_tokens).into() - remove_liquidity_result + output_payments.push(remove_liq_result.first_token_payment_out.clone()); + output_payments.push(remove_liq_result.second_token_payment_out.clone()); + + let caller = self.blockchain().get_caller(); + self.send().direct_multi(&caller, &output_payments); + + ( + remove_liq_result.first_token_payment_out.clone(), + remove_liq_result.second_token_payment_out, + ).into() } /// Claim rewards from a previously entered farm. diff --git a/locked-asset/simple-lock/src/proxy_lp.rs b/locked-asset/simple-lock/src/proxy_lp.rs index 4f85130f6..6987e9913 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, @@ -184,6 +184,8 @@ pub trait ProxyLpModule: second_payment_unlocked_wrapper.status_before, ); + self.lp_address_for_lp(&add_liq_result.lp_tokens.token_identifier).set(lp_address); + let lp_token_name = add_liq_result .lp_tokens .token_identifier @@ -393,6 +395,13 @@ pub trait ProxyLpModule: second_token_id: &TokenIdentifier, ) -> SingleValueMapper; + + #[storage_mapper("lpAddressForLp")] + fn lp_address_for_lp( + &self, + lp: &TokenIdentifier, + ) -> SingleValueMapper; + #[view(getLpProxyTokenId)] #[storage_mapper("lpProxyTokenId")] fn lp_proxy_token(&self) -> NonFungibleTokenMapper; 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 From 8c7a2707286d8a10bc225f5254bcbd8081287980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Fri, 26 Jan 2024 13:01:29 +0200 Subject: [PATCH 03/21] Simple lock whitelist --- locked-asset/simple-lock-whitelist/wasm/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 From 0fa9b7b40105fba8fa3510fdec404cc7cddf72a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Fri, 26 Jan 2024 13:01:45 +0200 Subject: [PATCH 04/21] Destroy farm in proxy-dex --- locked-asset/proxy_dex/src/proxy_farm.rs | 73 ++++++ locked-asset/proxy_dex/src/proxy_pair.rs | 41 +++- .../proxy_dex/tests/proxy_farm_test.rs | 222 ++++++++++++++++++ locked-asset/proxy_dex/wasm/src/lib.rs | 5 +- 4 files changed, 332 insertions(+), 9 deletions(-) diff --git a/locked-asset/proxy_dex/src/proxy_farm.rs b/locked-asset/proxy_dex/src/proxy_farm.rs index 1d15c7528..5e2789c0c 100644 --- a/locked-asset/proxy_dex/src/proxy_farm.rs +++ b/locked-asset/proxy_dex/src/proxy_farm.rs @@ -234,6 +234,79 @@ pub trait ProxyFarmModule: (initial_proxy_farming_tokens, exit_result.reward_tokens).into() } + #[payable("*")] + #[endpoint(destroyFarmProxy)] + fn destroy_farm_proxy( + &self, + farm_address: ManagedAddress, + first_token_amount_min: BigUint, + second_token_amount_min: BigUint, + opt_original_caller: OptionalValue, + ) -> MultiValueEncoded { + self.require_is_intermediated_farm(&farm_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 pair_address = self.lp_address_for_lp(&exit_result.farming_tokens.token_identifier).get(); + + let mut output_payments = self.remove_liquidity_proxy_common( + initial_proxy_farming_tokens.clone(), + pair_address, + first_token_amount_min, + second_token_amount_min, + ); + + // Push farm rewards + output_payments.push(exit_result.reward_tokens.clone()); + + self.send_multiple_tokens_if_not_zero(&caller, &output_payments); + + + self.emit_exit_farm_proxy_event( + &original_caller, + &farm_address, + payment, + wrapped_farm_attributes_for_exit, + exit_result.reward_tokens.clone(), + ); + + output_payments.into() + } + fn handle_farm_penalty_and_get_output_proxy_farming_token( &self, caller: &ManagedAddress, diff --git a/locked-asset/proxy_dex/src/proxy_pair.rs b/locked-asset/proxy_dex/src/proxy_pair.rs index 1536f41cb..1f3a032ab 100644 --- a/locked-asset/proxy_dex/src/proxy_pair.rs +++ b/locked-asset/proxy_dex/src/proxy_pair.rs @@ -68,6 +68,8 @@ pub trait ProxyPairModule: second_payment.amount.clone() - &add_liq_result.second_token_leftover.amount }; + self.lp_address_for_lp(&add_liq_result.lp_tokens_received.token_identifier).set(pair_address.clone()); + let new_token_attributes = WrappedLpTokenAttributes { locked_tokens: locked_token_used, lp_token_id: add_liq_result.lp_tokens_received.token_identifier.clone(), @@ -143,12 +145,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 +228,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("*")] @@ -278,4 +298,11 @@ pub trait ProxyPairModule: fn require_wrapped_lp_token_id_not_empty(&self) { require!(!self.wrapped_lp_token().is_empty(), "Empty token id"); } + + #[storage_mapper("lpAddressForLp")] + fn lp_address_for_lp( + &self, + lp: &TokenIdentifier, + ) -> SingleValueMapper; + } diff --git a/locked-asset/proxy_dex/tests/proxy_farm_test.rs b/locked-asset/proxy_dex/tests/proxy_farm_test.rs index 4dc879dba..1b998e493 100644 --- a/locked-asset/proxy_dex/tests/proxy_farm_test.rs +++ b/locked-asset/proxy_dex/tests/proxy_farm_test.rs @@ -1419,3 +1419,225 @@ 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_biguint!(1), + managed_biguint!(1), + OptionalValue::None, + ); + + let output_vec = output_payments.to_vec(); + + assert_eq!(output_payments.len(), 3); + assert_eq!( + output_vec.get(0).amount.to_u64().unwrap(), + removed_locked_token_amount.to_u64().unwrap() + ); + assert_eq!( + output_vec.get(1).amount.to_u64().unwrap(), + removed_other_token_amount.to_u64().unwrap() + ); + assert_eq!(output_vec.get(2).amount.to_u64().unwrap(), 0u64); + }, + ) + .assert_ok(); + + // check user received half of the farm tokens back, and another new wrapped LP token + setup.b_mock.check_nft_balance::( + &first_user, + WRAPPED_FARM_TOKEN_ID, + 1, + &(&expected_lp_token_amount / 2u64), + 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 From 016473d755e19c8b92e46b765754260154fdeba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Tue, 6 Feb 2024 18:18:50 +0200 Subject: [PATCH 05/21] Destroy farm: pair_addr provided as parameter --- locked-asset/proxy_dex/src/proxy_farm.rs | 3 +-- locked-asset/proxy_dex/src/proxy_pair.rs | 9 --------- locked-asset/proxy_dex/tests/proxy_farm_test.rs | 1 + locked-asset/simple-lock/src/proxy_farm.rs | 7 ++----- locked-asset/simple-lock/src/proxy_lp.rs | 9 --------- 5 files changed, 4 insertions(+), 25 deletions(-) diff --git a/locked-asset/proxy_dex/src/proxy_farm.rs b/locked-asset/proxy_dex/src/proxy_farm.rs index 5e2789c0c..c67f2daf8 100644 --- a/locked-asset/proxy_dex/src/proxy_farm.rs +++ b/locked-asset/proxy_dex/src/proxy_farm.rs @@ -239,6 +239,7 @@ pub trait ProxyFarmModule: 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, @@ -281,8 +282,6 @@ pub trait ProxyFarmModule: exit_result.farming_tokens.amount, ); - let pair_address = self.lp_address_for_lp(&exit_result.farming_tokens.token_identifier).get(); - let mut output_payments = self.remove_liquidity_proxy_common( initial_proxy_farming_tokens.clone(), pair_address, diff --git a/locked-asset/proxy_dex/src/proxy_pair.rs b/locked-asset/proxy_dex/src/proxy_pair.rs index 1f3a032ab..79542f06a 100644 --- a/locked-asset/proxy_dex/src/proxy_pair.rs +++ b/locked-asset/proxy_dex/src/proxy_pair.rs @@ -68,8 +68,6 @@ pub trait ProxyPairModule: second_payment.amount.clone() - &add_liq_result.second_token_leftover.amount }; - self.lp_address_for_lp(&add_liq_result.lp_tokens_received.token_identifier).set(pair_address.clone()); - let new_token_attributes = WrappedLpTokenAttributes { locked_tokens: locked_token_used, lp_token_id: add_liq_result.lp_tokens_received.token_identifier.clone(), @@ -298,11 +296,4 @@ pub trait ProxyPairModule: fn require_wrapped_lp_token_id_not_empty(&self) { require!(!self.wrapped_lp_token().is_empty(), "Empty token id"); } - - #[storage_mapper("lpAddressForLp")] - fn lp_address_for_lp( - &self, - lp: &TokenIdentifier, - ) -> SingleValueMapper; - } diff --git a/locked-asset/proxy_dex/tests/proxy_farm_test.rs b/locked-asset/proxy_dex/tests/proxy_farm_test.rs index 1b998e493..6a705f195 100644 --- a/locked-asset/proxy_dex/tests/proxy_farm_test.rs +++ b/locked-asset/proxy_dex/tests/proxy_farm_test.rs @@ -1611,6 +1611,7 @@ fn destroy_farm_locked_tokens_test() { |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, diff --git a/locked-asset/simple-lock/src/proxy_farm.rs b/locked-asset/simple-lock/src/proxy_farm.rs index d380179ec..9d947b777 100644 --- a/locked-asset/simple-lock/src/proxy_farm.rs +++ b/locked-asset/simple-lock/src/proxy_farm.rs @@ -261,6 +261,7 @@ pub trait ProxyFarmModule: #[endpoint(destroyFarmLockedTokens)] fn destroy_farm_locked_tokens( &self, + pair_address: ManagedAddress, first_token_min_amount_out: BigUint, second_token_min_amount_out: BigUint, ) -> ExitFarmThroughProxyResultType { @@ -294,12 +295,8 @@ pub trait ProxyFarmModule: let initial_farming_tokens = exit_farm_result.initial_farming_tokens; - let lp_address = self - .lp_address_for_lp(&initial_farming_tokens.token_identifier) - .get(); - let remove_liq_result = self.call_pair_remove_liquidity_simple( - lp_address, + pair_address, initial_farming_tokens.token_identifier, initial_farming_tokens.amount, first_token_min_amount_out, diff --git a/locked-asset/simple-lock/src/proxy_lp.rs b/locked-asset/simple-lock/src/proxy_lp.rs index 6987e9913..ed16b65d1 100644 --- a/locked-asset/simple-lock/src/proxy_lp.rs +++ b/locked-asset/simple-lock/src/proxy_lp.rs @@ -184,8 +184,6 @@ pub trait ProxyLpModule: second_payment_unlocked_wrapper.status_before, ); - self.lp_address_for_lp(&add_liq_result.lp_tokens.token_identifier).set(lp_address); - let lp_token_name = add_liq_result .lp_tokens .token_identifier @@ -395,13 +393,6 @@ pub trait ProxyLpModule: second_token_id: &TokenIdentifier, ) -> SingleValueMapper; - - #[storage_mapper("lpAddressForLp")] - fn lp_address_for_lp( - &self, - lp: &TokenIdentifier, - ) -> SingleValueMapper; - #[view(getLpProxyTokenId)] #[storage_mapper("lpProxyTokenId")] fn lp_proxy_token(&self) -> NonFungibleTokenMapper; From 5c8f183e4591f77b4e110914895ac11c3861aebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Tue, 6 Feb 2024 19:06:12 +0200 Subject: [PATCH 06/21] Simple-lock fix: destroy farm returns locked token --- locked-asset/simple-lock/src/proxy_farm.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/locked-asset/simple-lock/src/proxy_farm.rs b/locked-asset/simple-lock/src/proxy_farm.rs index 9d947b777..707f73e68 100644 --- a/locked-asset/simple-lock/src/proxy_farm.rs +++ b/locked-asset/simple-lock/src/proxy_farm.rs @@ -261,7 +261,6 @@ pub trait ProxyFarmModule: #[endpoint(destroyFarmLockedTokens)] fn destroy_farm_locked_tokens( &self, - pair_address: ManagedAddress, first_token_min_amount_out: BigUint, second_token_min_amount_out: BigUint, ) -> ExitFarmThroughProxyResultType { @@ -295,24 +294,23 @@ pub trait ProxyFarmModule: let initial_farming_tokens = exit_farm_result.initial_farming_tokens; - let remove_liq_result = self.call_pair_remove_liquidity_simple( - pair_address, - initial_farming_tokens.token_identifier, - initial_farming_tokens.amount, + let (first_token_payment_out, second_token_payment_out) = self.remove_liquidity_locked_token_common( + initial_farming_tokens, first_token_min_amount_out, second_token_min_amount_out, - ); + ).into_tuple(); - output_payments.push(remove_liq_result.first_token_payment_out.clone()); - output_payments.push(remove_liq_result.second_token_payment_out.clone()); + output_payments.push(first_token_payment_out.clone()); + output_payments.push(second_token_payment_out.clone()); let caller = self.blockchain().get_caller(); self.send().direct_multi(&caller, &output_payments); ( - remove_liq_result.first_token_payment_out.clone(), - remove_liq_result.second_token_payment_out, - ).into() + first_token_payment_out, + second_token_payment_out, + ) + .into() } /// Claim rewards from a previously entered farm. From a250fb7c7cc783b4eb6f3a2221c57438544feca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Tue, 6 Feb 2024 19:10:16 +0200 Subject: [PATCH 07/21] Burn farm tokens for claim and destry endpoints --- locked-asset/proxy_dex/src/proxy_farm.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/locked-asset/proxy_dex/src/proxy_farm.rs b/locked-asset/proxy_dex/src/proxy_farm.rs index c67f2daf8..b642da727 100644 --- a/locked-asset/proxy_dex/src/proxy_farm.rs +++ b/locked-asset/proxy_dex/src/proxy_farm.rs @@ -289,12 +289,14 @@ pub trait ProxyFarmModule: second_token_amount_min, ); + // Burn farm token + wrapped_farm_token_mapper.nft_burn(payment.token_nonce, &payment.amount); + // Push farm rewards output_payments.push(exit_result.reward_tokens.clone()); self.send_multiple_tokens_if_not_zero(&caller, &output_payments); - self.emit_exit_farm_proxy_event( &original_caller, &farm_address, @@ -396,6 +398,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, From a60edcdc32d743ca3ec7a3c30874b5e6e505920b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Tue, 6 Feb 2024 19:20:19 +0200 Subject: [PATCH 08/21] simple-lock: Fix ExitFarmResultType --- locked-asset/simple-lock/src/farm_interactions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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>; From 1d02cacd1a6b2ddf0655d89f1e1a2633347948e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Tue, 6 Feb 2024 19:42:13 +0200 Subject: [PATCH 09/21] simple-lock/proxy-dex improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit simple-lock: Check Wrapped LP in destry test proxy-dex: Remove unnecesarry function Signed-off-by: Costin CarabaČ™ --- .../proxy_dex/tests/proxy_farm_test.rs | 11 ++++++++-- .../simple-lock/src/lp_interactions.rs | 22 ------------------- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/locked-asset/proxy_dex/tests/proxy_farm_test.rs b/locked-asset/proxy_dex/tests/proxy_farm_test.rs index 6a705f195..6166b97e8 100644 --- a/locked-asset/proxy_dex/tests/proxy_farm_test.rs +++ b/locked-asset/proxy_dex/tests/proxy_farm_test.rs @@ -1594,7 +1594,7 @@ fn destroy_farm_locked_tokens_test() { 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 @@ -1633,7 +1633,6 @@ fn destroy_farm_locked_tokens_test() { ) .assert_ok(); - // check user received half of the farm tokens back, and another new wrapped LP token setup.b_mock.check_nft_balance::( &first_user, WRAPPED_FARM_TOKEN_ID, @@ -1641,4 +1640,12 @@ fn destroy_farm_locked_tokens_test() { &(&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/simple-lock/src/lp_interactions.rs b/locked-asset/simple-lock/src/lp_interactions.rs index 86e229a3f..4229cca53 100644 --- a/locked-asset/simple-lock/src/lp_interactions.rs +++ b/locked-asset/simple-lock/src/lp_interactions.rs @@ -123,28 +123,6 @@ pub trait LpInteractionsModule { } } - fn call_pair_remove_liquidity_simple( - &self, - lp_address: ManagedAddress, - lp_token_id: TokenIdentifier, - lp_token_amount: BigUint, - first_token_amount_min: BigUint, - second_token_amount_min: BigUint, - ) -> RemoveLiquidityResultWrapper { - let lp_payments_out: RemoveLiquidityResultType = self - .lp_proxy(lp_address) - .remove_liquidity(first_token_amount_min, second_token_amount_min) - .with_esdt_transfer((lp_token_id, 0, lp_token_amount)) - .execute_on_dest_context(); - - let (first_token_payment_out, second_token_payment_out) = lp_payments_out.into_tuple(); - - RemoveLiquidityResultWrapper { - first_token_payment_out, - second_token_payment_out, - } - } - #[proxy] fn lp_proxy(&self, sc_address: ManagedAddress) -> lp_proxy::Proxy; } From 6980ca83851bc0e34e1c186f47ecc7fea5b80e6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Wed, 7 Feb 2024 15:35:37 +0200 Subject: [PATCH 10/21] simple-lock: Test destroy farm --- dex/farm/tests/farm_single_user_test.rs | 422 ++++++++++++++++++++++++ 1 file changed, 422 insertions(+) diff --git a/dex/farm/tests/farm_single_user_test.rs b/dex/farm/tests/farm_single_user_test.rs index c3df21b83..ed2e278b0 100644 --- a/dex/farm/tests/farm_single_user_test.rs +++ b/dex/farm/tests/farm_single_user_test.rs @@ -615,3 +615,425 @@ 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; + + const LOCKED_TOKEN_ID: &[u8] = b"NOOOO-123456"; + const LOCKED_LP_TOKEN_ID: &[u8] = b"LKLP-123456"; + const FARM_PROXY_TOKEN_ID: &[u8] = b"PROXY-123456"; + + DebugApi::dummy(); + let rust_zero = rust_biguint!(0); + let mut farm_setup = SingleUserFarmSetup::new(farm::contract_obj); + let b_mock = &mut farm_setup.blockchain_wrapper; + + // 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(); + 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, + ); + }) + .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_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, + ], + ); + + // user lock tokens + let user_addr = farm_setup.user_address.clone(); + + let lp_proxy_token_attributes: LpProxyTokenAttributes = LpProxyTokenAttributes { + lp_token_id: managed_token_id!(LP_TOKEN_ID), + first_token_id: managed_token_id!(WEGLD_TOKEN_ID), + first_token_locked_nonce: 1, + second_token_id: managed_token_id!(MEX_TOKEN_ID), + second_token_locked_nonce: 2, + }; + + b_mock.set_nft_balance( + &user_addr, + LOCKED_LP_TOKEN_ID, + 1, + &rust_biguint!(1_000_000_000), + &lp_proxy_token_attributes, + ); + + b_mock.set_esdt_balance( + lock_wrapper.address_ref(), + LP_TOKEN_ID, + &rust_biguint!(1_000_000_000), + ); + + // user enter farm + b_mock + .execute_esdt_transfer( + &user_addr, + &lock_wrapper, + LOCKED_LP_TOKEN_ID, + 1, + &rust_biguint!(1_000_000_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!(1_000_000_000)); + }, + ) + .assert_ok(); + + b_mock.check_nft_balance( + &user_addr, + FARM_PROXY_TOKEN_ID, + 1, + &rust_biguint!(1_000_000_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(5); + + b_mock + .execute_esdt_transfer( + &user_addr, + &lock_wrapper, + FARM_PROXY_TOKEN_ID, + 1, + &rust_biguint!(1_000_000_000), + |sc| { + let claim_result = + sc.destroy_farm_locked_tokens(managed_biguint!(1), managed_biguint!(1)); + + let (first_token_payment_out, second_token_payment_out) = + claim_result.into_tuple(); + + assert_eq!( + first_token_payment_out.token_identifier, + managed_token_id!(WEGLD_TOKEN_ID) + ); + assert_eq!(first_token_payment_out.amount, managed_biguint!(1_000_000_000)); + + assert_eq!( + second_token_payment_out.token_identifier, + managed_token_id!(MEX_TOKEN_ID) + ); + assert_eq!( + second_token_payment_out.amount, + managed_biguint!(1_000_000_000) + ); + }, + ) + .assert_ok(); + + b_mock.check_nft_balance( + &user_addr, + FARM_PROXY_TOKEN_ID, + 2, + &rust_biguint!(1_000_000_000), + Some(&FarmProxyTokenAttributes:: { + farm_type: FarmType::SimpleFarm, + farm_token_id: managed_token_id!(FARM_TOKEN_ID), + farm_token_nonce: 2, + farming_token_id: managed_token_id!(LP_TOKEN_ID), + farming_token_locked_nonce: 1, + }), + ); + b_mock.check_esdt_balance( + &user_addr, + MEX_TOKEN_ID, + &rust_biguint!(10 * PER_BLOCK_REWARD_AMOUNT), + ); + + // user exit farm + b_mock.set_block_nonce(25); + + b_mock + .execute_esdt_transfer( + &user_addr, + &lock_wrapper, + FARM_PROXY_TOKEN_ID, + 2, + &rust_biguint!(1_000_000_000), + |sc| { + let exit_farm_result = sc.exit_farm_locked_token(); + let (locked_tokens, reward_tokens) = exit_farm_result.into_tuple(); + + assert_eq!( + locked_tokens.token_identifier, + managed_token_id!(LOCKED_LP_TOKEN_ID) + ); + assert_eq!(locked_tokens.token_nonce, 1); + assert_eq!(locked_tokens.amount, managed_biguint!(1_000_000_000)); + + assert_eq!( + reward_tokens.token_identifier, + managed_token_id!(MEX_TOKEN_ID) + ); + assert_eq!(reward_tokens.token_nonce, 0); + assert_eq!( + reward_tokens.amount, + managed_biguint!(15 * PER_BLOCK_REWARD_AMOUNT) + ); + }, + ) + .assert_ok(); + + b_mock.check_nft_balance( + &user_addr, + LOCKED_LP_TOKEN_ID, + 1, + &rust_biguint!(1_000_000_000), + Some(&lp_proxy_token_attributes), + ); + b_mock.check_esdt_balance( + &user_addr, + MEX_TOKEN_ID, + &rust_biguint!(25 * PER_BLOCK_REWARD_AMOUNT), + ); + + // user enter farm again + b_mock.set_block_epoch(0); + + b_mock + .execute_esdt_transfer( + &user_addr, + &lock_wrapper, + LOCKED_LP_TOKEN_ID, + 1, + &rust_biguint!(500_000_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, 3); + assert_eq!(out_farm_token.amount, managed_biguint!(500_000_000)); + }, + ) + .assert_ok(); + + b_mock.check_nft_balance( + &user_addr, + FARM_PROXY_TOKEN_ID, + 3, + &rust_biguint!(500_000_000), + Some(&FarmProxyTokenAttributes:: { + farm_type: FarmType::SimpleFarm, + farm_token_id: managed_token_id!(FARM_TOKEN_ID), + farm_token_nonce: 3, + farming_token_id: managed_token_id!(LP_TOKEN_ID), + farming_token_locked_nonce: 1, + }), + ); + + // user enter farm along with previous position + let payments = [ + TxTokenTransfer { + token_identifier: LOCKED_LP_TOKEN_ID.to_vec(), + nonce: 1, + value: rust_biguint!(300_000_000), + }, + TxTokenTransfer { + token_identifier: FARM_PROXY_TOKEN_ID.to_vec(), + nonce: 3, + value: rust_biguint!(500_000_000), + }, + ]; + b_mock + .execute_esdt_multi_transfer(&user_addr, &lock_wrapper, &payments, |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, 4); + assert_eq!(out_farm_token.amount, managed_biguint!(800_000_000)); + }) + .assert_ok(); + + b_mock.check_nft_balance( + &user_addr, + FARM_PROXY_TOKEN_ID, + 4, + &rust_biguint!(800_000_000), + Some(&FarmProxyTokenAttributes:: { + farm_type: FarmType::SimpleFarm, + farm_token_id: managed_token_id!(FARM_TOKEN_ID), + farm_token_nonce: 4, + farming_token_id: managed_token_id!(LP_TOKEN_ID), + farming_token_locked_nonce: 1, + }), + ); + + // test enter with three additional farm tokens + b_mock + .execute_esdt_transfer( + &user_addr, + &lock_wrapper, + LOCKED_LP_TOKEN_ID, + 1, + &rust_biguint!(50_000_000), + |sc| { + sc.enter_farm_locked_token(FarmType::SimpleFarm); + }, + ) + .assert_ok(); + b_mock + .execute_esdt_transfer( + &user_addr, + &lock_wrapper, + LOCKED_LP_TOKEN_ID, + 1, + &rust_biguint!(50_000_000), + |sc| { + sc.enter_farm_locked_token(FarmType::SimpleFarm); + }, + ) + .assert_ok(); + + let payments = [ + TxTokenTransfer { + token_identifier: LOCKED_LP_TOKEN_ID.to_vec(), + nonce: 1, + value: rust_biguint!(100_000_000), + }, + TxTokenTransfer { + token_identifier: FARM_PROXY_TOKEN_ID.to_vec(), + nonce: 4, + value: rust_biguint!(800_000_000), + }, + TxTokenTransfer { + token_identifier: FARM_PROXY_TOKEN_ID.to_vec(), + nonce: 5, + value: rust_biguint!(50_000_000), + }, + TxTokenTransfer { + token_identifier: FARM_PROXY_TOKEN_ID.to_vec(), + nonce: 6, + value: rust_biguint!(50_000_000), + }, + ]; + b_mock + .execute_esdt_multi_transfer(&user_addr, &lock_wrapper, &payments, |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, 7); + assert_eq!(out_farm_token.amount, managed_biguint!(1_000_000_000)); + }) + .assert_ok(); + + b_mock.check_nft_balance( + &user_addr, + FARM_PROXY_TOKEN_ID, + 7, + &rust_biguint!(1_000_000_000), + Some(&FarmProxyTokenAttributes:: { + farm_type: FarmType::SimpleFarm, + farm_token_id: managed_token_id!(FARM_TOKEN_ID), + farm_token_nonce: 7, + farming_token_id: managed_token_id!(LP_TOKEN_ID), + farming_token_locked_nonce: 1, + }), + ); + + // exit farm + b_mock.set_block_epoch(25); + b_mock + .execute_esdt_transfer( + &user_addr, + &lock_wrapper, + FARM_PROXY_TOKEN_ID, + 7, + &rust_biguint!(1_000_000_000), + |sc| { + let exit_farm_result = sc.exit_farm_locked_token(); + let (locked_tokens, _reward_tokens) = exit_farm_result.into_tuple(); + + assert_eq!( + locked_tokens.token_identifier, + managed_token_id!(LOCKED_LP_TOKEN_ID) + ); + assert_eq!(locked_tokens.token_nonce, 1); + assert_eq!(locked_tokens.amount, managed_biguint!(1_000_000_000)); + }, + ) + .assert_ok(); + + b_mock.check_nft_balance( + &user_addr, + LOCKED_LP_TOKEN_ID, + 1, + &rust_biguint!(1_000_000_000), + Some(&lp_proxy_token_attributes), + ); +} From 0d9e8f6434d9ef13b287211fd848a11eebba6dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Tue, 20 Feb 2024 13:17:39 +0200 Subject: [PATCH 11/21] Simple lock: Destroy farm test --- .../farm_setup/single_user_farm_setup.rs | 103 ++++- dex/farm/tests/farm_single_user_test.rs | 412 ++++++------------ locked-asset/simple-lock/src/proxy_farm.rs | 56 ++- .../simple-lock/tests/simple_lock_test.rs | 253 +++++++++++ .../tests/simple_lock_test_setup/mod.rs | 366 ++++++++++++++++ 5 files changed, 882 insertions(+), 308 deletions(-) create mode 100644 locked-asset/simple-lock/tests/simple_lock_test.rs create mode 100644 locked-asset/simple-lock/tests/simple_lock_test_setup/mod.rs 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 ed2e278b0..1db431556 100644 --- a/dex/farm/tests/farm_single_user_test.rs +++ b/dex/farm/tests/farm_single_user_test.rs @@ -4,21 +4,25 @@ 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 +32,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 +57,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 +85,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 +110,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 +161,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 +217,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 @@ -625,14 +631,11 @@ fn test_destroy_farm_through_simple_lock() { use simple_lock::proxy_lp::{LpProxyTokenAttributes, ProxyLpModule}; use simple_lock::SimpleLock; - const LOCKED_TOKEN_ID: &[u8] = b"NOOOO-123456"; - const LOCKED_LP_TOKEN_ID: &[u8] = b"LKLP-123456"; - const FARM_PROXY_TOKEN_ID: &[u8] = b"PROXY-123456"; - 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; + let user_addr = farm_setup.user_address.clone(); // setup simple lock SC let lock_wrapper = b_mock.create_sc_account( @@ -643,6 +646,7 @@ fn test_destroy_farm_through_simple_lock() { ); 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(); @@ -657,6 +661,11 @@ fn test_destroy_farm_through_simple_lock() { 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(); @@ -673,6 +682,15 @@ fn test_destroy_farm_through_simple_lock() { ) .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, @@ -692,178 +710,106 @@ fn test_destroy_farm_through_simple_lock() { ], ); - // user lock tokens - let user_addr = farm_setup.user_address.clone(); - - let lp_proxy_token_attributes: LpProxyTokenAttributes = LpProxyTokenAttributes { - lp_token_id: managed_token_id!(LP_TOKEN_ID), - first_token_id: managed_token_id!(WEGLD_TOKEN_ID), - first_token_locked_nonce: 1, - second_token_id: managed_token_id!(MEX_TOKEN_ID), - second_token_locked_nonce: 2, - }; - - b_mock.set_nft_balance( - &user_addr, - LOCKED_LP_TOKEN_ID, - 1, - &rust_biguint!(1_000_000_000), - &lp_proxy_token_attributes, - ); - - b_mock.set_esdt_balance( - lock_wrapper.address_ref(), - LP_TOKEN_ID, - &rust_biguint!(1_000_000_000), - ); + 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)); - // user enter farm b_mock .execute_esdt_transfer( &user_addr, &lock_wrapper, - LOCKED_LP_TOKEN_ID, - 1, - &rust_biguint!(1_000_000_000), + MEX_TOKEN_ID, + 0, + &rust_biguint!(10_000_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!(1_000_000_000)); + sc.lock_tokens_endpoint(15, OptionalValue::None); }, ) .assert_ok(); b_mock.check_nft_balance( &user_addr, - FARM_PROXY_TOKEN_ID, + LOCKED_TOKEN_ID, 1, - &rust_biguint!(1_000_000_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, + &rust_biguint!(10_000_000), + Some(&LockedTokenAttributes:: { + original_token_id: managed_token_id_wrapped!(MEX_TOKEN_ID), + original_token_nonce: 0, + unlock_epoch: 15, }), ); - // user claim farm rewards - b_mock.set_block_nonce(10); 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_transfer( - &user_addr, - &lock_wrapper, - FARM_PROXY_TOKEN_ID, - 1, - &rust_biguint!(1_000_000_000), - |sc| { - let claim_result = - sc.destroy_farm_locked_tokens(managed_biguint!(1), managed_biguint!(1)); - - let (first_token_payment_out, second_token_payment_out) = - claim_result.into_tuple(); - - assert_eq!( - first_token_payment_out.token_identifier, - managed_token_id!(WEGLD_TOKEN_ID) - ); - assert_eq!(first_token_payment_out.amount, managed_biguint!(1_000_000_000)); - - assert_eq!( - second_token_payment_out.token_identifier, - managed_token_id!(MEX_TOKEN_ID) - ); - assert_eq!( - second_token_payment_out.amount, - managed_biguint!(1_000_000_000) - ); - }, - ) - .assert_ok(); - - b_mock.check_nft_balance( - &user_addr, - FARM_PROXY_TOKEN_ID, - 2, - &rust_biguint!(1_000_000_000), - Some(&FarmProxyTokenAttributes:: { - farm_type: FarmType::SimpleFarm, - farm_token_id: managed_token_id!(FARM_TOKEN_ID), - farm_token_nonce: 2, - farming_token_id: managed_token_id!(LP_TOKEN_ID), - farming_token_locked_nonce: 1, - }), - ); - b_mock.check_esdt_balance( - &user_addr, - MEX_TOKEN_ID, - &rust_biguint!(10 * PER_BLOCK_REWARD_AMOUNT), - ); - - // user exit farm - b_mock.set_block_nonce(25); + .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(); - b_mock - .execute_esdt_transfer( - &user_addr, - &lock_wrapper, - FARM_PROXY_TOKEN_ID, - 2, - &rust_biguint!(1_000_000_000), - |sc| { - let exit_farm_result = sc.exit_farm_locked_token(); - let (locked_tokens, reward_tokens) = exit_farm_result.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!( - locked_tokens.token_identifier, - managed_token_id!(LOCKED_LP_TOKEN_ID) - ); - assert_eq!(locked_tokens.token_nonce, 1); - assert_eq!(locked_tokens.amount, managed_biguint!(1_000_000_000)); + 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!( - reward_tokens.token_identifier, - managed_token_id!(MEX_TOKEN_ID) - ); - assert_eq!(reward_tokens.token_nonce, 0); - assert_eq!( - reward_tokens.amount, - managed_biguint!(15 * PER_BLOCK_REWARD_AMOUNT) - ); - }, - ) + 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!(1_000_000_000), - Some(&lp_proxy_token_attributes), + &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( - &user_addr, - MEX_TOKEN_ID, - &rust_biguint!(25 * PER_BLOCK_REWARD_AMOUNT), + lock_wrapper.address_ref(), + LP_TOKEN_ID, + &rust_biguint!(9_999_000), ); - // user enter farm again - b_mock.set_block_epoch(0); - + // user enter farm b_mock .execute_esdt_transfer( &user_addr, &lock_wrapper, LOCKED_LP_TOKEN_ID, 1, - &rust_biguint!(500_000_000), + &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(); @@ -871,8 +817,8 @@ fn test_destroy_farm_through_simple_lock() { out_farm_token.token_identifier, managed_token_id!(FARM_PROXY_TOKEN_ID) ); - assert_eq!(out_farm_token.token_nonce, 3); - assert_eq!(out_farm_token.amount, managed_biguint!(500_000_000)); + assert_eq!(out_farm_token.token_nonce, 1); + assert_eq!(out_farm_token.amount, managed_biguint!(9_999_000)); }, ) .assert_ok(); @@ -880,160 +826,52 @@ fn test_destroy_farm_through_simple_lock() { b_mock.check_nft_balance( &user_addr, FARM_PROXY_TOKEN_ID, - 3, - &rust_biguint!(500_000_000), + 1, + &rust_biguint!(9_999_000), Some(&FarmProxyTokenAttributes:: { farm_type: FarmType::SimpleFarm, farm_token_id: managed_token_id!(FARM_TOKEN_ID), - farm_token_nonce: 3, + farm_token_nonce: 1, farming_token_id: managed_token_id!(LP_TOKEN_ID), farming_token_locked_nonce: 1, }), ); - // user enter farm along with previous position - let payments = [ - TxTokenTransfer { - token_identifier: LOCKED_LP_TOKEN_ID.to_vec(), - nonce: 1, - value: rust_biguint!(300_000_000), - }, - TxTokenTransfer { - token_identifier: FARM_PROXY_TOKEN_ID.to_vec(), - nonce: 3, - value: rust_biguint!(500_000_000), - }, - ]; - b_mock - .execute_esdt_multi_transfer(&user_addr, &lock_wrapper, &payments, |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, 4); - assert_eq!(out_farm_token.amount, managed_biguint!(800_000_000)); - }) - .assert_ok(); - - b_mock.check_nft_balance( - &user_addr, - FARM_PROXY_TOKEN_ID, - 4, - &rust_biguint!(800_000_000), - Some(&FarmProxyTokenAttributes:: { - farm_type: FarmType::SimpleFarm, - farm_token_id: managed_token_id!(FARM_TOKEN_ID), - farm_token_nonce: 4, - 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); - // test enter with three additional farm tokens b_mock .execute_esdt_transfer( &user_addr, &lock_wrapper, - LOCKED_LP_TOKEN_ID, - 1, - &rust_biguint!(50_000_000), - |sc| { - sc.enter_farm_locked_token(FarmType::SimpleFarm); - }, - ) - .assert_ok(); - b_mock - .execute_esdt_transfer( - &user_addr, - &lock_wrapper, - LOCKED_LP_TOKEN_ID, + FARM_PROXY_TOKEN_ID, 1, - &rust_biguint!(50_000_000), + &rust_biguint!(9_999_000), |sc| { - sc.enter_farm_locked_token(FarmType::SimpleFarm); - }, - ) - .assert_ok(); - - let payments = [ - TxTokenTransfer { - token_identifier: LOCKED_LP_TOKEN_ID.to_vec(), - nonce: 1, - value: rust_biguint!(100_000_000), - }, - TxTokenTransfer { - token_identifier: FARM_PROXY_TOKEN_ID.to_vec(), - nonce: 4, - value: rust_biguint!(800_000_000), - }, - TxTokenTransfer { - token_identifier: FARM_PROXY_TOKEN_ID.to_vec(), - nonce: 5, - value: rust_biguint!(50_000_000), - }, - TxTokenTransfer { - token_identifier: FARM_PROXY_TOKEN_ID.to_vec(), - nonce: 6, - value: rust_biguint!(50_000_000), - }, - ]; - b_mock - .execute_esdt_multi_transfer(&user_addr, &lock_wrapper, &payments, |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, 7); - assert_eq!(out_farm_token.amount, managed_biguint!(1_000_000_000)); - }) - .assert_ok(); + let claim_result = + sc.destroy_farm_locked_tokens(managed_biguint!(1), managed_biguint!(1)); - b_mock.check_nft_balance( - &user_addr, - FARM_PROXY_TOKEN_ID, - 7, - &rust_biguint!(1_000_000_000), - Some(&FarmProxyTokenAttributes:: { - farm_type: FarmType::SimpleFarm, - farm_token_id: managed_token_id!(FARM_TOKEN_ID), - farm_token_nonce: 7, - farming_token_id: managed_token_id!(LP_TOKEN_ID), - farming_token_locked_nonce: 1, - }), - ); + let (first_token_payment_out, second_token_payment_out) = claim_result.into_tuple(); - // exit farm - b_mock.set_block_epoch(25); - b_mock - .execute_esdt_transfer( - &user_addr, - &lock_wrapper, - FARM_PROXY_TOKEN_ID, - 7, - &rust_biguint!(1_000_000_000), - |sc| { - let exit_farm_result = sc.exit_farm_locked_token(); - let (locked_tokens, _reward_tokens) = exit_farm_result.into_tuple(); + assert_eq!( + first_token_payment_out.token_identifier, + managed_token_id!(WEGLD_TOKEN_ID) + ); + assert_eq!( + first_token_payment_out.amount, + managed_biguint!(9_999_000) + ); assert_eq!( - locked_tokens.token_identifier, - managed_token_id!(LOCKED_LP_TOKEN_ID) + second_token_payment_out.token_identifier, + managed_token_id!(LOCKED_TOKEN_ID) + ); + assert_eq!( + second_token_payment_out.amount, + managed_biguint!(9_999_000) ); - assert_eq!(locked_tokens.token_nonce, 1); - assert_eq!(locked_tokens.amount, managed_biguint!(1_000_000_000)); }, ) .assert_ok(); - - b_mock.check_nft_balance( - &user_addr, - LOCKED_LP_TOKEN_ID, - 1, - &rust_biguint!(1_000_000_000), - Some(&lp_proxy_token_attributes), - ); } diff --git a/locked-asset/simple-lock/src/proxy_farm.rs b/locked-asset/simple-lock/src/proxy_farm.rs index 707f73e68..62bba9d6e 100644 --- a/locked-asset/simple-lock/src/proxy_farm.rs +++ b/locked-asset/simple-lock/src/proxy_farm.rs @@ -1,9 +1,7 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); -use multiversx_sc_modules::transfer_role_proxy::PaymentsVec; - -use crate::{error_messages::*, proxy_lp::LpProxyTokenAttributes}; +use crate::{error_messages::*, locked_token::PreviousStatusFlag, proxy_lp::LpProxyTokenAttributes}; #[derive( TypeAbi, TopEncode, TopDecode, NestedEncode, NestedDecode, PartialEq, Debug, Clone, Copy, @@ -287,30 +285,54 @@ pub trait ProxyFarmModule: INVALID_PAYMENTS_RECEIVED_FROM_FARM_ERR_MSG ); - let mut output_payments = PaymentsVec::new(); if exit_farm_result.reward_tokens.amount > 0 { - output_payments.push(exit_farm_result.reward_tokens); + 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 initial_farming_tokens = exit_farm_result.initial_farming_tokens; - let (first_token_payment_out, second_token_payment_out) = self.remove_liquidity_locked_token_common( - initial_farming_tokens, + // get LOCKED_LP nonce + let locked_lp_nonce = farm_proxy_token_attributes.farming_token_locked_nonce; + let lp_proxy_token_mapper = self.lp_proxy_token(); + let lp_proxy_token_attributes: LpProxyTokenAttributes = + lp_proxy_token_mapper.get_token_attributes(locked_lp_nonce); + + // get LP address + let lp_address = self + .lp_address_for_token_pair( + &lp_proxy_token_attributes.first_token_id, + &lp_proxy_token_attributes.second_token_id, + ) + .get(); + + let remove_liq_result = self.call_pair_remove_liquidity( + lp_address, + lp_proxy_token_attributes.lp_token_id, + initial_farming_tokens.amount, first_token_min_amount_out, second_token_min_amount_out, - ).into_tuple(); - - output_payments.push(first_token_payment_out.clone()); - output_payments.push(second_token_payment_out.clone()); + &lp_proxy_token_attributes.first_token_id, + &lp_proxy_token_attributes.second_token_id, + ); let caller = self.blockchain().get_caller(); - self.send().direct_multi(&caller, &output_payments); + let first_token_result_payment = self.send_tokens_optimal_status( + &caller, + remove_liq_result.first_token_payment_out, + PreviousStatusFlag::new(lp_proxy_token_attributes.first_token_locked_nonce), + ); + let second_token_result_payment = self.send_tokens_optimal_status( + &caller, + remove_liq_result.second_token_payment_out, + PreviousStatusFlag::new(lp_proxy_token_attributes.second_token_locked_nonce), + ); - ( - first_token_payment_out, - second_token_payment_out, - ) - .into() + (first_token_result_payment, second_token_result_payment).into() } /// Claim rewards from a previously entered farm. diff --git a/locked-asset/simple-lock/tests/simple_lock_test.rs b/locked-asset/simple-lock/tests/simple_lock_test.rs new file mode 100644 index 000000000..65094222e --- /dev/null +++ b/locked-asset/simple-lock/tests/simple_lock_test.rs @@ -0,0 +1,253 @@ +#![allow(deprecated)] + +mod simple_lock_test_setup; + +use common_structs::FarmTokenAttributes; +use config::ConfigModule; +use energy_factory::energy::EnergyModule; +use energy_query::Energy; + +use multiversx_sc::{ + codec::{multi_types::OptionalValue, Empty}, + types::{BigInt, EsdtLocalRole, EsdtTokenPayment}, +}; +use multiversx_sc_scenario::{ + managed_address, managed_biguint, managed_token_id, rust_biguint, + whitebox_legacy::TxTokenTransfer, DebugApi, +}; +use num_traits::ToPrimitive; +use proxy_dex::{ + proxy_farm::ProxyFarmModule, proxy_pair::ProxyPairModule, + wrapped_farm_attributes::WrappedFarmTokenAttributes, + wrapped_lp_attributes::WrappedLpTokenAttributes, +}; + +#[test] +fn destroy_farm_locked_tokens_test() { + let mut setup = SimpleLockSetup::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, + ); + + let output_vec = output_payments.to_vec(); + + assert_eq!(output_payments.len(), 3); + assert_eq!( + output_vec.get(0).amount.to_u64().unwrap(), + removed_locked_token_amount.to_u64().unwrap() + ); + assert_eq!( + output_vec.get(1).amount.to_u64().unwrap(), + removed_other_token_amount.to_u64().unwrap() + ); + assert_eq!(output_vec.get(2).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/simple-lock/tests/simple_lock_test_setup/mod.rs b/locked-asset/simple-lock/tests/simple_lock_test_setup/mod.rs new file mode 100644 index 000000000..260c382c5 --- /dev/null +++ b/locked-asset/simple-lock/tests/simple_lock_test_setup/mod.rs @@ -0,0 +1,366 @@ +#![allow(dead_code)] +#![allow(deprecated)] + +use common_structs::FarmTokenAttributes; +use multiversx_sc::codec::multi_types::OptionalValue; +use multiversx_sc::storage::mappers::StorageTokenWrapper; +use multiversx_sc::types::{Address, EsdtLocalRole, ManagedAddress, MultiValueEncoded}; +use multiversx_sc_scenario::whitebox_legacy::{TxContextStack, TxTokenTransfer}; +use multiversx_sc_scenario::{ + managed_address, managed_biguint, managed_token_id, rust_biguint, whitebox_legacy::*, DebugApi, +}; + +type RustBigUint = num_bigint::BigUint; + +use config::*; +use farm::exit_penalty::ExitPenaltyModule; +use farm::*; +use farm_boosted_yields::boosted_yields_factors::BoostedYieldsFactorsModule; +use farm_token::FarmTokenModule; +use pausable::{PausableModule, State}; + +// General +pub static MEX_TOKEN_ID: &[u8] = b"MEX-123456"; +pub static WEGLD_TOKEN_ID: &[u8] = b"WEGLD-123456"; +pub const EPOCHS_IN_YEAR: u64 = 360; +pub const USER_BALANCE: u64 = 1_000_000_000_000_000_000; + +// Pair +pub static LP_TOKEN_ID: &[u8] = b"LPTOK-123456"; + +// Farm +pub static FARM_LOCKED_TOKEN_ID: &[u8] = b"FARML-123456"; +pub const DIVISION_SAFETY_CONSTANT: u64 = 1_000_000_000_000_000_000; +pub const PER_BLOCK_REWARD_AMOUNT: u64 = 5_000; +pub const USER_REWARDS_BASE_CONST: u64 = 10; +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; + +// Simple Lock +pub static LOCKED_TOKEN_ID: &[u8] = b"LOCKED-123456"; +pub static LEGACY_LOCKED_TOKEN_ID: &[u8] = b"LEGACY-123456"; +pub static LOCK_OPTIONS: &[u64] = &[EPOCHS_IN_YEAR, 5 * EPOCHS_IN_YEAR, 10 * EPOCHS_IN_YEAR]; // 1, 5 or 10 years +pub static PENALTY_PERCENTAGES: &[u64] = &[4_000, 6_000, 8_000]; + +// Proxy +pub static WRAPPED_LP_TOKEN_ID: &[u8] = b"WPLP-123456"; +pub static WRAPPED_FARM_TOKEN_ID: &[u8] = b"WPFARM-123456"; + + +pub struct SimpleLockSetup +where + SimpleLockObjBuilder: 'static + Copy + Fn() -> simple_lock::ContractObj, + PairObjBuilder: 'static + Copy + Fn() -> pair::ContractObj, + FarmLockedObjBuilder: 'static + Copy + Fn() -> farm_with_locked_rewards::ContractObj, +{ + pub b_mock: BlockchainStateWrapper, + pub owner: Address, + pub first_user: Address, + pub second_user: Address, + pub simple_lock_wrapper: + ContractObjWrapper, SimpleLockObjBuilder>, + pub pair_wrapper: ContractObjWrapper, PairObjBuilder>, + pub farm_locked_wrapper: + ContractObjWrapper, FarmLockedObjBuilder>, +} + +impl + SimpleLockSetup +where + SimpleLockObjBuilder: 'static + Copy + Fn() -> simple_lock::ContractObj, + PairObjBuilder: 'static + Copy + Fn() -> pair::ContractObj, + FarmLockedObjBuilder: 'static + Copy + Fn() -> farm_with_locked_rewards::ContractObj, +{ + pub fn new(farm_builder: SimpleLockObjBuilder) -> Self { + let rust_zero = rust_biguint!(0u64); + let mut blockchain_wrapper = BlockchainStateWrapper::new(); + let owner_addr = blockchain_wrapper.create_user_account(&rust_zero); + let farm_wrapper = blockchain_wrapper.create_sc_account( + &rust_zero, + Some(&owner_addr), + farm_builder, + FARM_WASM_PATH, + ); + + // init farm contract + + blockchain_wrapper + .execute_tx(&owner_addr, &farm_wrapper, &rust_zero, |sc| { + let reward_token_id = managed_token_id!(MEX_TOKEN_ID); + let farming_token_id = managed_token_id!(LP_TOKEN_ID); + let division_safety_constant = managed_biguint!(DIVISION_SAFETY_CONSTANT); + let pair_address = managed_address!(&Address::zero()); + + sc.init( + reward_token_id, + farming_token_id, + division_safety_constant, + pair_address, + ManagedAddress::::zero(), + MultiValueEncoded::new(), + ); + + let farm_token_id = managed_token_id!(FARM_TOKEN_ID); + sc.farm_token().set_token_id(farm_token_id); + + sc.per_block_reward_amount() + .set(&managed_biguint!(PER_BLOCK_REWARD_AMOUNT)); + sc.minimum_farming_epochs().set(MIN_FARMING_EPOCHS); + sc.penalty_percent().set(PENALTY_PERCENT); + + sc.state().set(State::Active); + sc.produce_rewards_enabled().set(true); + }) + .assert_ok(); + + blockchain_wrapper + .execute_tx(&owner_addr, &farm_wrapper, &rust_biguint!(0), |sc| { + sc.set_boosted_yields_factors( + managed_biguint!(MAX_REWARDS_FACTOR), + managed_biguint!(USER_REWARDS_ENERGY_CONST), + managed_biguint!(USER_REWARDS_FARM_CONST), + managed_biguint!(MIN_ENERGY_AMOUNT_FOR_BOOSTED_YIELDS), + managed_biguint!(MIN_FARM_AMOUNT_FOR_BOOSTED_YIELDS), + ); + }) + .assert_ok(); + + let farm_token_roles = [ + EsdtLocalRole::NftCreate, + EsdtLocalRole::NftAddQuantity, + EsdtLocalRole::NftBurn, + ]; + blockchain_wrapper.set_esdt_local_roles( + farm_wrapper.address_ref(), + FARM_TOKEN_ID, + &farm_token_roles[..], + ); + + let farming_token_roles = [EsdtLocalRole::Burn]; + blockchain_wrapper.set_esdt_local_roles( + farm_wrapper.address_ref(), + LP_TOKEN_ID, + &farming_token_roles[..], + ); + + let reward_token_roles = [EsdtLocalRole::Mint]; + blockchain_wrapper.set_esdt_local_roles( + farm_wrapper.address_ref(), + MEX_TOKEN_ID, + &reward_token_roles[..], + ); + + let user_addr = blockchain_wrapper.create_user_account(&rust_biguint!(100_000_000)); + blockchain_wrapper.set_esdt_balance( + &user_addr, + LP_TOKEN_ID, + &rust_biguint!(USER_TOTAL_LP_TOKENS), + ); + + SingleUserFarmSetup { + blockchain_wrapper, + owner_address: owner_addr, + user_address: user_addr, + farm_wrapper, + } + } + + pub fn enter_farm( + &mut self, + farm_in_amount: u64, + additional_farm_tokens: &[TxTokenTransfer], + expected_farm_token_nonce: u64, + expected_reward_per_share: u64, + expected_entering_epoch: u64, + expected_compounded_reward: u64, + ) { + let mut payments = Vec::with_capacity(1 + additional_farm_tokens.len()); + payments.push(TxTokenTransfer { + token_identifier: LP_TOKEN_ID.to_vec(), + nonce: 0, + value: rust_biguint!(farm_in_amount), + }); + payments.extend_from_slice(additional_farm_tokens); + + let mut expected_total_out_amount = 0; + for payment in payments.iter() { + expected_total_out_amount += payment.value.to_u64_digits()[0]; + } + + let b_mock = &mut self.blockchain_wrapper; + b_mock + .execute_esdt_multi_transfer(&self.user_address, &self.farm_wrapper, &payments, |sc| { + let enter_farm_result = sc.enter_farm_endpoint(OptionalValue::None); + let (out_farm_token, _reward_token) = enter_farm_result.into_tuple(); + assert_eq!( + out_farm_token.token_identifier, + managed_token_id!(FARM_TOKEN_ID) + ); + assert_eq!(out_farm_token.token_nonce, expected_farm_token_nonce); + assert_eq!( + out_farm_token.amount, + managed_biguint!(expected_total_out_amount) + ); + }) + .assert_ok(); + + DebugApi::dummy(); + + let expected_attributes = FarmTokenAttributes:: { + reward_per_share: managed_biguint!(expected_reward_per_share), + entering_epoch: expected_entering_epoch, + compounded_reward: managed_biguint!(expected_compounded_reward), + current_farm_amount: managed_biguint!(expected_total_out_amount), + original_owner: managed_address!(&self.user_address), + }; + b_mock.check_nft_balance( + &self.user_address, + FARM_TOKEN_ID, + expected_farm_token_nonce, + &rust_biguint!(expected_total_out_amount), + Some(&expected_attributes), + ); + + let _ = TxContextStack::static_pop(); + } + + pub fn exit_farm( + &mut self, + farm_token_amount: u64, + farm_token_nonce: u64, + expected_mex_out: u64, + expected_farm_token_amount: u64, + expected_user_mex_balance: &RustBigUint, + expected_user_lp_token_balance: &RustBigUint, + ) { + let b_mock = &mut self.blockchain_wrapper; + b_mock + .execute_esdt_transfer( + &self.user_address, + &self.farm_wrapper, + FARM_TOKEN_ID, + farm_token_nonce, + &rust_biguint!(farm_token_amount), + |sc| { + let multi_result = sc.exit_farm_endpoint(OptionalValue::None); + + let (first_result, second_result) = multi_result.into_tuple(); + + assert_eq!( + first_result.token_identifier, + managed_token_id!(LP_TOKEN_ID) + ); + assert_eq!(first_result.token_nonce, 0); + assert_eq!( + first_result.amount, + managed_biguint!(expected_farm_token_amount) + ); + + assert_eq!( + second_result.token_identifier, + managed_token_id!(MEX_TOKEN_ID) + ); + assert_eq!(second_result.token_nonce, 0); + assert_eq!(second_result.amount, managed_biguint!(expected_mex_out)); + }, + ) + .assert_ok(); + + b_mock.check_esdt_balance(&self.user_address, MEX_TOKEN_ID, expected_user_mex_balance); + b_mock.check_esdt_balance( + &self.user_address, + LP_TOKEN_ID, + expected_user_lp_token_balance, + ); + } + + #[allow(clippy::too_many_arguments)] + pub fn claim_rewards( + &mut self, + farm_token_amount: u64, + farm_token_nonce: u64, + expected_mex_out: u64, + expected_user_mex_balance: &RustBigUint, + expected_user_lp_token_balance: &RustBigUint, + expected_farm_token_nonce_out: u64, + expected_reward_per_share: u64, + ) { + let b_mock = &mut self.blockchain_wrapper; + b_mock + .execute_esdt_transfer( + &self.user_address, + &self.farm_wrapper, + FARM_TOKEN_ID, + farm_token_nonce, + &rust_biguint!(farm_token_amount), + |sc| { + let multi_result = sc.claim_rewards_endpoint(OptionalValue::None); + + let (first_result, second_result) = multi_result.into_tuple(); + + assert_eq!( + first_result.token_identifier, + managed_token_id!(FARM_TOKEN_ID) + ); + assert_eq!(first_result.token_nonce, expected_farm_token_nonce_out); + assert_eq!(first_result.amount, managed_biguint!(farm_token_amount)); + + assert_eq!( + second_result.token_identifier, + managed_token_id!(MEX_TOKEN_ID) + ); + assert_eq!(second_result.token_nonce, 0); + assert_eq!(second_result.amount, managed_biguint!(expected_mex_out)); + }, + ) + .assert_ok(); + + DebugApi::dummy(); + let expected_attributes = FarmTokenAttributes:: { + reward_per_share: managed_biguint!(expected_reward_per_share), + entering_epoch: 0, + compounded_reward: managed_biguint!(0), + current_farm_amount: managed_biguint!(farm_token_amount), + original_owner: managed_address!(&self.user_address), + }; + + b_mock.check_nft_balance( + &self.user_address, + FARM_TOKEN_ID, + expected_farm_token_nonce_out, + &rust_biguint!(farm_token_amount), + Some(&expected_attributes), + ); + b_mock.check_esdt_balance(&self.user_address, MEX_TOKEN_ID, expected_user_mex_balance); + b_mock.check_esdt_balance( + &self.user_address, + LP_TOKEN_ID, + expected_user_lp_token_balance, + ); + + let _ = TxContextStack::static_pop(); + } + + pub fn check_farm_token_supply(&mut self, expected_farm_token_supply: u64) { + let b_mock = &mut self.blockchain_wrapper; + b_mock + .execute_query(&self.farm_wrapper, |sc| { + let actual_farm_supply = sc.farm_token_supply().get(); + assert_eq!( + managed_biguint!(expected_farm_token_supply), + actual_farm_supply + ); + }) + .assert_ok(); + } + + pub fn set_block_nonce(&mut self, block_nonce: u64) { + self.blockchain_wrapper.set_block_nonce(block_nonce); + } + + pub fn set_block_epoch(&mut self, block_epoch: u64) { + self.blockchain_wrapper.set_block_epoch(block_epoch); + } +} From 1682a478315e0839b3eda5869fbae7d4420e67f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Tue, 20 Feb 2024 13:18:26 +0200 Subject: [PATCH 12/21] Cargo fmt --- dex/farm/tests/farm_single_user_test.rs | 15 +++------------ .../governance-v2/src/configurable.rs | 3 ++- .../governance-v2/tests/gov_rust_test.rs | 2 +- .../governance-v2/tests/gov_test_setup/mod.rs | 14 ++++---------- farm-staking/farm-staking/src/custom_rewards.rs | 8 ++++++-- farm-staking/farm-staking/src/lib.rs | 2 +- .../farm-staking/tests/farm_staking_setup/mod.rs | 11 ++++++++--- .../farm-staking/tests/farm_staking_test.rs | 3 ++- .../lkmex-transfer/tests/lkmex_transfer_tests.rs | 2 +- locked-asset/proxy_dex/src/lib.rs | 2 +- locked-asset/proxy_dex/tests/proxy_farm_test.rs | 2 +- locked-asset/simple-lock/src/proxy_farm.rs | 4 +++- .../simple-lock/tests/simple_lock_test.rs | 2 +- .../tests/simple_lock_test_setup/mod.rs | 1 - .../tests/distribution_scenario_go_test.rs | 3 ++- 15 files changed, 36 insertions(+), 38 deletions(-) diff --git a/dex/farm/tests/farm_single_user_test.rs b/dex/farm/tests/farm_single_user_test.rs index 1db431556..f1262efe0 100644 --- a/dex/farm/tests/farm_single_user_test.rs +++ b/dex/farm/tests/farm_single_user_test.rs @@ -4,10 +4,7 @@ mod farm_setup; use config::ConfigModule; use farm_setup::single_user_farm_setup::*; -use multiversx_sc::{ - codec::multi_types::OptionalValue, - types::EsdtLocalRole, -}; +use multiversx_sc::{codec::multi_types::OptionalValue, types::EsdtLocalRole}; use multiversx_sc_scenario::{ managed_address, managed_biguint, managed_token_id, managed_token_id_wrapped, rust_biguint, whitebox_legacy::TxTokenTransfer, DebugApi, @@ -858,19 +855,13 @@ fn test_destroy_farm_through_simple_lock() { first_token_payment_out.token_identifier, managed_token_id!(WEGLD_TOKEN_ID) ); - assert_eq!( - first_token_payment_out.amount, - managed_biguint!(9_999_000) - ); + assert_eq!(first_token_payment_out.amount, managed_biguint!(9_999_000)); assert_eq!( second_token_payment_out.token_identifier, managed_token_id!(LOCKED_TOKEN_ID) ); - assert_eq!( - second_token_payment_out.amount, - managed_biguint!(9_999_000) - ); + assert_eq!(second_token_payment_out.amount, managed_biguint!(9_999_000)); }, ) .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..bd9dcbf17 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] 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/tests/proxy_farm_test.rs b/locked-asset/proxy_dex/tests/proxy_farm_test.rs index 6166b97e8..9018b972c 100644 --- a/locked-asset/proxy_dex/tests/proxy_farm_test.rs +++ b/locked-asset/proxy_dex/tests/proxy_farm_test.rs @@ -1594,7 +1594,7 @@ fn destroy_farm_locked_tokens_test() { 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 diff --git a/locked-asset/simple-lock/src/proxy_farm.rs b/locked-asset/simple-lock/src/proxy_farm.rs index 62bba9d6e..5932e26a2 100644 --- a/locked-asset/simple-lock/src/proxy_farm.rs +++ b/locked-asset/simple-lock/src/proxy_farm.rs @@ -1,7 +1,9 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); -use crate::{error_messages::*, locked_token::PreviousStatusFlag, proxy_lp::LpProxyTokenAttributes}; +use crate::{ + error_messages::*, locked_token::PreviousStatusFlag, proxy_lp::LpProxyTokenAttributes, +}; #[derive( TypeAbi, TopEncode, TopDecode, NestedEncode, NestedDecode, PartialEq, Debug, Clone, Copy, diff --git a/locked-asset/simple-lock/tests/simple_lock_test.rs b/locked-asset/simple-lock/tests/simple_lock_test.rs index 65094222e..4029ba34a 100644 --- a/locked-asset/simple-lock/tests/simple_lock_test.rs +++ b/locked-asset/simple-lock/tests/simple_lock_test.rs @@ -196,7 +196,7 @@ fn destroy_farm_locked_tokens_test() { 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 diff --git a/locked-asset/simple-lock/tests/simple_lock_test_setup/mod.rs b/locked-asset/simple-lock/tests/simple_lock_test_setup/mod.rs index 260c382c5..92f145fba 100644 --- a/locked-asset/simple-lock/tests/simple_lock_test_setup/mod.rs +++ b/locked-asset/simple-lock/tests/simple_lock_test_setup/mod.rs @@ -48,7 +48,6 @@ pub static PENALTY_PERCENTAGES: &[u64] = &[4_000, 6_000, 8_000]; pub static WRAPPED_LP_TOKEN_ID: &[u8] = b"WPLP-123456"; pub static WRAPPED_FARM_TOKEN_ID: &[u8] = b"WPFARM-123456"; - pub struct SimpleLockSetup where SimpleLockObjBuilder: 'static + Copy + Fn() -> simple_lock::ContractObj, 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] From c2eb950a7e5755cb4040f2b104a4b01ae80086de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Tue, 20 Feb 2024 13:35:53 +0200 Subject: [PATCH 13/21] Remove unnecessary test --- .../simple-lock/tests/simple_lock_test.rs | 253 ------------ .../tests/simple_lock_test_setup/mod.rs | 365 ------------------ 2 files changed, 618 deletions(-) delete mode 100644 locked-asset/simple-lock/tests/simple_lock_test.rs delete mode 100644 locked-asset/simple-lock/tests/simple_lock_test_setup/mod.rs diff --git a/locked-asset/simple-lock/tests/simple_lock_test.rs b/locked-asset/simple-lock/tests/simple_lock_test.rs deleted file mode 100644 index 4029ba34a..000000000 --- a/locked-asset/simple-lock/tests/simple_lock_test.rs +++ /dev/null @@ -1,253 +0,0 @@ -#![allow(deprecated)] - -mod simple_lock_test_setup; - -use common_structs::FarmTokenAttributes; -use config::ConfigModule; -use energy_factory::energy::EnergyModule; -use energy_query::Energy; - -use multiversx_sc::{ - codec::{multi_types::OptionalValue, Empty}, - types::{BigInt, EsdtLocalRole, EsdtTokenPayment}, -}; -use multiversx_sc_scenario::{ - managed_address, managed_biguint, managed_token_id, rust_biguint, - whitebox_legacy::TxTokenTransfer, DebugApi, -}; -use num_traits::ToPrimitive; -use proxy_dex::{ - proxy_farm::ProxyFarmModule, proxy_pair::ProxyPairModule, - wrapped_farm_attributes::WrappedFarmTokenAttributes, - wrapped_lp_attributes::WrappedLpTokenAttributes, -}; - -#[test] -fn destroy_farm_locked_tokens_test() { - let mut setup = SimpleLockSetup::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, - ); - - let output_vec = output_payments.to_vec(); - - assert_eq!(output_payments.len(), 3); - assert_eq!( - output_vec.get(0).amount.to_u64().unwrap(), - removed_locked_token_amount.to_u64().unwrap() - ); - assert_eq!( - output_vec.get(1).amount.to_u64().unwrap(), - removed_other_token_amount.to_u64().unwrap() - ); - assert_eq!(output_vec.get(2).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/simple-lock/tests/simple_lock_test_setup/mod.rs b/locked-asset/simple-lock/tests/simple_lock_test_setup/mod.rs deleted file mode 100644 index 92f145fba..000000000 --- a/locked-asset/simple-lock/tests/simple_lock_test_setup/mod.rs +++ /dev/null @@ -1,365 +0,0 @@ -#![allow(dead_code)] -#![allow(deprecated)] - -use common_structs::FarmTokenAttributes; -use multiversx_sc::codec::multi_types::OptionalValue; -use multiversx_sc::storage::mappers::StorageTokenWrapper; -use multiversx_sc::types::{Address, EsdtLocalRole, ManagedAddress, MultiValueEncoded}; -use multiversx_sc_scenario::whitebox_legacy::{TxContextStack, TxTokenTransfer}; -use multiversx_sc_scenario::{ - managed_address, managed_biguint, managed_token_id, rust_biguint, whitebox_legacy::*, DebugApi, -}; - -type RustBigUint = num_bigint::BigUint; - -use config::*; -use farm::exit_penalty::ExitPenaltyModule; -use farm::*; -use farm_boosted_yields::boosted_yields_factors::BoostedYieldsFactorsModule; -use farm_token::FarmTokenModule; -use pausable::{PausableModule, State}; - -// General -pub static MEX_TOKEN_ID: &[u8] = b"MEX-123456"; -pub static WEGLD_TOKEN_ID: &[u8] = b"WEGLD-123456"; -pub const EPOCHS_IN_YEAR: u64 = 360; -pub const USER_BALANCE: u64 = 1_000_000_000_000_000_000; - -// Pair -pub static LP_TOKEN_ID: &[u8] = b"LPTOK-123456"; - -// Farm -pub static FARM_LOCKED_TOKEN_ID: &[u8] = b"FARML-123456"; -pub const DIVISION_SAFETY_CONSTANT: u64 = 1_000_000_000_000_000_000; -pub const PER_BLOCK_REWARD_AMOUNT: u64 = 5_000; -pub const USER_REWARDS_BASE_CONST: u64 = 10; -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; - -// Simple Lock -pub static LOCKED_TOKEN_ID: &[u8] = b"LOCKED-123456"; -pub static LEGACY_LOCKED_TOKEN_ID: &[u8] = b"LEGACY-123456"; -pub static LOCK_OPTIONS: &[u64] = &[EPOCHS_IN_YEAR, 5 * EPOCHS_IN_YEAR, 10 * EPOCHS_IN_YEAR]; // 1, 5 or 10 years -pub static PENALTY_PERCENTAGES: &[u64] = &[4_000, 6_000, 8_000]; - -// Proxy -pub static WRAPPED_LP_TOKEN_ID: &[u8] = b"WPLP-123456"; -pub static WRAPPED_FARM_TOKEN_ID: &[u8] = b"WPFARM-123456"; - -pub struct SimpleLockSetup -where - SimpleLockObjBuilder: 'static + Copy + Fn() -> simple_lock::ContractObj, - PairObjBuilder: 'static + Copy + Fn() -> pair::ContractObj, - FarmLockedObjBuilder: 'static + Copy + Fn() -> farm_with_locked_rewards::ContractObj, -{ - pub b_mock: BlockchainStateWrapper, - pub owner: Address, - pub first_user: Address, - pub second_user: Address, - pub simple_lock_wrapper: - ContractObjWrapper, SimpleLockObjBuilder>, - pub pair_wrapper: ContractObjWrapper, PairObjBuilder>, - pub farm_locked_wrapper: - ContractObjWrapper, FarmLockedObjBuilder>, -} - -impl - SimpleLockSetup -where - SimpleLockObjBuilder: 'static + Copy + Fn() -> simple_lock::ContractObj, - PairObjBuilder: 'static + Copy + Fn() -> pair::ContractObj, - FarmLockedObjBuilder: 'static + Copy + Fn() -> farm_with_locked_rewards::ContractObj, -{ - pub fn new(farm_builder: SimpleLockObjBuilder) -> Self { - let rust_zero = rust_biguint!(0u64); - let mut blockchain_wrapper = BlockchainStateWrapper::new(); - let owner_addr = blockchain_wrapper.create_user_account(&rust_zero); - let farm_wrapper = blockchain_wrapper.create_sc_account( - &rust_zero, - Some(&owner_addr), - farm_builder, - FARM_WASM_PATH, - ); - - // init farm contract - - blockchain_wrapper - .execute_tx(&owner_addr, &farm_wrapper, &rust_zero, |sc| { - let reward_token_id = managed_token_id!(MEX_TOKEN_ID); - let farming_token_id = managed_token_id!(LP_TOKEN_ID); - let division_safety_constant = managed_biguint!(DIVISION_SAFETY_CONSTANT); - let pair_address = managed_address!(&Address::zero()); - - sc.init( - reward_token_id, - farming_token_id, - division_safety_constant, - pair_address, - ManagedAddress::::zero(), - MultiValueEncoded::new(), - ); - - let farm_token_id = managed_token_id!(FARM_TOKEN_ID); - sc.farm_token().set_token_id(farm_token_id); - - sc.per_block_reward_amount() - .set(&managed_biguint!(PER_BLOCK_REWARD_AMOUNT)); - sc.minimum_farming_epochs().set(MIN_FARMING_EPOCHS); - sc.penalty_percent().set(PENALTY_PERCENT); - - sc.state().set(State::Active); - sc.produce_rewards_enabled().set(true); - }) - .assert_ok(); - - blockchain_wrapper - .execute_tx(&owner_addr, &farm_wrapper, &rust_biguint!(0), |sc| { - sc.set_boosted_yields_factors( - managed_biguint!(MAX_REWARDS_FACTOR), - managed_biguint!(USER_REWARDS_ENERGY_CONST), - managed_biguint!(USER_REWARDS_FARM_CONST), - managed_biguint!(MIN_ENERGY_AMOUNT_FOR_BOOSTED_YIELDS), - managed_biguint!(MIN_FARM_AMOUNT_FOR_BOOSTED_YIELDS), - ); - }) - .assert_ok(); - - let farm_token_roles = [ - EsdtLocalRole::NftCreate, - EsdtLocalRole::NftAddQuantity, - EsdtLocalRole::NftBurn, - ]; - blockchain_wrapper.set_esdt_local_roles( - farm_wrapper.address_ref(), - FARM_TOKEN_ID, - &farm_token_roles[..], - ); - - let farming_token_roles = [EsdtLocalRole::Burn]; - blockchain_wrapper.set_esdt_local_roles( - farm_wrapper.address_ref(), - LP_TOKEN_ID, - &farming_token_roles[..], - ); - - let reward_token_roles = [EsdtLocalRole::Mint]; - blockchain_wrapper.set_esdt_local_roles( - farm_wrapper.address_ref(), - MEX_TOKEN_ID, - &reward_token_roles[..], - ); - - let user_addr = blockchain_wrapper.create_user_account(&rust_biguint!(100_000_000)); - blockchain_wrapper.set_esdt_balance( - &user_addr, - LP_TOKEN_ID, - &rust_biguint!(USER_TOTAL_LP_TOKENS), - ); - - SingleUserFarmSetup { - blockchain_wrapper, - owner_address: owner_addr, - user_address: user_addr, - farm_wrapper, - } - } - - pub fn enter_farm( - &mut self, - farm_in_amount: u64, - additional_farm_tokens: &[TxTokenTransfer], - expected_farm_token_nonce: u64, - expected_reward_per_share: u64, - expected_entering_epoch: u64, - expected_compounded_reward: u64, - ) { - let mut payments = Vec::with_capacity(1 + additional_farm_tokens.len()); - payments.push(TxTokenTransfer { - token_identifier: LP_TOKEN_ID.to_vec(), - nonce: 0, - value: rust_biguint!(farm_in_amount), - }); - payments.extend_from_slice(additional_farm_tokens); - - let mut expected_total_out_amount = 0; - for payment in payments.iter() { - expected_total_out_amount += payment.value.to_u64_digits()[0]; - } - - let b_mock = &mut self.blockchain_wrapper; - b_mock - .execute_esdt_multi_transfer(&self.user_address, &self.farm_wrapper, &payments, |sc| { - let enter_farm_result = sc.enter_farm_endpoint(OptionalValue::None); - let (out_farm_token, _reward_token) = enter_farm_result.into_tuple(); - assert_eq!( - out_farm_token.token_identifier, - managed_token_id!(FARM_TOKEN_ID) - ); - assert_eq!(out_farm_token.token_nonce, expected_farm_token_nonce); - assert_eq!( - out_farm_token.amount, - managed_biguint!(expected_total_out_amount) - ); - }) - .assert_ok(); - - DebugApi::dummy(); - - let expected_attributes = FarmTokenAttributes:: { - reward_per_share: managed_biguint!(expected_reward_per_share), - entering_epoch: expected_entering_epoch, - compounded_reward: managed_biguint!(expected_compounded_reward), - current_farm_amount: managed_biguint!(expected_total_out_amount), - original_owner: managed_address!(&self.user_address), - }; - b_mock.check_nft_balance( - &self.user_address, - FARM_TOKEN_ID, - expected_farm_token_nonce, - &rust_biguint!(expected_total_out_amount), - Some(&expected_attributes), - ); - - let _ = TxContextStack::static_pop(); - } - - pub fn exit_farm( - &mut self, - farm_token_amount: u64, - farm_token_nonce: u64, - expected_mex_out: u64, - expected_farm_token_amount: u64, - expected_user_mex_balance: &RustBigUint, - expected_user_lp_token_balance: &RustBigUint, - ) { - let b_mock = &mut self.blockchain_wrapper; - b_mock - .execute_esdt_transfer( - &self.user_address, - &self.farm_wrapper, - FARM_TOKEN_ID, - farm_token_nonce, - &rust_biguint!(farm_token_amount), - |sc| { - let multi_result = sc.exit_farm_endpoint(OptionalValue::None); - - let (first_result, second_result) = multi_result.into_tuple(); - - assert_eq!( - first_result.token_identifier, - managed_token_id!(LP_TOKEN_ID) - ); - assert_eq!(first_result.token_nonce, 0); - assert_eq!( - first_result.amount, - managed_biguint!(expected_farm_token_amount) - ); - - assert_eq!( - second_result.token_identifier, - managed_token_id!(MEX_TOKEN_ID) - ); - assert_eq!(second_result.token_nonce, 0); - assert_eq!(second_result.amount, managed_biguint!(expected_mex_out)); - }, - ) - .assert_ok(); - - b_mock.check_esdt_balance(&self.user_address, MEX_TOKEN_ID, expected_user_mex_balance); - b_mock.check_esdt_balance( - &self.user_address, - LP_TOKEN_ID, - expected_user_lp_token_balance, - ); - } - - #[allow(clippy::too_many_arguments)] - pub fn claim_rewards( - &mut self, - farm_token_amount: u64, - farm_token_nonce: u64, - expected_mex_out: u64, - expected_user_mex_balance: &RustBigUint, - expected_user_lp_token_balance: &RustBigUint, - expected_farm_token_nonce_out: u64, - expected_reward_per_share: u64, - ) { - let b_mock = &mut self.blockchain_wrapper; - b_mock - .execute_esdt_transfer( - &self.user_address, - &self.farm_wrapper, - FARM_TOKEN_ID, - farm_token_nonce, - &rust_biguint!(farm_token_amount), - |sc| { - let multi_result = sc.claim_rewards_endpoint(OptionalValue::None); - - let (first_result, second_result) = multi_result.into_tuple(); - - assert_eq!( - first_result.token_identifier, - managed_token_id!(FARM_TOKEN_ID) - ); - assert_eq!(first_result.token_nonce, expected_farm_token_nonce_out); - assert_eq!(first_result.amount, managed_biguint!(farm_token_amount)); - - assert_eq!( - second_result.token_identifier, - managed_token_id!(MEX_TOKEN_ID) - ); - assert_eq!(second_result.token_nonce, 0); - assert_eq!(second_result.amount, managed_biguint!(expected_mex_out)); - }, - ) - .assert_ok(); - - DebugApi::dummy(); - let expected_attributes = FarmTokenAttributes:: { - reward_per_share: managed_biguint!(expected_reward_per_share), - entering_epoch: 0, - compounded_reward: managed_biguint!(0), - current_farm_amount: managed_biguint!(farm_token_amount), - original_owner: managed_address!(&self.user_address), - }; - - b_mock.check_nft_balance( - &self.user_address, - FARM_TOKEN_ID, - expected_farm_token_nonce_out, - &rust_biguint!(farm_token_amount), - Some(&expected_attributes), - ); - b_mock.check_esdt_balance(&self.user_address, MEX_TOKEN_ID, expected_user_mex_balance); - b_mock.check_esdt_balance( - &self.user_address, - LP_TOKEN_ID, - expected_user_lp_token_balance, - ); - - let _ = TxContextStack::static_pop(); - } - - pub fn check_farm_token_supply(&mut self, expected_farm_token_supply: u64) { - let b_mock = &mut self.blockchain_wrapper; - b_mock - .execute_query(&self.farm_wrapper, |sc| { - let actual_farm_supply = sc.farm_token_supply().get(); - assert_eq!( - managed_biguint!(expected_farm_token_supply), - actual_farm_supply - ); - }) - .assert_ok(); - } - - pub fn set_block_nonce(&mut self, block_nonce: u64) { - self.blockchain_wrapper.set_block_nonce(block_nonce); - } - - pub fn set_block_epoch(&mut self, block_epoch: u64) { - self.blockchain_wrapper.set_block_epoch(block_epoch); - } -} From ea688d7da250a55dc2b25188d8d1fb4ab130e3b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Tue, 20 Feb 2024 13:36:15 +0200 Subject: [PATCH 14/21] Fix clippy --- energy-integration/governance-v2/tests/gov_rust_test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/energy-integration/governance-v2/tests/gov_rust_test.rs b/energy-integration/governance-v2/tests/gov_rust_test.rs index bd9dcbf17..342655adf 100644 --- a/energy-integration/governance-v2/tests/gov_rust_test.rs +++ b/energy-integration/governance-v2/tests/gov_rust_test.rs @@ -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())); From 39cefd6953f3db9810d2d7310a75402877c88e46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Thu, 22 Feb 2024 12:12:09 +0200 Subject: [PATCH 15/21] Fixes after review --- dex/farm/tests/farm_single_user_test.rs | 17 +++-- locked-asset/proxy_dex/src/proxy_farm.rs | 23 +++++-- .../proxy_dex/tests/proxy_farm_test.rs | 9 +-- locked-asset/simple-lock/src/proxy_farm.rs | 65 +++++++------------ 4 files changed, 56 insertions(+), 58 deletions(-) diff --git a/dex/farm/tests/farm_single_user_test.rs b/dex/farm/tests/farm_single_user_test.rs index f1262efe0..5cef9bf08 100644 --- a/dex/farm/tests/farm_single_user_test.rs +++ b/dex/farm/tests/farm_single_user_test.rs @@ -849,19 +849,24 @@ fn test_destroy_farm_through_simple_lock() { let claim_result = sc.destroy_farm_locked_tokens(managed_biguint!(1), managed_biguint!(1)); - let (first_token_payment_out, second_token_payment_out) = claim_result.into_tuple(); - assert_eq!( - first_token_payment_out.token_identifier, + claim_result.first_payment.token_identifier, managed_token_id!(WEGLD_TOKEN_ID) ); - assert_eq!(first_token_payment_out.amount, managed_biguint!(9_999_000)); + assert_eq!(claim_result.first_payment.amount, managed_biguint!(9_999_000)); assert_eq!( - second_token_payment_out.token_identifier, + claim_result.second_payment.token_identifier, managed_token_id!(LOCKED_TOKEN_ID) ); - assert_eq!(second_token_payment_out.amount, managed_biguint!(9_999_000)); + 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 b642da727..a911d1e56 100644 --- a/locked-asset/proxy_dex/src/proxy_farm.rs +++ b/locked-asset/proxy_dex/src/proxy_farm.rs @@ -22,6 +22,14 @@ 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 @@ -243,7 +251,8 @@ pub trait ProxyFarmModule: first_token_amount_min: BigUint, second_token_amount_min: BigUint, opt_original_caller: OptionalValue, - ) -> MultiValueEncoded { + ) -> DestroyFarmResultType { + self.require_is_intermediated_farm(&farm_address); self.require_wrapped_farm_token_id_not_empty(); self.require_wrapped_lp_token_id_not_empty(); @@ -282,7 +291,7 @@ pub trait ProxyFarmModule: exit_result.farming_tokens.amount, ); - let mut output_payments = self.remove_liquidity_proxy_common( + let mut remove_liquidity_result = self.remove_liquidity_proxy_common( initial_proxy_farming_tokens.clone(), pair_address, first_token_amount_min, @@ -293,9 +302,9 @@ pub trait ProxyFarmModule: wrapped_farm_token_mapper.nft_burn(payment.token_nonce, &payment.amount); // Push farm rewards - output_payments.push(exit_result.reward_tokens.clone()); + remove_liquidity_result.push(exit_result.reward_tokens.clone()); - self.send_multiple_tokens_if_not_zero(&caller, &output_payments); + self.send_multiple_tokens_if_not_zero(&caller, &remove_liquidity_result); self.emit_exit_farm_proxy_event( &original_caller, @@ -305,7 +314,11 @@ pub trait ProxyFarmModule: exit_result.reward_tokens.clone(), ); - output_payments.into() + 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( diff --git a/locked-asset/proxy_dex/tests/proxy_farm_test.rs b/locked-asset/proxy_dex/tests/proxy_farm_test.rs index 9018b972c..c4bc87b70 100644 --- a/locked-asset/proxy_dex/tests/proxy_farm_test.rs +++ b/locked-asset/proxy_dex/tests/proxy_farm_test.rs @@ -1617,18 +1617,15 @@ fn destroy_farm_locked_tokens_test() { OptionalValue::None, ); - let output_vec = output_payments.to_vec(); - - assert_eq!(output_payments.len(), 3); assert_eq!( - output_vec.get(0).amount.to_u64().unwrap(), + output_payments.first_payment.amount.to_u64().unwrap(), removed_locked_token_amount.to_u64().unwrap() ); assert_eq!( - output_vec.get(1).amount.to_u64().unwrap(), + output_payments.second_payment.amount.to_u64().unwrap(), removed_other_token_amount.to_u64().unwrap() ); - assert_eq!(output_vec.get(2).amount.to_u64().unwrap(), 0u64); + assert_eq!(output_payments.farm_rewards.amount.to_u64().unwrap(), 0u64); }, ) .assert_ok(); diff --git a/locked-asset/simple-lock/src/proxy_farm.rs b/locked-asset/simple-lock/src/proxy_farm.rs index 5932e26a2..c84c2270e 100644 --- a/locked-asset/simple-lock/src/proxy_farm.rs +++ b/locked-asset/simple-lock/src/proxy_farm.rs @@ -1,9 +1,7 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); -use crate::{ - error_messages::*, locked_token::PreviousStatusFlag, proxy_lp::LpProxyTokenAttributes, -}; +use crate::{error_messages::*, proxy_lp::LpProxyTokenAttributes}; #[derive( TypeAbi, TopEncode, TopDecode, NestedEncode, NestedDecode, PartialEq, Debug, Clone, Copy, @@ -28,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 @@ -263,7 +268,7 @@ pub trait ProxyFarmModule: &self, first_token_min_amount_out: BigUint, second_token_min_amount_out: BigUint, - ) -> ExitFarmThroughProxyResultType { + ) -> DestroyFarmResultType { let payment: EsdtTokenPayment = self.call_value().single_esdt(); let farm_proxy_token_attributes: FarmProxyTokenAttributes = @@ -278,7 +283,7 @@ pub trait ProxyFarmModule: farm_address, farm_proxy_token_attributes.farm_token_id, farm_proxy_token_attributes.farm_token_nonce, - payment.amount, + payment.amount.clone(), caller.clone(), ); require!( @@ -296,45 +301,23 @@ pub trait ProxyFarmModule: ); } - let initial_farming_tokens = exit_farm_result.initial_farming_tokens; - - // get LOCKED_LP nonce - let locked_lp_nonce = farm_proxy_token_attributes.farming_token_locked_nonce; - let lp_proxy_token_mapper = self.lp_proxy_token(); - let lp_proxy_token_attributes: LpProxyTokenAttributes = - lp_proxy_token_mapper.get_token_attributes(locked_lp_nonce); - - // get LP address - let lp_address = self - .lp_address_for_token_pair( - &lp_proxy_token_attributes.first_token_id, - &lp_proxy_token_attributes.second_token_id, + let (first_payment, second_payment) = self + .remove_liquidity_locked_token_common( + exit_farm_result.initial_farming_tokens, + first_token_min_amount_out, + second_token_min_amount_out, ) - .get(); - - let remove_liq_result = self.call_pair_remove_liquidity( - lp_address, - lp_proxy_token_attributes.lp_token_id, - initial_farming_tokens.amount, - first_token_min_amount_out, - second_token_min_amount_out, - &lp_proxy_token_attributes.first_token_id, - &lp_proxy_token_attributes.second_token_id, - ); + .into_tuple(); - let caller = self.blockchain().get_caller(); - let first_token_result_payment = self.send_tokens_optimal_status( - &caller, - remove_liq_result.first_token_payment_out, - PreviousStatusFlag::new(lp_proxy_token_attributes.first_token_locked_nonce), - ); - let second_token_result_payment = self.send_tokens_optimal_status( - &caller, - remove_liq_result.second_token_payment_out, - PreviousStatusFlag::new(lp_proxy_token_attributes.second_token_locked_nonce), - ); + // Burn farm token + let farm_proxy_token_mapper = self.farm_proxy_token(); + farm_proxy_token_mapper.nft_burn(payment.token_nonce, &payment.amount); - (first_token_result_payment, second_token_result_payment).into() + DestroyFarmResultType { + first_payment, + second_payment, + farm_rewards: exit_farm_result.reward_tokens, + } } /// Claim rewards from a previously entered farm. From ce739aa1b7546b97443c910ae3e656408997d75d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Thu, 22 Feb 2024 15:16:41 +0200 Subject: [PATCH 16/21] destroy_farm_proxy: Check pair_address is legitimate --- locked-asset/proxy_dex/src/proxy_farm.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/locked-asset/proxy_dex/src/proxy_farm.rs b/locked-asset/proxy_dex/src/proxy_farm.rs index a911d1e56..cacc5db9c 100644 --- a/locked-asset/proxy_dex/src/proxy_farm.rs +++ b/locked-asset/proxy_dex/src/proxy_farm.rs @@ -254,6 +254,7 @@ pub trait ProxyFarmModule: ) -> DestroyFarmResultType { self.require_is_intermediated_farm(&farm_address); + self.require_is_intermediated_pair(&farm_address); self.require_wrapped_farm_token_id_not_empty(); self.require_wrapped_lp_token_id_not_empty(); From dad54239b0d9329b3c3ad500cc29ee3693b54aca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Thu, 22 Feb 2024 15:17:47 +0200 Subject: [PATCH 17/21] simple-lock/destroy_farm_locked_tokens: Burn farm proxy token --- locked-asset/simple-lock/src/proxy_farm.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/locked-asset/simple-lock/src/proxy_farm.rs b/locked-asset/simple-lock/src/proxy_farm.rs index c84c2270e..e03e20da2 100644 --- a/locked-asset/simple-lock/src/proxy_farm.rs +++ b/locked-asset/simple-lock/src/proxy_farm.rs @@ -345,7 +345,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!( @@ -357,6 +357,10 @@ pub trait ProxyFarmModule: farm_proxy_token_attributes.farm_token_nonce = claim_rewards_result.new_farm_tokens.token_nonce; + // Burn farm token + let farm_proxy_token_mapper = self.farm_proxy_token(); + farm_proxy_token_mapper.nft_burn(payment.token_nonce, &payment.amount); + let new_proxy_token_payment = self.farm_proxy_token().nft_create_and_send( &caller, claim_rewards_result.new_farm_tokens.amount, From adf0267446bbb474158e46eaf0e6fec193e09d89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Thu, 22 Feb 2024 15:19:56 +0200 Subject: [PATCH 18/21] Cargo format --- dex/farm/tests/farm_single_user_test.rs | 11 ++++++++--- locked-asset/proxy_dex/src/proxy_farm.rs | 6 ++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/dex/farm/tests/farm_single_user_test.rs b/dex/farm/tests/farm_single_user_test.rs index 5cef9bf08..6ff0a3d3a 100644 --- a/dex/farm/tests/farm_single_user_test.rs +++ b/dex/farm/tests/farm_single_user_test.rs @@ -853,14 +853,19 @@ fn test_destroy_farm_through_simple_lock() { 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.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.second_payment.amount, + managed_biguint!(9_999_000) + ); assert_eq!( claim_result.farm_rewards.token_identifier, diff --git a/locked-asset/proxy_dex/src/proxy_farm.rs b/locked-asset/proxy_dex/src/proxy_farm.rs index cacc5db9c..e64f39a36 100644 --- a/locked-asset/proxy_dex/src/proxy_farm.rs +++ b/locked-asset/proxy_dex/src/proxy_farm.rs @@ -29,7 +29,6 @@ pub struct DestroyFarmResultType { pub farm_rewards: EsdtTokenPayment, } - #[multiversx_sc::module] pub trait ProxyFarmModule: crate::proxy_common::ProxyCommonModule @@ -252,7 +251,6 @@ pub trait ProxyFarmModule: second_token_amount_min: BigUint, opt_original_caller: OptionalValue, ) -> DestroyFarmResultType { - self.require_is_intermediated_farm(&farm_address); self.require_is_intermediated_pair(&farm_address); self.require_wrapped_farm_token_id_not_empty(); @@ -315,10 +313,10 @@ pub trait ProxyFarmModule: exit_result.reward_tokens.clone(), ); - DestroyFarmResultType{ + DestroyFarmResultType { first_payment: remove_liquidity_result.get(0), second_payment: remove_liquidity_result.get(1), - farm_rewards: exit_result.reward_tokens + farm_rewards: exit_result.reward_tokens, } } From e76036559d97ddbc39ebb9a28c44b66165a62194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Thu, 22 Feb 2024 17:37:04 +0200 Subject: [PATCH 19/21] simple-lock: Remove burn of wrapped farm token from destroy and claim rewards --- locked-asset/proxy_dex/src/proxy_pair.rs | 8 ++++++++ locked-asset/simple-lock/src/proxy_farm.rs | 17 ++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/locked-asset/proxy_dex/src/proxy_pair.rs b/locked-asset/proxy_dex/src/proxy_pair.rs index 79542f06a..e580285e1 100644 --- a/locked-asset/proxy_dex/src/proxy_pair.rs +++ b/locked-asset/proxy_dex/src/proxy_pair.rs @@ -9,6 +9,14 @@ use crate::wrapped_lp_attributes::{WrappedLpToken, WrappedLpTokenAttributes}; use common_structs::Epoch; use fixed_supply_token::FixedSupplyToken; + +#[derive(TypeAbi, TopEncode, TopDecode, NestedEncode, NestedDecode)] +pub struct RemoveLiquidityProxyCommon { + pub first_payment: EsdtTokenPayment, + pub second_payment: EsdtTokenPayment, + pub farm_rewards: EsdtTokenPayment, +} + #[multiversx_sc::module] pub trait ProxyPairModule: crate::proxy_common::ProxyCommonModule diff --git a/locked-asset/simple-lock/src/proxy_farm.rs b/locked-asset/simple-lock/src/proxy_farm.rs index e03e20da2..33184ca3f 100644 --- a/locked-asset/simple-lock/src/proxy_farm.rs +++ b/locked-asset/simple-lock/src/proxy_farm.rs @@ -301,18 +301,21 @@ pub trait ProxyFarmModule: ); } + 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( - exit_farm_result.initial_farming_tokens, + 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(); - // Burn farm token - let farm_proxy_token_mapper = self.farm_proxy_token(); - farm_proxy_token_mapper.nft_burn(payment.token_nonce, &payment.amount); - DestroyFarmResultType { first_payment, second_payment, @@ -357,10 +360,6 @@ pub trait ProxyFarmModule: farm_proxy_token_attributes.farm_token_nonce = claim_rewards_result.new_farm_tokens.token_nonce; - // Burn farm token - let farm_proxy_token_mapper = self.farm_proxy_token(); - farm_proxy_token_mapper.nft_burn(payment.token_nonce, &payment.amount); - let new_proxy_token_payment = self.farm_proxy_token().nft_create_and_send( &caller, claim_rewards_result.new_farm_tokens.amount, From f865799617bef6673b99711ec5e128193ddbdbb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Thu, 22 Feb 2024 17:51:49 +0200 Subject: [PATCH 20/21] Small fix --- locked-asset/proxy_dex/src/proxy_farm.rs | 2 +- locked-asset/proxy_dex/tests/proxy_farm_test.rs | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/locked-asset/proxy_dex/src/proxy_farm.rs b/locked-asset/proxy_dex/src/proxy_farm.rs index e64f39a36..1064a1708 100644 --- a/locked-asset/proxy_dex/src/proxy_farm.rs +++ b/locked-asset/proxy_dex/src/proxy_farm.rs @@ -252,7 +252,7 @@ pub trait ProxyFarmModule: opt_original_caller: OptionalValue, ) -> DestroyFarmResultType { self.require_is_intermediated_farm(&farm_address); - self.require_is_intermediated_pair(&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(); diff --git a/locked-asset/proxy_dex/tests/proxy_farm_test.rs b/locked-asset/proxy_dex/tests/proxy_farm_test.rs index c4bc87b70..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; From 31779fa682585264e3af07376cd9d2e31f4774b7 Mon Sep 17 00:00:00 2001 From: Sorin Petreasca Date: Tue, 27 Feb 2024 16:34:42 +0200 Subject: [PATCH 21/21] remove RemoveLiquidityProxyCommon struct --- locked-asset/proxy_dex/src/proxy_pair.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/locked-asset/proxy_dex/src/proxy_pair.rs b/locked-asset/proxy_dex/src/proxy_pair.rs index e580285e1..79542f06a 100644 --- a/locked-asset/proxy_dex/src/proxy_pair.rs +++ b/locked-asset/proxy_dex/src/proxy_pair.rs @@ -9,14 +9,6 @@ use crate::wrapped_lp_attributes::{WrappedLpToken, WrappedLpTokenAttributes}; use common_structs::Epoch; use fixed_supply_token::FixedSupplyToken; - -#[derive(TypeAbi, TopEncode, TopDecode, NestedEncode, NestedDecode)] -pub struct RemoveLiquidityProxyCommon { - pub first_payment: EsdtTokenPayment, - pub second_payment: EsdtTokenPayment, - pub farm_rewards: EsdtTokenPayment, -} - #[multiversx_sc::module] pub trait ProxyPairModule: crate::proxy_common::ProxyCommonModule