diff --git a/Cargo.lock b/Cargo.lock index 97f3c2e89..04e8e5188 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -757,6 +757,26 @@ dependencies = [ "multiversx-sc-meta", ] +[[package]] +name = "factory-legacy" +version = "0.0.0" +dependencies = [ + "common_errors", + "common_structs", + "multiversx-sc", + "multiversx-sc-modules", + "multiversx-sc-scenario", + "token_merge_helper", +] + +[[package]] +name = "factory-legacy-meta" +version = "0.0.0" +dependencies = [ + "factory-legacy", + "multiversx-sc-meta", +] + [[package]] name = "farm" version = "0.0.0" @@ -2247,7 +2267,7 @@ name = "proxy-dex-legacy" version = "0.0.0" dependencies = [ "common_structs", - "factory", + "factory-legacy", "multiversx-sc", "multiversx-sc-scenario", "token_merge_helper", diff --git a/Cargo.toml b/Cargo.toml index db13e51b2..7a6041dc6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,8 @@ members = [ "legacy-contracts/farm-v-13/meta", "legacy-contracts/proxy-dex-legacy", "legacy-contracts/proxy-dex-legacy/meta", + "legacy-contracts/factory-legacy", + "legacy-contracts/factory-legacy/meta", "locked-asset/", "locked-asset/distribution", diff --git a/legacy-contracts/factory-legacy/.gitignore b/legacy-contracts/factory-legacy/.gitignore new file mode 100644 index 000000000..eaf5915bd --- /dev/null +++ b/legacy-contracts/factory-legacy/.gitignore @@ -0,0 +1,7 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ +*/target/ + +# The erdpy output +output diff --git a/legacy-contracts/factory-legacy/Cargo.toml b/legacy-contracts/factory-legacy/Cargo.toml new file mode 100644 index 000000000..bff8b6fa4 --- /dev/null +++ b/legacy-contracts/factory-legacy/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "factory-legacy" +publish = false +version = "0.0.0" +edition = "2018" + +[lib] +path = "src/lib.rs" + +[dependencies.multiversx-sc] +version = "=0.50.5" +features = ["esdt-token-payment-legacy-decode"] + +[dependencies.multiversx-sc-modules] +version = "=0.50.5" + +[dev-dependencies.multiversx-sc-scenario] +version = "=0.50.5" + +[dependencies.common_structs] +path = "../../common/common_structs" + +[dependencies.common_errors] +path = "../../common/common_errors" + +[dependencies.token_merge_helper] +path = "../../common/modules/token_merge_helper" \ No newline at end of file diff --git a/legacy-contracts/factory-legacy/README.md b/legacy-contracts/factory-legacy/README.md new file mode 100644 index 000000000..b61d85ad8 --- /dev/null +++ b/legacy-contracts/factory-legacy/README.md @@ -0,0 +1,26 @@ +# Locked Asset Factory Smart Contract + +This document presents how one can deploy and configure a Locked Asset Factory Contract. +The bigger picture about what a Locked Asset Factory Contract can do can be found in the Repository's Root Readme. + +## Deployment + +The Locked Asset Factory contract can be deployed using `erdpy` and using the interraction snippets. + +The init parameters are: + +- asset_token_id. The TokenId of the asset that a locked asset represents. In case of Maiar Exchange it will be MEX. + +- default_unlock_period. A vector of unlock milestones. This represents a period since each epoch in the vector will be added with a starting epoch. + +The Contract requires LocalMint and LocalBurn for asset token. + +## Creating and Forwarding SFTs + +Before creating LockedAssetLockens, the owner has to issue those tokens using `issueLockedAssetToken` and after this he also has to give the NftCreate, NftAddQuantity and NftBurn roles to the contract unsing `setLocalRolesLockedAssetToken`. + +The Contract has an endpoint `createAndForward` that can be called in order to request an amount of Locked MEX. Only those addresses in the `whitelisted_contracts` set can call this endpoint. This whitelist can be configured by the admin using `whitelist` and `removeWhitelist` endpoints. + +## Unlocking MEX + +A user that has Locked MEX can unlock it and can receive the Locked MEX "remaining" and the unlocked MEX amount. The newly created Locked MEX will have its unlock milestones re-calculated such that the percents unlocking schedule will be updated to the new locked amount. For example: if default_unlock_period is `0x000000000000000232`, `0x000000000000000432` it would mean that after `0000000000000002` epochs, should unlock `32`.to_dec() (`50`) percent of the amount. After the first unlock at epoch 3 let's say, the next unlock milestone will be recalculated as `0x000000000000000464`. Notice the `50%` become `100%`. diff --git a/legacy-contracts/factory-legacy/meta/Cargo.toml b/legacy-contracts/factory-legacy/meta/Cargo.toml new file mode 100644 index 000000000..01027f67e --- /dev/null +++ b/legacy-contracts/factory-legacy/meta/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "factory-legacy-meta" + +version = "0.0.0" +authors = [ "you",] +edition = "2018" +publish = false + +[dependencies.factory-legacy] +path = ".." + +[dependencies.multiversx-sc-meta] +version = "0.50.5" +default-features = false \ No newline at end of file diff --git a/legacy-contracts/factory-legacy/meta/src/main.rs b/legacy-contracts/factory-legacy/meta/src/main.rs new file mode 100644 index 000000000..64a2b3bb3 --- /dev/null +++ b/legacy-contracts/factory-legacy/meta/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + multiversx_sc_meta::cli_main::(); +} \ No newline at end of file diff --git a/legacy-contracts/factory-legacy/multiversx.json b/legacy-contracts/factory-legacy/multiversx.json new file mode 100644 index 000000000..c2cab7433 --- /dev/null +++ b/legacy-contracts/factory-legacy/multiversx.json @@ -0,0 +1,4 @@ +{ + "language": "rust" +} + diff --git a/legacy-contracts/factory-legacy/src/attr_ex_helper.rs b/legacy-contracts/factory-legacy/src/attr_ex_helper.rs new file mode 100644 index 000000000..322bb0b73 --- /dev/null +++ b/legacy-contracts/factory-legacy/src/attr_ex_helper.rs @@ -0,0 +1,68 @@ +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); + +use common_structs::LockedAssetTokenAttributes; +use common_structs::LockedAssetTokenAttributesEx; +use common_structs::UnlockMilestoneEx; +use common_structs::UnlockScheduleEx; + +// 1% = 1_000; +pub const _PRECISION_EXTENDED: u64 = 100_000u64; + +// From 1 to 1_000; +pub const PRECISION_EX_INCREASE: u64 = 1_000u64; + +#[multiversx_sc::module] +pub trait AttrExHelper { + fn get_attributes_ex( + &self, + token_id: &TokenIdentifier, + token_nonce: u64, + attr_ex_activation: u64, + ) -> LockedAssetTokenAttributesEx { + let token_info = self.blockchain().get_esdt_token_data( + &self.blockchain().get_sc_address(), + token_id, + token_nonce, + ); + + if token_nonce < attr_ex_activation { + let attr = self + .serializer() + .top_decode_from_managed_buffer::>( + &token_info.attributes, + ); + self.convert_attr_to_attr_ex(&attr) + } else { + self.serializer() + .top_decode_from_managed_buffer::>( + &token_info.attributes, + ) + } + } + + fn convert_attr_to_attr_ex( + &self, + attr: &LockedAssetTokenAttributes, + ) -> LockedAssetTokenAttributesEx { + let mut new_milestones: ManagedVec = ManagedVec::new(); + + for milestones in attr.unlock_schedule.unlock_milestones.iter() { + new_milestones.push(UnlockMilestoneEx { + unlock_epoch: milestones.unlock_epoch, + unlock_percent: (milestones.unlock_percent as u64) * PRECISION_EX_INCREASE, + }); + } + + LockedAssetTokenAttributesEx { + unlock_schedule: UnlockScheduleEx { + unlock_milestones: new_milestones, + }, + is_merged: attr.is_merged, + } + } + + #[view(getExtendedAttributesActivationNonce)] + #[storage_mapper("extended_attributes_activation_nonce")] + fn extended_attributes_activation_nonce(&self) -> SingleValueMapper; +} diff --git a/legacy-contracts/factory-legacy/src/cache.rs b/legacy-contracts/factory-legacy/src/cache.rs new file mode 100644 index 000000000..24d1a031d --- /dev/null +++ b/legacy-contracts/factory-legacy/src/cache.rs @@ -0,0 +1,49 @@ +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); + +use common_structs::{Nonce, UnlockScheduleEx}; + +use crate::attr_ex_helper; + +use super::locked_asset; + +#[multiversx_sc::module] +pub trait CacheModule: locked_asset::LockedAssetModule + attr_ex_helper::AttrExHelper { + #[inline(always)] + fn get_sft_nonce_for_unlock_schedule( + &self, + unlock_schedule: &UnlockScheduleEx, + ) -> Option { + self.nonce_cache_ex().get(unlock_schedule) + } + + #[view(getUnlockScheduleForSFTNonce)] + fn get_unlock_schedule_for_sft_nonce( + &self, + nonce: Nonce, + ) -> Option> { + self.unlock_schedule_cache_ex().get(&nonce) + } + + #[inline(always)] + fn cache_unlock_schedule_and_nonce( + &self, + unlock_schedule: &UnlockScheduleEx, + nonce: Nonce, + ) { + self.nonce_cache_ex().insert(unlock_schedule.clone(), nonce); + self.unlock_schedule_cache_ex() + .insert(nonce, unlock_schedule.clone()); + } + + #[view(getCacheSize)] + fn get_cache_size(&self) -> usize { + self.nonce_cache_ex().len() + } + + #[storage_mapper("nonce_cache_ex")] + fn nonce_cache_ex(&self) -> MapMapper, Nonce>; + + #[storage_mapper("unlock_schedule_cache_ex")] + fn unlock_schedule_cache_ex(&self) -> MapMapper>; +} diff --git a/legacy-contracts/factory-legacy/src/events.rs b/legacy-contracts/factory-legacy/src/events.rs new file mode 100644 index 000000000..149c7af5c --- /dev/null +++ b/legacy-contracts/factory-legacy/src/events.rs @@ -0,0 +1,123 @@ +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); + +use common_structs::LockedAssetTokenAttributesEx; + +#[derive(TypeAbi, TopEncode)] +pub struct CreateAndForwardEvent { + caller: ManagedAddress, + destination: ManagedAddress, + locked_asset_token_id: TokenIdentifier, + locked_asset_token_nonce: u64, + locked_asset_token_amount: BigUint, + locked_assets_attributes: LockedAssetTokenAttributesEx, + start_epoch: u64, + block: u64, + epoch: u64, + timestamp: u64, +} + +#[derive(TypeAbi, TopEncode)] +pub struct UnlockAssetsEvent { + caller: ManagedAddress, + input_locked_assets_token_id: TokenIdentifier, + input_locked_assets_token_nonce: u64, + input_locked_assets_token_amount: BigUint, + output_locked_assets_token_id: TokenIdentifier, + output_locked_assets_token_nonce: u64, + output_locked_assets_token_amount: BigUint, + asset_token_id: TokenIdentifier, + asset_token_amount: BigUint, + input_assets_attributes: LockedAssetTokenAttributesEx, + output_assets_attributes: LockedAssetTokenAttributesEx, + block: u64, + epoch: u64, + timestamp: u64, +} + +#[multiversx_sc::module] +pub trait EventsModule { + fn emit_create_and_forward_event( + self, + caller: &ManagedAddress, + destination: &ManagedAddress, + locked_asset_token_id: &TokenIdentifier, + locked_asset_token_nonce: u64, + locked_asset_token_amount: &BigUint, + locked_assets_attributes: &LockedAssetTokenAttributesEx, + start_epoch: u64, + ) { + let epoch = self.blockchain().get_block_epoch(); + self.create_and_forward_event( + caller, + destination, + epoch, + &CreateAndForwardEvent { + caller: caller.clone(), + destination: destination.clone(), + locked_asset_token_id: locked_asset_token_id.clone(), + locked_asset_token_nonce, + locked_asset_token_amount: locked_asset_token_amount.clone(), + locked_assets_attributes: locked_assets_attributes.clone(), + start_epoch, + block: self.blockchain().get_block_nonce(), + epoch, + timestamp: self.blockchain().get_block_timestamp(), + }, + ) + } + + fn emit_unlock_assets_event( + self, + caller: &ManagedAddress, + input_locked_assets_token_id: &TokenIdentifier, + input_locked_assets_token_nonce: u64, + input_locked_assets_token_amount: &BigUint, + output_locked_assets_token_id: &TokenIdentifier, + output_locked_assets_token_nonce: u64, + output_locked_assets_token_amount: &BigUint, + asset_token_id: &TokenIdentifier, + asset_token_amount: &BigUint, + input_assets_attributes: &LockedAssetTokenAttributesEx, + output_assets_attributes: &LockedAssetTokenAttributesEx, + ) { + let epoch = self.blockchain().get_block_epoch(); + self.unlock_assets_event( + caller, + epoch, + &UnlockAssetsEvent { + caller: caller.clone(), + input_locked_assets_token_id: input_locked_assets_token_id.clone(), + input_locked_assets_token_nonce, + input_locked_assets_token_amount: input_locked_assets_token_amount.clone(), + output_locked_assets_token_id: output_locked_assets_token_id.clone(), + output_locked_assets_token_nonce, + output_locked_assets_token_amount: output_locked_assets_token_amount.clone(), + asset_token_id: asset_token_id.clone(), + asset_token_amount: asset_token_amount.clone(), + input_assets_attributes: input_assets_attributes.clone(), + output_assets_attributes: output_assets_attributes.clone(), + block: self.blockchain().get_block_nonce(), + epoch, + timestamp: self.blockchain().get_block_timestamp(), + }, + ) + } + + #[event("create_and_forward")] + fn create_and_forward_event( + self, + #[indexed] caller: &ManagedAddress, + #[indexed] destination: &ManagedAddress, + #[indexed] epoch: u64, + swap_event: &CreateAndForwardEvent, + ); + + #[event("unlock_assets")] + fn unlock_assets_event( + self, + #[indexed] caller: &ManagedAddress, + #[indexed] epoch: u64, + swap_event: &UnlockAssetsEvent, + ); +} diff --git a/legacy-contracts/factory-legacy/src/lib.rs b/legacy-contracts/factory-legacy/src/lib.rs new file mode 100644 index 000000000..56449f8d1 --- /dev/null +++ b/legacy-contracts/factory-legacy/src/lib.rs @@ -0,0 +1,363 @@ +#![no_std] + +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); + +use attr_ex_helper::PRECISION_EX_INCREASE; +use common_structs::{ + Epoch, LockedAssetTokenAttributesEx, UnlockMilestoneEx, UnlockPeriod, UnlockScheduleEx, +}; + +pub mod attr_ex_helper; +mod cache; +mod events; +pub mod locked_asset; +pub mod locked_asset_token_merge; +pub mod migration; + +const ADDITIONAL_AMOUNT_TO_CREATE: u64 = 1; +const EPOCHS_IN_MONTH: u64 = 30; + +#[derive(TypeAbi, TopEncode, TopDecode)] +pub struct OldEsdtTokenPayment { + pub token_type: EsdtTokenType, + pub payment: EsdtTokenPayment, +} + +impl OldEsdtTokenPayment { + pub fn new(payment: EsdtTokenPayment) -> Self { + Self { + token_type: payment.token_type(), + payment, + } + } +} + +#[multiversx_sc::contract] +pub trait LockedAssetFactory: + locked_asset::LockedAssetModule + + cache::CacheModule + + token_merge_helper::TokenMergeHelperModule + + locked_asset_token_merge::LockedAssetTokenMergeModule + + events::EventsModule + + attr_ex_helper::AttrExHelper + + migration::LockedTokenMigrationModule + + multiversx_sc_modules::pause::PauseModule +{ + #[init] + fn init(&self) { + self.set_paused(true); + } + + #[only_owner] + #[endpoint] + fn whitelist(&self, address: ManagedAddress) { + let is_new = self.whitelisted_contracts().insert(address); + require!(is_new, "ManagedAddress already whitelisted"); + } + + #[only_owner] + #[endpoint(removeWhitelist)] + fn remove_whitelist(&self, address: ManagedAddress) { + let is_removed = self.whitelisted_contracts().remove(&address); + require!(is_removed, "ManagedAddresss not whitelisted"); + } + + #[endpoint(createAndForwardCustomPeriod)] + fn create_and_forward_custom_period( + &self, + amount: BigUint, + address: ManagedAddress, + start_epoch: Epoch, + unlock_period: UnlockPeriod, + ) -> OldEsdtTokenPayment { + self.require_not_paused(); + + let caller = self.blockchain().get_caller(); + require!( + self.whitelisted_contracts().contains(&caller), + "Permission denied" + ); + require!(!unlock_period.unlock_milestones.is_empty(), "Empty arg"); + + let month_start_epoch = self.get_month_start_epoch(start_epoch); + let attr = LockedAssetTokenAttributesEx { + unlock_schedule: self.create_unlock_schedule(month_start_epoch, unlock_period), + is_merged: false, + }; + + let new_token = self.produce_tokens_and_send(&amount, &attr, &address); + + self.emit_create_and_forward_event( + &caller, + &address, + &new_token.token_identifier, + new_token.token_nonce, + &new_token.amount, + &attr, + month_start_epoch, + ); + + OldEsdtTokenPayment::new(new_token) + } + + #[endpoint(createAndForward)] + fn create_and_forward( + &self, + amount: BigUint, + address: ManagedAddress, + start_epoch: Epoch, + ) -> OldEsdtTokenPayment { + self.require_not_paused(); + + let caller = self.blockchain().get_caller(); + require!( + self.whitelisted_contracts().contains(&caller), + "Permission denied" + ); + require!( + !self.locked_asset_token_id().is_empty(), + "Locked Asset Token not registered" + ); + require!(amount > 0, "Zero input amount"); + + let month_start_epoch = self.get_month_start_epoch(start_epoch); + let unlock_period = self.default_unlock_period().get(); + let attr = LockedAssetTokenAttributesEx { + unlock_schedule: self.create_unlock_schedule(month_start_epoch, unlock_period), + is_merged: false, + }; + + let new_token = self.produce_tokens_and_send(&amount, &attr, &address); + + self.emit_create_and_forward_event( + &caller, + &address, + &new_token.token_identifier, + new_token.token_nonce, + &new_token.amount, + &attr, + start_epoch, + ); + + OldEsdtTokenPayment::new(new_token) + } + + #[payable("*")] + #[endpoint(unlockAssets)] + fn unlock_assets(&self) { + self.require_not_paused(); + + let (token_id, token_nonce, amount) = self.call_value().single_esdt().into_tuple(); + let locked_token_id = self.locked_asset_token_id().get(); + require!(token_id == locked_token_id, "Bad payment token"); + + let attr_ex_activation = self.extended_attributes_activation_nonce().get(); + let attributes = self.get_attributes_ex(&token_id, token_nonce, attr_ex_activation); + let unlock_schedule = &attributes.unlock_schedule; + + let month_start_epoch = self.get_month_start_epoch(self.blockchain().get_block_epoch()); + let unlock_amount = self.get_unlock_amount( + &amount, + month_start_epoch, + &unlock_schedule.unlock_milestones, + ); + require!(amount >= unlock_amount, "Cannot unlock more than locked"); + require!(unlock_amount > 0u64, "Method called too soon"); + + let caller = self.blockchain().get_caller(); + self.mint_and_send_assets(&caller, &unlock_amount); + + let mut output_locked_assets_token_amount = + EsdtTokenPayment::new(token_id.clone(), 0, BigUint::zero()); + let mut output_locked_asset_attributes = LockedAssetTokenAttributesEx { + unlock_schedule: UnlockScheduleEx { + unlock_milestones: ManagedVec::new(), + }, + is_merged: false, + }; + + let locked_remaining = &amount - &unlock_amount; + if locked_remaining > 0u64 { + let new_unlock_milestones = self.create_new_unlock_milestones( + month_start_epoch, + &unlock_schedule.unlock_milestones, + ); + output_locked_asset_attributes = LockedAssetTokenAttributesEx { + unlock_schedule: UnlockScheduleEx { + unlock_milestones: new_unlock_milestones, + }, + is_merged: attributes.is_merged, + }; + output_locked_assets_token_amount = self.produce_tokens_and_send( + &locked_remaining, + &output_locked_asset_attributes, + &caller, + ); + } + + self.send() + .esdt_local_burn(&locked_token_id, token_nonce, &amount); + + let initial_amounts_per_epoch = attributes.get_unlock_amounts_per_epoch(&amount); + let final_amounts_per_epoch = + output_locked_asset_attributes.get_unlock_amounts_per_epoch(&locked_remaining); + self.update_energy_after_unlock( + caller.clone(), + initial_amounts_per_epoch, + final_amounts_per_epoch, + ); + + self.emit_unlock_assets_event( + &caller, + &token_id, + token_nonce, + &amount, + &output_locked_assets_token_amount.token_identifier, + output_locked_assets_token_amount.token_nonce, + &output_locked_assets_token_amount.amount, + &self.asset_token_id().get(), + &unlock_amount, + &attributes, + &output_locked_asset_attributes, + ); + } + + fn get_month_start_epoch(&self, epoch: Epoch) -> Epoch { + epoch - (epoch - self.init_epoch().get()) % EPOCHS_IN_MONTH + } + + fn produce_tokens_and_send( + &self, + amount: &BigUint, + attributes: &LockedAssetTokenAttributesEx, + address: &ManagedAddress, + ) -> EsdtTokenPayment { + let result = self.get_sft_nonce_for_unlock_schedule(&attributes.unlock_schedule); + let sent_nonce = match result { + Option::Some(cached_nonce) => { + self.add_quantity_and_send_locked_assets(amount, cached_nonce, address); + cached_nonce + } + Option::None => { + let do_cache_result = !attributes.is_merged; + + let additional_amount_to_create = if do_cache_result { + BigUint::from(ADDITIONAL_AMOUNT_TO_CREATE) + } else { + BigUint::zero() + }; + + let new_nonce = self.create_and_send_locked_assets( + amount, + &additional_amount_to_create, + address, + attributes, + ); + + if do_cache_result { + self.cache_unlock_schedule_and_nonce(&attributes.unlock_schedule, new_nonce); + } + new_nonce + } + }; + + let token_id = self.locked_asset_token_id().get(); + EsdtTokenPayment::new(token_id, sent_nonce, amount.clone()) + } + + #[only_owner] + #[endpoint(setTransferRoleForAddress)] + fn set_transfer_role_for_address(&self, opt_address: OptionalValue) { + let address = match opt_address { + OptionalValue::Some(addr) => addr, + OptionalValue::None => self.blockchain().get_sc_address(), + }; + + self.send() + .esdt_system_sc_proxy() + .set_special_roles( + &address, + &self.locked_asset_token_id().get(), + [EsdtLocalRole::Transfer][..].iter().cloned(), + ) + .async_call_and_exit() + } + + #[only_owner] + #[endpoint(unsetTransferRoleForAddress)] + fn unset_transfer_role_for_address(&self, opt_address: OptionalValue) { + let address = match opt_address { + OptionalValue::Some(addr) => addr, + OptionalValue::None => self.blockchain().get_sc_address(), + }; + + self.send() + .esdt_system_sc_proxy() + .unset_special_roles( + &address, + &self.locked_asset_token_id().get(), + [EsdtLocalRole::Transfer][..].iter().cloned(), + ) + .async_call_and_exit() + } + + #[only_owner] + #[endpoint(setBurnRoleForAddress)] + fn set_burn_role_for_address(&self, opt_address: OptionalValue) { + let address = match opt_address { + OptionalValue::Some(addr) => addr, + OptionalValue::None => self.blockchain().get_sc_address(), + }; + + self.send() + .esdt_system_sc_proxy() + .set_special_roles( + &address, + &self.locked_asset_token_id().get(), + [EsdtLocalRole::NftBurn][..].iter().cloned(), + ) + .async_call_and_exit() + } + + fn create_unlock_schedule( + &self, + start_epoch: Epoch, + unlock_period: UnlockPeriod, + ) -> UnlockScheduleEx { + let mut result = ManagedVec::new(); + for milestone in unlock_period.unlock_milestones.iter() { + result.push(UnlockMilestoneEx { + unlock_epoch: milestone.unlock_epoch + start_epoch, + unlock_percent: milestone.unlock_percent as u64 * PRECISION_EX_INCREASE, + }); + } + UnlockScheduleEx { + unlock_milestones: result, + } + } + + #[view(getLastErrorMessage)] + #[storage_mapper("last_error_message")] + fn last_error_message(&self) -> SingleValueMapper; + + #[view(getInitEpoch)] + #[storage_mapper("init_epoch")] + fn init_epoch(&self) -> SingleValueMapper; + + #[storage_mapper("whitelist")] + fn whitelisted_contracts(&self) -> SetMapper; + + #[view(getWhitelistedContracts)] + fn get_whitelisted_contracts(&self) -> MultiValueEncoded { + let mut result = MultiValueEncoded::new(); + for pair in self.whitelisted_contracts().iter() { + result.push(pair); + } + result + } + + #[view(getDefaultUnlockPeriod)] + #[storage_mapper("default_unlock_period")] + fn default_unlock_period(&self) -> SingleValueMapper>; +} diff --git a/legacy-contracts/factory-legacy/src/locked_asset.rs b/legacy-contracts/factory-legacy/src/locked_asset.rs new file mode 100644 index 000000000..a1e02cc8d --- /dev/null +++ b/legacy-contracts/factory-legacy/src/locked_asset.rs @@ -0,0 +1,209 @@ +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); + +use common_structs::*; + +use crate::attr_ex_helper::{self, PRECISION_EX_INCREASE}; + +pub const ONE_MILLION: u64 = 1_000_000u64; +pub const TEN_THOUSAND: u64 = 10_000u64; +pub const PERCENTAGE_TOTAL_EX: u64 = 100_000u64; +pub const MAX_MILESTONES_IN_SCHEDULE: usize = 64; +pub const DOUBLE_MAX_MILESTONES_IN_SCHEDULE: usize = 2 * MAX_MILESTONES_IN_SCHEDULE; + +use core::fmt::Debug; + +#[derive(ManagedVecItem)] +pub struct LockedTokenEx { + pub token_amount: EsdtTokenPayment, + pub attributes: LockedAssetTokenAttributesEx, +} + +#[derive(ManagedVecItem, Clone, Debug)] +pub struct EpochAmountPair { + pub epoch: u64, + pub amount: BigUint, +} + +#[multiversx_sc::module] +pub trait LockedAssetModule: attr_ex_helper::AttrExHelper { + fn create_and_send_locked_assets( + &self, + amount: &BigUint, + additional_amount_to_create: &BigUint, + address: &ManagedAddress, + attributes: &LockedAssetTokenAttributesEx, + ) -> Nonce { + let token_id = self.locked_asset_token_id().get(); + let last_created_nonce = self.send().esdt_nft_create_compact( + &token_id, + &(amount + additional_amount_to_create), + attributes, + ); + self.send() + .direct_esdt(address, &token_id, last_created_nonce, amount); + + last_created_nonce + } + + fn add_quantity_and_send_locked_assets( + &self, + amount: &BigUint, + sft_nonce: Nonce, + address: &ManagedAddress, + ) { + let token_id = self.locked_asset_token_id().get(); + self.send().esdt_local_mint(&token_id, sft_nonce, amount); + + self.send() + .direct_esdt(address, &token_id, sft_nonce, amount); + } + + fn get_unlock_amount( + &self, + amount: &BigUint, + current_epoch: Epoch, + unlock_milestones: &ManagedVec, + ) -> BigUint { + amount * &BigUint::from(self.get_unlock_percent(current_epoch, unlock_milestones)) + / PERCENTAGE_TOTAL_EX + } + + fn get_unlock_percent( + &self, + current_epoch: Epoch, + unlock_milestones: &ManagedVec, + ) -> u64 { + let mut unlock_percent = 0u64; + + for milestone in unlock_milestones.into_iter() { + if milestone.unlock_epoch <= current_epoch { + unlock_percent += milestone.unlock_percent; + } + } + + require!( + unlock_percent <= PERCENTAGE_TOTAL_EX, + "unlock percent greater than max" + ); + + unlock_percent + } + + fn create_new_unlock_milestones( + &self, + current_epoch: Epoch, + old_unlock_milestones: &ManagedVec, + ) -> ManagedVec { + let unlock_percent = self.get_unlock_percent(current_epoch, old_unlock_milestones); + let unlock_percent_remaining = PERCENTAGE_TOTAL_EX - unlock_percent; + + if unlock_percent_remaining == 0 { + return ManagedVec::new(); + } + + let mut unlock_milestones_merged = + ArrayVec::::new(); + for old_milestone in old_unlock_milestones.iter() { + if old_milestone.unlock_epoch > current_epoch { + let new_unlock_percent = + old_milestone.unlock_percent * PRECISION_EX_INCREASE * ONE_MILLION + / unlock_percent_remaining; + unlock_milestones_merged.push(UnlockMilestoneEx { + unlock_epoch: old_milestone.unlock_epoch, + unlock_percent: new_unlock_percent, + }); + } + } + + self.distribute_leftover(&mut unlock_milestones_merged); + self.get_non_zero_percent_milestones_as_vec(&unlock_milestones_merged) + } + + fn distribute_leftover( + &self, + unlock_milestones_merged: &mut ArrayVec, + ) { + let mut sum_of_new_percents = 0u64; + for milestone in unlock_milestones_merged.iter() { + sum_of_new_percents += milestone.unlock_percent / TEN_THOUSAND; + } + let mut leftover = PERCENTAGE_TOTAL_EX - sum_of_new_percents; + + while leftover != 0 { + let mut max_rounding_error = 0; + let mut max_rounding_error_index = 0; + for index in 0..unlock_milestones_merged.len() { + let rounding_error = unlock_milestones_merged[index].unlock_percent % TEN_THOUSAND; + if rounding_error >= max_rounding_error { + max_rounding_error = rounding_error; + max_rounding_error_index = index; + } + } + + leftover -= 1; + unlock_milestones_merged[max_rounding_error_index].unlock_percent = + ((unlock_milestones_merged[max_rounding_error_index].unlock_percent + / TEN_THOUSAND) + + 1) + * TEN_THOUSAND; + } + } + + fn get_non_zero_percent_milestones_as_vec( + &self, + unlock_milestones_merged: &ArrayVec, + ) -> ManagedVec { + let mut new_unlock_milestones = ManagedVec::new(); + + for el in unlock_milestones_merged.iter() { + let percent_rounded = el.unlock_percent / TEN_THOUSAND; + if percent_rounded != 0 { + new_unlock_milestones.push(UnlockMilestoneEx { + unlock_epoch: el.unlock_epoch, + unlock_percent: percent_rounded, + }); + } + } + + new_unlock_milestones + } + + fn validate_unlock_milestones(&self, unlock_milestones: &ManagedVec) { + require!(!unlock_milestones.is_empty(), "Empty param"); + + let mut percents_sum: u8 = 0; + let mut last_milestone_unlock_epoch: u64 = 0; + + for milestone in unlock_milestones.into_iter() { + require!( + milestone.unlock_epoch >= last_milestone_unlock_epoch, + "Unlock epochs not in order" + ); + require!( + milestone.unlock_percent <= 100, + "Unlock percent more than 100" + ); + last_milestone_unlock_epoch = milestone.unlock_epoch; + percents_sum += milestone.unlock_percent; + } + + require!(percents_sum == 100, "Percents do not sum up to 100"); + } + + fn mint_and_send_assets(&self, dest: &ManagedAddress, amount: &BigUint) { + if amount > &0 { + let asset_token_id = self.asset_token_id().get(); + self.send().esdt_local_mint(&asset_token_id, 0, amount); + self.send().direct_esdt(dest, &asset_token_id, 0, amount); + } + } + + #[view(getLockedAssetTokenId)] + #[storage_mapper("locked_asset_token_id")] + fn locked_asset_token_id(&self) -> SingleValueMapper; + + #[view(getAssetTokenId)] + #[storage_mapper("asset_token_id")] + fn asset_token_id(&self) -> SingleValueMapper; +} diff --git a/legacy-contracts/factory-legacy/src/locked_asset_token_merge.rs b/legacy-contracts/factory-legacy/src/locked_asset_token_merge.rs new file mode 100644 index 000000000..8cb637658 --- /dev/null +++ b/legacy-contracts/factory-legacy/src/locked_asset_token_merge.rs @@ -0,0 +1,162 @@ +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); + +use common_structs::*; + +use crate::attr_ex_helper::{self, PRECISION_EX_INCREASE}; + +use super::locked_asset; +use super::locked_asset::{ + EpochAmountPair, LockedTokenEx, DOUBLE_MAX_MILESTONES_IN_SCHEDULE, MAX_MILESTONES_IN_SCHEDULE, + ONE_MILLION, PERCENTAGE_TOTAL_EX, +}; + +#[multiversx_sc::module] +pub trait LockedAssetTokenMergeModule: + locked_asset::LockedAssetModule + + token_merge_helper::TokenMergeHelperModule + + attr_ex_helper::AttrExHelper +{ + fn burn_tokens_from_payments(&self, payments: &ManagedVec) { + for entry in payments { + self.send() + .esdt_local_burn(&entry.token_identifier, entry.token_nonce, &entry.amount); + } + } + + fn get_merged_locked_asset_token_amount_and_attributes( + &self, + payments: &ManagedVec, + ) -> (BigUint, LockedAssetTokenAttributesEx) { + require!(!payments.is_empty(), "Cannot merge with 0 tokens"); + + let mut tokens = ManagedVec::new(); + let mut sum_amount = BigUint::zero(); + let locked_asset_token_id = self.locked_asset_token_id().get(); + let attr_ex_activation = self.extended_attributes_activation_nonce().get(); + for entry in payments { + require!( + entry.token_identifier == locked_asset_token_id, + "Bad token id" + ); + + tokens.push(LockedTokenEx { + token_amount: EsdtTokenPayment::new( + entry.token_identifier.clone(), + entry.token_nonce, + entry.amount.clone(), + ), + attributes: self.get_attributes_ex( + &entry.token_identifier, + entry.token_nonce, + attr_ex_activation, + ), + }); + sum_amount += &entry.amount; + } + + if tokens.len() == 1 { + let token_0 = tokens.get(0); + return (token_0.token_amount.amount.clone(), token_0.attributes); + } + + let attrs = LockedAssetTokenAttributesEx { + unlock_schedule: self.aggregated_unlock_schedule(&tokens), + is_merged: true, + }; + + (sum_amount, attrs) + } + + fn calculate_new_unlock_milestones( + &self, + unlock_epoch_amount_merged: &ArrayVec< + EpochAmountPair, + DOUBLE_MAX_MILESTONES_IN_SCHEDULE, + >, + amount_total: &BigUint, + ) -> ManagedVec { + let mut unlock_milestones_merged = + ArrayVec::::new(); + + for el in unlock_epoch_amount_merged.iter() { + let unlock_percent = &(&el.amount * PRECISION_EX_INCREASE * ONE_MILLION) / amount_total; + + // Accumulate even the percents of 0 + unlock_milestones_merged.push(UnlockMilestoneEx { + unlock_epoch: el.epoch, + unlock_percent: unlock_percent.to_u64().unwrap(), + }) + } + + self.distribute_leftover(&mut unlock_milestones_merged); + self.get_non_zero_percent_milestones_as_vec(&unlock_milestones_merged) + } + + fn aggregated_unlock_schedule( + &self, + tokens: &ManagedVec>, + ) -> UnlockScheduleEx { + let mut array = + ArrayVec::, DOUBLE_MAX_MILESTONES_IN_SCHEDULE>::new(); + + let mut sum = BigUint::zero(); + for locked_token in tokens.iter() { + for milestone in locked_token + .attributes + .unlock_schedule + .unlock_milestones + .iter() + { + require!( + array.len() < DOUBLE_MAX_MILESTONES_IN_SCHEDULE, + "too many unlock milestones" + ); + array.push(EpochAmountPair { + epoch: milestone.unlock_epoch, + amount: self.rule_of_three( + &BigUint::from(milestone.unlock_percent), + &BigUint::from(PERCENTAGE_TOTAL_EX), + &locked_token.token_amount.amount, + ), + }); + } + sum += &locked_token.token_amount.amount; + } + array.sort_unstable_by(|a, b| a.epoch.cmp(&b.epoch)); + + let default = EpochAmountPair { + epoch: 0u64, + amount: BigUint::zero(), + }; + let mut unlock_epoch_amount_merged = + ArrayVec::, DOUBLE_MAX_MILESTONES_IN_SCHEDULE>::new(); + for elem in array.iter() { + let last = unlock_epoch_amount_merged.last().unwrap_or(&default); + + if elem.epoch == last.epoch || elem.epoch == last.epoch + 1 { + let new_elem = EpochAmountPair { + epoch: elem.epoch, + amount: &last.amount + &elem.amount, + }; + unlock_epoch_amount_merged.pop(); + unlock_epoch_amount_merged.push(new_elem); + } else { + unlock_epoch_amount_merged.push(elem.clone()); + } + } + require!(sum != 0u64, "Sum cannot be zero"); + require!( + unlock_epoch_amount_merged.len() < MAX_MILESTONES_IN_SCHEDULE, + "Too many milestones" + ); + require!(!unlock_epoch_amount_merged.is_empty(), "Empty milestones"); + + let new_unlock_milestones = + self.calculate_new_unlock_milestones(&unlock_epoch_amount_merged, &sum); + + UnlockScheduleEx { + unlock_milestones: new_unlock_milestones, + } + } +} diff --git a/legacy-contracts/factory-legacy/src/migration.rs b/legacy-contracts/factory-legacy/src/migration.rs new file mode 100644 index 000000000..393f82a59 --- /dev/null +++ b/legacy-contracts/factory-legacy/src/migration.rs @@ -0,0 +1,61 @@ +multiversx_sc::imports!(); + +use common_structs::UnlockEpochAmountPairs; + +mod energy_factory_proxy { + use common_structs::UnlockEpochAmountPairs; + + multiversx_sc::imports!(); + + #[multiversx_sc::proxy] + pub trait EnergyFactoryProxy { + #[endpoint(updateEnergyAfterOldTokenUnlock)] + fn update_energy_after_old_token_unlock( + &self, + original_caller: ManagedAddress, + initial_epoch_amount_pairs: UnlockEpochAmountPairs, + final_epoch_amount_pairs: UnlockEpochAmountPairs, + ); + } +} + +#[multiversx_sc::module] +pub trait LockedTokenMigrationModule: + crate::locked_asset::LockedAssetModule + crate::attr_ex_helper::AttrExHelper +{ + #[only_owner] + #[endpoint(setNewFactoryAddress)] + fn set_new_factory_address(&self, sc_address: ManagedAddress) { + require!( + !sc_address.is_zero() && self.blockchain().is_smart_contract(&sc_address), + "Invalid SC address" + ); + self.new_factory_address().set(&sc_address); + } + + fn update_energy_after_unlock( + &self, + caller: ManagedAddress, + initial_epoch_amount_pairs: UnlockEpochAmountPairs, + final_epoch_amount_pairs: UnlockEpochAmountPairs, + ) { + let new_factory_address = self.new_factory_address().get(); + let _: IgnoreValue = self + .new_factory_proxy_builder(new_factory_address) + .update_energy_after_old_token_unlock( + caller, + initial_epoch_amount_pairs, + final_epoch_amount_pairs, + ) + .execute_on_dest_context(); + } + + #[proxy] + fn new_factory_proxy_builder( + &self, + sc_address: ManagedAddress, + ) -> energy_factory_proxy::Proxy; + + #[storage_mapper("newFactoryAddress")] + fn new_factory_address(&self) -> SingleValueMapper; +} diff --git a/legacy-contracts/factory-legacy/testnet.toml b/legacy-contracts/factory-legacy/testnet.toml new file mode 100644 index 000000000..e69de29bb diff --git a/legacy-contracts/factory-legacy/wasm/Cargo.lock b/legacy-contracts/factory-legacy/wasm/Cargo.lock new file mode 100644 index 000000000..50cc43b0b --- /dev/null +++ b/legacy-contracts/factory-legacy/wasm/Cargo.lock @@ -0,0 +1,255 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "common_errors" +version = "0.0.0" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "common_structs" +version = "0.0.0" +dependencies = [ + "fixed-supply-token", + "math", + "mergeable", + "multiversx-sc", + "unwrappable", +] + +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + +[[package]] +name = "factory-legacy" +version = "0.0.0" +dependencies = [ + "common_errors", + "common_structs", + "multiversx-sc", + "multiversx-sc-modules", + "token_merge_helper", +] + +[[package]] +name = "factory-legacy-wasm" +version = "0.0.0" +dependencies = [ + "factory-legacy", + "multiversx-sc-wasm-adapter", +] + +[[package]] +name = "fixed-supply-token" +version = "0.0.0" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "math" +version = "0.0.0" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "mergeable" +version = "0.0.0" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "multiversx-sc" +version = "0.50.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38a802d6cfa67748145a9e729336f4e6390eba702b5f14360ed01fcff14faa4" +dependencies = [ + "bitflags", + "hex-literal", + "multiversx-sc-codec", + "multiversx-sc-derive", + "num-traits", + "unwrap-infallible", +] + +[[package]] +name = "multiversx-sc-codec" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c94397b2fba14e40edfa55905b3f453ed57aa06c9b1960ad6a0ca6bfb7a236" +dependencies = [ + "arrayvec", + "multiversx-sc-codec-derive", + "unwrap-infallible", +] + +[[package]] +name = "multiversx-sc-codec-derive" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf72a8042da0bc19da0b8f0d4f61b4c66ae853560fefc69cd8fea87bf1aa8c14" +dependencies = [ + "hex", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "multiversx-sc-derive" +version = "0.50.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dc53ddcbd71948d2e8d3d6b814da866e2920b24e6c0cbfa643922f781897476" +dependencies = [ + "hex", + "proc-macro2", + "quote", + "radix_trie", + "syn", +] + +[[package]] +name = "multiversx-sc-modules" +version = "0.50.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea1ae09db9cac18669b85d50932410df6082e1a575975ba5224e3b7ae33cbe7d" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "multiversx-sc-wasm-adapter" +version = "0.50.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99a090365b4483b4ea955ba1322f986f6821be88144291f0013c03f59b4de753" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "proc-macro2" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "syn" +version = "2.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "token_merge_helper" +version = "0.0.0" +dependencies = [ + "common_errors", + "multiversx-sc", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unwrap-infallible" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "151ac09978d3c2862c4e39b557f4eceee2cc72150bc4cb4f16abf061b6e381fb" + +[[package]] +name = "unwrappable" +version = "0.0.0" +dependencies = [ + "multiversx-sc", +] diff --git a/legacy-contracts/factory-legacy/wasm/Cargo.toml b/legacy-contracts/factory-legacy/wasm/Cargo.toml new file mode 100644 index 000000000..bd05eac77 --- /dev/null +++ b/legacy-contracts/factory-legacy/wasm/Cargo.toml @@ -0,0 +1,34 @@ +# Code generated by the multiversx-sc build system. DO NOT EDIT. + +# ########################################## +# ############## AUTO-GENERATED ############# +# ########################################## + +[package] +name = "factory-legacy-wasm" +version = "0.0.0" +edition = "2018" +publish = false + +[lib] +crate-type = ["cdylib"] + +[profile.release] +codegen-units = 1 +opt-level = "z" +lto = true +debug = false +panic = "abort" +overflow-checks = false + +[profile.dev] +panic = "abort" + +[dependencies.factory-legacy] +path = ".." + +[dependencies.multiversx-sc-wasm-adapter] +version = "=0.50.5" + +[workspace] +members = ["."] diff --git a/legacy-contracts/factory-legacy/wasm/src/lib.rs b/legacy-contracts/factory-legacy/wasm/src/lib.rs new file mode 100644 index 000000000..1ddbeb62c --- /dev/null +++ b/legacy-contracts/factory-legacy/wasm/src/lib.rs @@ -0,0 +1,45 @@ +// Code generated by the multiversx-sc build system. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +// Init: 1 +// Endpoints: 21 +// Async Callback (empty): 1 +// Total number of exported functions: 23 + +#![no_std] + +multiversx_sc_wasm_adapter::allocator!(); +multiversx_sc_wasm_adapter::panic_handler!(); + +multiversx_sc_wasm_adapter::endpoints! { + factory_legacy + ( + init => init + whitelist => whitelist + removeWhitelist => remove_whitelist + createAndForwardCustomPeriod => create_and_forward_custom_period + createAndForward => create_and_forward + unlockAssets => unlock_assets + setTransferRoleForAddress => set_transfer_role_for_address + unsetTransferRoleForAddress => unset_transfer_role_for_address + setBurnRoleForAddress => set_burn_role_for_address + getLastErrorMessage => last_error_message + getInitEpoch => init_epoch + getWhitelistedContracts => get_whitelisted_contracts + getDefaultUnlockPeriod => default_unlock_period + getLockedAssetTokenId => locked_asset_token_id + getAssetTokenId => asset_token_id + getUnlockScheduleForSFTNonce => get_unlock_schedule_for_sft_nonce + getCacheSize => get_cache_size + getExtendedAttributesActivationNonce => extended_attributes_activation_nonce + setNewFactoryAddress => set_new_factory_address + pause => pause_endpoint + unpause => unpause_endpoint + isPaused => paused_status + ) +} + +multiversx_sc_wasm_adapter::async_callback_empty! {} diff --git a/legacy-contracts/farm-v-13/wasm/src/lib.rs b/legacy-contracts/farm-v-13/wasm/src/lib.rs index 850923617..ad5759863 100644 --- a/legacy-contracts/farm-v-13/wasm/src/lib.rs +++ b/legacy-contracts/farm-v-13/wasm/src/lib.rs @@ -6,9 +6,9 @@ // Init: 1 // Upgrade: 1 -// Endpoints: 3 +// Endpoints: 4 // Async Callback (empty): 1 -// Total number of exported functions: 6 +// Total number of exported functions: 7 #![no_std] @@ -23,6 +23,7 @@ multiversx_sc_wasm_adapter::endpoints! { exitFarm => exit_farm calculateRewardsForGivenPosition => calculate_rewards_for_given_position end_produce_rewards => end_produce_rewards + getFarmingTokenId => farming_token_id ) } diff --git a/legacy-contracts/proxy-dex-legacy/Cargo.toml b/legacy-contracts/proxy-dex-legacy/Cargo.toml index cb6801e13..d91ce9636 100644 --- a/legacy-contracts/proxy-dex-legacy/Cargo.toml +++ b/legacy-contracts/proxy-dex-legacy/Cargo.toml @@ -20,5 +20,5 @@ path = "../../common/common_structs" [dependencies.token_merge_helper] path = "../../common/modules/token_merge_helper" -[dependencies.factory] -path = "../../locked-asset/factory" +[dependencies.factory-legacy] +path = "../factory-legacy" diff --git a/legacy-contracts/proxy-dex-legacy/src/energy_update.rs b/legacy-contracts/proxy-dex-legacy/src/energy_update.rs index 06921dd35..e1bb7725a 100644 --- a/legacy-contracts/proxy-dex-legacy/src/energy_update.rs +++ b/legacy-contracts/proxy-dex-legacy/src/energy_update.rs @@ -2,7 +2,7 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); use common_structs::LockedAssetTokenAttributesEx; -use factory::attr_ex_helper; +use factory_legacy::attr_ex_helper; use crate::{energy::Energy, proxy_common}; @@ -55,8 +55,9 @@ pub trait EnergyUpdateModule: let mut energy = self.get_energy_entry(user); let current_epoch = self.blockchain().get_block_epoch(); + let extended_attributes_activation_nonce = self.get_extended_attributes_activation_nonce(); let attributes: LockedAssetTokenAttributesEx = - self.get_attributes_ex(token_id, token_nonce); + self.get_attributes_ex(token_id, token_nonce, extended_attributes_activation_nonce); let amounts_per_epoch = attributes.get_unlock_amounts_per_epoch(token_amount); for epoch_amount_pair in &amounts_per_epoch.pairs { energy.update_after_unlock_any( diff --git a/legacy-contracts/proxy-dex-legacy/src/lib.rs b/legacy-contracts/proxy-dex-legacy/src/lib.rs index 32305f10f..e62a10190 100644 --- a/legacy-contracts/proxy-dex-legacy/src/lib.rs +++ b/legacy-contracts/proxy-dex-legacy/src/lib.rs @@ -12,7 +12,7 @@ pub mod proxy_farm; mod proxy_pair; pub mod transfer_role; -use factory::attr_ex_helper; +use factory_legacy::attr_ex_helper; #[multiversx_sc::contract] pub trait ProxyDexImpl: diff --git a/legacy-contracts/proxy-dex-legacy/src/migration_from_v1_2.rs b/legacy-contracts/proxy-dex-legacy/src/migration_from_v1_2.rs index 838954dd8..871e42259 100644 --- a/legacy-contracts/proxy-dex-legacy/src/migration_from_v1_2.rs +++ b/legacy-contracts/proxy-dex-legacy/src/migration_from_v1_2.rs @@ -3,7 +3,7 @@ multiversx_sc::derive_imports!(); use common_structs::RawResultWrapper; use common_structs::RawResultsType; -use factory::attr_ex_helper; +use factory_legacy::attr_ex_helper; use super::events; use super::proxy_common; diff --git a/legacy-contracts/proxy-dex-legacy/src/proxy_farm.rs b/legacy-contracts/proxy-dex-legacy/src/proxy_farm.rs index bd39605e6..d875c5486 100644 --- a/legacy-contracts/proxy-dex-legacy/src/proxy_farm.rs +++ b/legacy-contracts/proxy-dex-legacy/src/proxy_farm.rs @@ -5,7 +5,7 @@ multiversx_sc::derive_imports!(); use common_structs::Nonce; use common_structs::{RawResultWrapper, RawResultsType}; -use factory::attr_ex_helper; +use factory_legacy::attr_ex_helper; use crate::energy_update; use crate::proxy_common::WrappedFarmTokenAttributes; diff --git a/legacy-contracts/proxy-dex-legacy/src/proxy_pair.rs b/legacy-contracts/proxy-dex-legacy/src/proxy_pair.rs index d0bc68b4a..c8ec2607c 100644 --- a/legacy-contracts/proxy-dex-legacy/src/proxy_pair.rs +++ b/legacy-contracts/proxy-dex-legacy/src/proxy_pair.rs @@ -6,7 +6,7 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); use common_structs::{RawResultWrapper, RawResultsType}; -use factory::attr_ex_helper; +use factory_legacy::attr_ex_helper; use crate::energy_update; use crate::proxy_common::WrappedLpTokenAttributes; diff --git a/legacy-contracts/proxy-dex-legacy/wasm/Cargo.lock b/legacy-contracts/proxy-dex-legacy/wasm/Cargo.lock index a3143553e..df92fe170 100644 --- a/legacy-contracts/proxy-dex-legacy/wasm/Cargo.lock +++ b/legacy-contracts/proxy-dex-legacy/wasm/Cargo.lock @@ -20,12 +20,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "common_errors" version = "0.0.0" @@ -44,12 +38,6 @@ dependencies = [ "unwrappable", ] -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - [[package]] name = "endian-type" version = "0.1.2" @@ -57,35 +45,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] -name = "energy-factory" +name = "factory-legacy" version = "0.0.0" dependencies = [ - "common_structs", - "legacy_token_decode_module", - "math", - "mergeable", - "multiversx-sc", - "multiversx-sc-modules", - "sc_whitelist_module", - "simple-lock", - "unwrappable", - "utils", -] - -[[package]] -name = "factory" -version = "0.0.0" -dependencies = [ - "arrayvec", "common_errors", "common_structs", - "energy-factory", - "itertools", "multiversx-sc", "multiversx-sc-modules", "token_merge_helper", - "token_send", - "wee_alloc", ] [[package]] @@ -107,30 +74,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "legacy_token_decode_module" -version = "0.0.0" -dependencies = [ - "common_structs", - "multiversx-sc", - "utils", -] - -[[package]] -name = "libc" -version = "0.2.118" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e509672465a0504304aa87f9f176f2b2b716ed8fb105ebe5c02dc6dce96a94" - [[package]] name = "math" version = "0.0.0" @@ -138,12 +81,6 @@ dependencies = [ "multiversx-sc", ] -[[package]] -name = "memory_units" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" - [[package]] name = "mergeable" version = "0.0.0" @@ -251,7 +188,7 @@ name = "proxy-dex-legacy" version = "0.0.0" dependencies = [ "common_structs", - "factory", + "factory-legacy", "multiversx-sc", "token_merge_helper", ] @@ -283,23 +220,6 @@ dependencies = [ "nibble_vec", ] -[[package]] -name = "sc_whitelist_module" -version = "0.0.0" -dependencies = [ - "common_errors", - "multiversx-sc", -] - -[[package]] -name = "simple-lock" -version = "0.0.0" -dependencies = [ - "common_structs", - "multiversx-sc", - "multiversx-sc-modules", -] - [[package]] name = "smallvec" version = "1.13.2" @@ -325,15 +245,6 @@ dependencies = [ "multiversx-sc", ] -[[package]] -name = "token_send" -version = "0.0.0" -dependencies = [ - "common_errors", - "common_structs", - "multiversx-sc", -] - [[package]] name = "unicode-ident" version = "1.0.12" @@ -352,47 +263,3 @@ version = "0.0.0" dependencies = [ "multiversx-sc", ] - -[[package]] -name = "utils" -version = "0.0.0" -dependencies = [ - "common_structs", - "fixed-supply-token", - "mergeable", - "multiversx-sc", -] - -[[package]] -name = "wee_alloc" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" -dependencies = [ - "cfg-if", - "libc", - "memory_units", - "winapi", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"