diff --git a/Cargo.lock b/Cargo.lock index c72ec6a..51a3ac4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,26 +27,16 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "aes" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", "once_cell", "version_check", + "zerocopy", ] [[package]] @@ -58,11 +48,17 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "anstream" -version = "0.5.0" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" +checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" dependencies = [ "anstyle", "anstyle-parse", @@ -93,17 +89,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "anstyle-wincon" -version = "2.1.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -129,29 +125,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "auto-farm" -version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-tools-sc?rev=39e355f#39e355f759869473d1fab9ec4f18a8c6c9506547" -dependencies = [ - "common_structs", - "energy-factory", - "energy-query", - "farm", - "farm-staking", - "farm-staking-proxy", - "farm-with-locked-rewards", - "fees-collector", - "legacy_token_decode_module", - "lkmex-transfer", - "mergeable", - "metabonding", - "multiversx-sc", - "multiversx-sc-modules", - "pair", - "utils", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -175,15 +148,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.3" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "base64ct" @@ -224,19 +191,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" - -[[package]] -name = "block-buffer" -version = "0.9.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "block-padding", - "generic-array", -] +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "block-buffer" @@ -247,12 +204,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - [[package]] name = "bstr" version = "1.6.2" @@ -281,34 +232,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" -[[package]] -name = "bzip2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ - "jobserver", "libc", ] @@ -318,21 +247,11 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - [[package]] name = "clap" -version = "4.4.2" +version = "4.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6" +checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" dependencies = [ "clap_builder", "clap_derive", @@ -340,9 +259,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.2" +version = "4.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" +checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" dependencies = [ "anstream", "anstyle", @@ -352,21 +271,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.29", + "syn", ] [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "colorchoice" @@ -382,7 +301,7 @@ checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" dependencies = [ "is-terminal", "lazy_static", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -394,7 +313,7 @@ checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" [[package]] name = "common-types" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "multiversx-sc", ] @@ -402,15 +321,23 @@ dependencies = [ [[package]] name = "common_errors" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "common_structs" +version = "0.0.0" dependencies = [ + "mergeable", "multiversx-sc", ] [[package]] name = "common_structs" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "fixed-supply-token", "math", @@ -419,13 +346,21 @@ dependencies = [ "unwrappable", ] +[[package]] +name = "common_subscriber" +version = "0.0.0" +dependencies = [ + "multiversx-sc", + "subscription-fee", +] + [[package]] name = "config" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "common_errors", - "common_structs", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", "multiversx-sc", "pausable", "permissions_module", @@ -438,19 +373,13 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - [[package]] name = "contexts" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "common_errors", - "common_structs", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", "config", "farm_token", "multiversx-sc", @@ -533,16 +462,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "crypto-mac" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" -dependencies = [ - "generic-array", - "subtle", -] - [[package]] name = "curve25519-dalek" version = "4.0.0" @@ -552,7 +471,7 @@ dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", - "digest 0.10.7", + "digest", "fiat-crypto", "platforms", "rustc_version", @@ -568,41 +487,7 @@ checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", -] - -[[package]] -name = "darling" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "syn 2.0.29", -] - -[[package]] -name = "darling_macro" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.29", + "syn", ] [[package]] @@ -615,41 +500,17 @@ dependencies = [ "zeroize", ] -[[package]] -name = "deranged" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", "crypto-common", "subtle", ] -[[package]] -name = "ed25519" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" -dependencies = [ - "signature 1.6.4", -] - [[package]] name = "ed25519" version = "2.2.2" @@ -657,7 +518,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60f6d271ca33075c88028be6f04d502853d63a5ece419d269c15315d4fc1cf1d" dependencies = [ "pkcs8", - "signature 2.1.0", + "signature", ] [[package]] @@ -667,9 +528,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" dependencies = [ "curve25519-dalek", - "ed25519 2.2.2", + "ed25519", "serde", - "sha2 0.10.7", + "sha2", "zeroize", ] @@ -697,9 +558,9 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] name = "energy-factory" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ - "common_structs", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", "legacy_token_decode_module", "math", "mergeable", @@ -714,46 +575,12 @@ dependencies = [ [[package]] name = "energy-query" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "energy-factory", "multiversx-sc", ] -[[package]] -name = "enumset" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e875f1719c16de097dee81ed675e2d9bb63096823ed3f0ca827b7dea3028bbbb" -dependencies = [ - "enumset_derive", -] - -[[package]] -name = "enumset_derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.29", -] - -[[package]] -name = "env_logger" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -768,7 +595,7 @@ checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" dependencies = [ "errno-dragonfly", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -784,9 +611,9 @@ dependencies = [ [[package]] name = "events" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ - "common_structs", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", "contexts", "multiversx-sc", ] @@ -794,10 +621,10 @@ dependencies = [ [[package]] name = "farm" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "common_errors", - "common_structs", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", "config", "contexts", "energy-query", @@ -824,11 +651,17 @@ dependencies = [ name = "farm-boosted-rewards-subscriber" version = "0.0.0" dependencies = [ - "auto-farm", + "common_structs 0.0.0", + "common_subscriber", + "config", "energy-factory", "energy-query", + "farm-boosted-yields", + "farm-with-locked-rewards", + "farm_token", "hex", - "hex-literal", + "hex-literal 0.3.4", + "locking_module", "multiversx-sc", "multiversx-sc-modules", "multiversx-sc-scenario", @@ -836,7 +669,8 @@ dependencies = [ "num-traits", "pair", "pausable", - "subscriber", + "sc_whitelist_module", + "simple-lock", "subscription-fee", ] @@ -851,7 +685,7 @@ dependencies = [ [[package]] name = "farm-boosted-yields" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "common-types", "config", @@ -863,68 +697,13 @@ dependencies = [ "weekly-rewards-splitting", ] -[[package]] -name = "farm-staking" -version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" -dependencies = [ - "common_errors", - "common_structs", - "config", - "contexts", - "energy-factory", - "energy-query", - "events", - "farm", - "farm-boosted-yields", - "farm_base_impl", - "farm_token", - "fixed-supply-token", - "math", - "mergeable", - "multiversx-sc", - "multiversx-sc-modules", - "pair", - "pausable", - "permissions_module", - "rewards", - "sc_whitelist_module", - "token_send", - "utils", - "week-timekeeping", - "weekly-rewards-splitting", -] - -[[package]] -name = "farm-staking-proxy" -version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" -dependencies = [ - "common_structs", - "config", - "farm", - "farm-staking", - "fixed-supply-token", - "hex-literal", - "mergeable", - "multiversx-sc", - "multiversx-sc-modules", - "pair", - "pausable", - "rewards", - "sc_whitelist_module", - "token_send", - "unwrappable", - "utils", -] - [[package]] name = "farm-with-locked-rewards" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "common_errors", - "common_structs", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", "config", "contexts", "energy-factory", @@ -952,10 +731,10 @@ dependencies = [ [[package]] name = "farm_base_impl" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "common_errors", - "common_structs", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", "config", "contexts", "events", @@ -975,10 +754,10 @@ dependencies = [ [[package]] name = "farm_token" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "common_errors", - "common_structs", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", "config", "multiversx-sc", "multiversx-sc-modules", @@ -996,7 +775,7 @@ checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" [[package]] name = "fees-collector" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "common-types", "common_errors", @@ -1021,7 +800,7 @@ checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" [[package]] name = "fixed-supply-token" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "multiversx-sc", ] @@ -1181,19 +960,14 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.13.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ "ahash", + "allocator-api2", ] -[[package]] -name = "hashbrown" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" - [[package]] name = "heck" version = "0.4.1" @@ -1228,14 +1002,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" [[package]] -name = "hmac" -version = "0.11.0" +name = "hex-literal" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac", - "digest 0.9.0", -] +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" [[package]] name = "hmac" @@ -1243,7 +1013,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -1280,12 +1050,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" version = "0.14.27" @@ -1323,12 +1087,6 @@ dependencies = [ "tokio-native-tls", ] -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "idna" version = "0.4.0" @@ -1373,16 +1131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" dependencies = [ "equivalent", - "hashbrown 0.14.0", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", + "hashbrown 0.14.3", ] [[package]] @@ -1399,7 +1148,7 @@ checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi 0.3.2", "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1412,19 +1161,19 @@ dependencies = [ ] [[package]] -name = "itoa" -version = "1.0.9" +name = "itertools" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] [[package]] -name = "jobserver" -version = "0.1.26" +name = "itoa" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" -dependencies = [ - "libc", -] +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "js-sys" @@ -1453,9 +1202,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "legacy_token_decode_module" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ - "common_structs", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", "multiversx-sc", "utils", ] @@ -1472,21 +1221,6 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" -[[package]] -name = "lkmex-transfer" -version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" -dependencies = [ - "common_structs", - "energy-factory", - "energy-query", - "legacy_token_decode_module", - "multiversx-sc", - "permissions_module", - "simple-lock", - "utils", -] - [[package]] name = "lock_api" version = "0.4.10" @@ -1500,7 +1234,7 @@ dependencies = [ [[package]] name = "locking_module" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "energy-factory", "multiversx-sc", @@ -1516,7 +1250,7 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "math" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "multiversx-sc", ] @@ -1530,19 +1264,9 @@ checksum = "5486aed0026218e61b8a01d5fbd5a0a134649abb71a0e53b7bc088529dced86e" [[package]] name = "mergeable" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" -dependencies = [ - "multiversx-sc", -] - -[[package]] -name = "metabonding" -version = "0.0.0" -source = "git+https://github.com/multiversx/mx-metabonding-sc?rev=fd17100#fd17100885419dd72d829b0962e6ce5594474898" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "multiversx-sc", - "multiversx-sc-modules", - "sc_whitelist_module", ] [[package]] @@ -1568,14 +1292,14 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "wasi", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "multiversx-chain-scenario-format" -version = "0.20.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5bd3e4bf86e4d8c53f915be3110261432fac45b1defe42c8eebe07c82ab983" +checksum = "2dfc2b1dc76af14c24145672c2779474046ab44ef56bac82a58844328f4b4d2e" dependencies = [ "bech32", "hex", @@ -1583,55 +1307,44 @@ dependencies = [ "num-traits", "serde", "serde_json", - "sha3 0.9.1", + "sha3", ] [[package]] name = "multiversx-chain-vm" -version = "0.5.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddf7a1c81cf1dd2af49b462d00c2f2c22f6d3d4f35a73228dc2a9aa6f19c56ce" +checksum = "75459864359798406a45a7bb2ed221d623b2e39484ec3e4ac6d23167bfc50b33" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.1", "ed25519-dalek", "hex", - "hex-literal", - "itertools", + "hex-literal 0.4.1", + "itertools 0.12.0", "multiversx-chain-vm-executor", "num-bigint", "num-traits", "rand", "rand_seeder", - "sha2 0.10.7", - "sha3 0.10.8", + "sha2", + "sha3", ] [[package]] name = "multiversx-chain-vm-executor" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e14f14947682eb69459676336dd8b678e2317aa9844724220ce73411bc947c3" -dependencies = [ - "anyhow", - "cfg-if", - "enumset", - "env_logger", - "lazy_static", - "libc", - "log", - "paste", - "thiserror", -] +checksum = "b59072fa0624b55ae5ae3fa6bfa91515bbeb4ac440214bc4a509e2c8806d6e9f" [[package]] name = "multiversx-sc" -version = "0.43.2" +version = "0.45.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "386c2727eba66bc5e502e470d7afa55fdd69aedff440c508bb9ba85aec36a52a" +checksum = "9b2bdb196b3ff2b9f8c744ec2e026c22c8e02bc91e5c6ed09951415c47fef6b8" dependencies = [ - "bitflags 1.3.2", - "hashbrown 0.13.2", - "hex-literal", + "bitflags 2.4.1", + "hashbrown 0.14.3", + "hex-literal 0.4.1", "multiversx-sc-codec", "multiversx-sc-derive", "num-traits", @@ -1639,9 +1352,9 @@ dependencies = [ [[package]] name = "multiversx-sc-codec" -version = "0.18.1" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f1e15b46c17b87c0c7cdd79b041a4abd7f3a2b45f3c993f6ce38c0f233e82b6" +checksum = "19908153158c03df4582af08f47c0eb39fb52a7dff4736b301a66acbbb9955d3" dependencies = [ "arrayvec", "multiversx-sc-codec-derive", @@ -1650,36 +1363,35 @@ dependencies = [ [[package]] name = "multiversx-sc-codec-derive" -version = "0.18.1" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a7bc0762cd6d88f8bc54805bc652b042a61cd7fbc2d0a325010f088b78fb2ac" +checksum = "d3b03b43f9cad320992f54ed162de2ed63e3ec83ed01361e57ee9c1865fba5a2" dependencies = [ "hex", "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "multiversx-sc-derive" -version = "0.43.2" +version = "0.45.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "050510b6b9836b24b4a73bb7878c58c268d56bde1c6eb0f9a88dce9a6518507b" +checksum = "2e60b5dce707f61376f74d713218f75326121d9f6a5f09a3a63de7aea2a92be9" dependencies = [ "hex", "proc-macro2", "quote", "radix_trie", - "syn 1.0.109", + "syn", ] [[package]] name = "multiversx-sc-meta" -version = "0.43.2" +version = "0.45.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be19671ee9a1e7a6a2fcdd50b4ec09c0a23786442ace3070dae39ef96edc91ff" +checksum = "d48b080d91bb616c9de425454a451464a31873be885d5ac03eaa32534007010c" dependencies = [ - "anyhow", "clap", "colored", "common-path", @@ -1694,33 +1406,33 @@ dependencies = [ "rustc_version", "serde", "serde_json", - "tempfile", - "tokio", "toml", + "wasmparser", + "wasmprinter", "zip", ] [[package]] name = "multiversx-sc-modules" -version = "0.43.2" +version = "0.45.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b55fe3585cbc745bd7b9793be4bcb3aa7f1869ced7a0981f3d47e6a832c6311" +checksum = "a5833f8bc88104357d38a8952d2a16c3e66080e2e512c0e7001c0c003006c475" dependencies = [ "multiversx-sc", ] [[package]] name = "multiversx-sc-scenario" -version = "0.43.2" +version = "0.45.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c062c41d0475be4c24babc589559bcbf8204f2ab80a82327012d61db7c39e722" +checksum = "f2877b9a1da12441be129c349affa5da4aa5c47200db8716d415f973c74603ce" dependencies = [ - "base64 0.13.1", + "base64", "bech32", "clap", "colored", "hex", - "itertools", + "itertools 0.12.0", "log", "multiversx-chain-scenario-format", "multiversx-chain-vm", @@ -1733,33 +1445,32 @@ dependencies = [ "pathdiff", "serde", "serde_json", - "sha2 0.10.7", + "sha2", "tokio", ] [[package]] name = "multiversx-sdk" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb48ac185858a4ac825c300643df43344baeafe434fb4f9d9077fb81318f987" +checksum = "5f86d0da66ca2eb334414786a287010bb669b8d815a7d3b690d629a04b86bb80" dependencies = [ "anyhow", - "base64 0.13.1", + "base64", "bech32", "bip39", - "ed25519 1.5.3", "hex", - "hmac 0.11.0", - "itertools", - "pbkdf2 0.9.0", + "hmac", + "itertools 0.12.0", + "pbkdf2", "pem", "rand", "reqwest", "serde", "serde_json", "serde_repr", - "sha2 0.9.9", - "sha3 0.9.1", + "sha2", + "sha3", "tokio", "zeroize", ] @@ -1846,19 +1557,13 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - [[package]] name = "openssl" version = "0.10.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "cfg-if", "foreign-types", "libc", @@ -1875,7 +1580,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn", ] [[package]] @@ -1899,12 +1604,12 @@ dependencies = [ [[package]] name = "pair" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "common_errors", - "common_structs", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", "fees-collector", - "itertools", + "itertools 0.10.5", "multiversx-sc", "pausable", "permissions_module", @@ -1932,26 +1637,9 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core", - "subtle", -] - -[[package]] -name = "paste" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" - [[package]] name = "pathdiff" version = "0.2.1" @@ -1961,7 +1649,7 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" [[package]] name = "pausable" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "multiversx-sc", "permissions_module", @@ -1969,32 +1657,21 @@ dependencies = [ [[package]] name = "pbkdf2" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05894bce6a1ba4be299d0c5f29563e08af2bc18bb7d48313113bed71e904739" -dependencies = [ - "crypto-mac", -] - -[[package]] -name = "pbkdf2" -version = "0.11.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ - "digest 0.10.7", - "hmac 0.12.1", - "password-hash", - "sha2 0.10.7", + "digest", ] [[package]] name = "pem" -version = "1.1.1" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" dependencies = [ - "base64 0.13.1", + "base64", + "serde", ] [[package]] @@ -2006,9 +1683,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "permissions_module" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.1", "common_errors", "multiversx-sc", ] @@ -2055,9 +1732,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] @@ -2164,7 +1841,7 @@ version = "0.11.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" dependencies = [ - "base64 0.21.3", + "base64", "bytes", "encoding_rs", "futures-core", @@ -2198,10 +1875,10 @@ dependencies = [ [[package]] name = "rewards" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "common_errors", - "common_structs", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", "config", "farm_token", "multiversx-sc", @@ -2247,11 +1924,11 @@ version = "0.38.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0c3dde1fc030af041adc40e79c0e7fbcf431dd24870053d187d7c66e4b87453" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2272,7 +1949,7 @@ dependencies = [ [[package]] name = "sc_whitelist_module" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "common_errors", "multiversx-sc", @@ -2284,7 +1961,7 @@ version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2339,7 +2016,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn", ] [[package]] @@ -2362,7 +2039,16 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn", +] + +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", ] [[package]] @@ -2377,51 +2063,15 @@ dependencies = [ "serde", ] -[[package]] -name = "sha1" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha3" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "keccak", - "opaque-debug", + "digest", ] [[package]] @@ -2430,7 +2080,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest 0.10.7", + "digest", "keccak", ] @@ -2443,12 +2093,6 @@ dependencies = [ "libc", ] -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" - [[package]] name = "signature" version = "2.1.0" @@ -2458,9 +2102,9 @@ checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" [[package]] name = "simple-lock" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ - "common_structs", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", "multiversx-sc", "multiversx-sc-modules", ] @@ -2497,7 +2141,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2516,38 +2160,13 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "subscriber" -version = "0.0.0" -dependencies = [ - "auto-farm", - "hex", - "hex-literal", - "multiversx-sc", - "multiversx-sc-modules", - "multiversx-sc-scenario", - "num-bigint", - "num-traits", - "pair", - "pausable", - "subscription-fee", -] - -[[package]] -name = "subscriber-meta" -version = "0.0.0" -dependencies = [ - "multiversx-sc-meta", - "subscriber", -] - [[package]] name = "subscription-fee" version = "0.0.0" dependencies = [ - "auto-farm", + "common_structs 0.0.0", "hex", - "hex-literal", + "hex-literal 0.3.4", "multiversx-sc", "multiversx-sc-modules", "multiversx-sc-scenario", @@ -2573,20 +2192,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" dependencies = [ "proc-macro2", "quote", @@ -2603,36 +2211,7 @@ dependencies = [ "fastrand", "redox_syscall", "rustix", - "windows-sys", -] - -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "thiserror" -version = "1.0.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.29", + "windows-sys 0.48.0", ] [[package]] @@ -2645,23 +2224,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "time" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" -dependencies = [ - "deranged", - "serde", - "time-core", -] - -[[package]] -name = "time-core" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" - [[package]] name = "tinyvec" version = "1.6.0" @@ -2680,7 +2242,7 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "token_merge_helper" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "common_errors", "multiversx-sc", @@ -2689,10 +2251,10 @@ dependencies = [ [[package]] name = "token_send" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "common_errors", - "common_structs", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", "multiversx-sc", ] @@ -2712,7 +2274,7 @@ dependencies = [ "signal-hook-registry", "socket2 0.5.3", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2723,7 +2285,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn", ] [[package]] @@ -2752,14 +2314,39 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.11" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +dependencies = [ + "indexmap 2.0.0", + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ - "indexmap 1.9.3", "serde", ] +[[package]] +name = "toml_edit" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +dependencies = [ + "indexmap 2.0.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tower-service" version = "0.3.2" @@ -2828,7 +2415,7 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unwrappable" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "multiversx-sc", ] @@ -2853,9 +2440,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "utils" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ - "common_structs", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", "fixed-supply-token", "mergeable", "multiversx-sc", @@ -2919,7 +2506,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.29", + "syn", "wasm-bindgen-shared", ] @@ -2953,7 +2540,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2964,6 +2551,26 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +[[package]] +name = "wasmparser" +version = "0.118.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ee9723b928e735d53000dec9eae7b07a60e490c85ab54abb66659fc61bfcd9" +dependencies = [ + "indexmap 2.0.0", + "semver", +] + +[[package]] +name = "wasmprinter" +version = "0.2.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d027eb8294904fc715ac0870cebe6b0271e96b90605ee21511e7565c4ce568c" +dependencies = [ + "anyhow", + "wasmparser", +] + [[package]] name = "web-sys" version = "0.3.64" @@ -2977,7 +2584,7 @@ dependencies = [ [[package]] name = "week-timekeeping" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "common-types", "multiversx-sc", @@ -2986,7 +2593,7 @@ dependencies = [ [[package]] name = "weekly-rewards-splitting" version = "0.0.0" -source = "git+https://github.com/multiversx/mx-exchange-sc?rev=7f25a72#7f25a72c62d5920590563e4ccc56a47bd9a8ac21" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "common-types", "energy-query", @@ -3033,7 +2640,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -3042,13 +2658,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -3057,42 +2688,93 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winnow" +version = "0.5.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b5c3db89721d50d0e2a673f5043fc4722f76dcc352d7b1ab8b8288bed4ed2c5" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" @@ -3100,61 +2782,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ "cfg-if", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] -name = "zeroize" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" - -[[package]] -name = "zip" -version = "0.6.6" +name = "zerocopy" +version = "0.7.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d" dependencies = [ - "aes", - "byteorder", - "bzip2", - "constant_time_eq", - "crc32fast", - "crossbeam-utils", - "flate2", - "hmac 0.12.1", - "pbkdf2 0.11.0", - "sha1", - "time", - "zstd", + "zerocopy-derive", ] [[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" +name = "zerocopy-derive" +version = "0.7.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a" dependencies = [ - "zstd-safe", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" +name = "zeroize" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" -dependencies = [ - "libc", - "zstd-sys", -] +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" [[package]] -name = "zstd-sys" -version = "2.0.8+zstd.1.5.5" +name = "zip" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" dependencies = [ - "cc", - "libc", - "pkg-config", + "byteorder", + "crc32fast", + "crossbeam-utils", + "flate2", ] diff --git a/Cargo.toml b/Cargo.toml index bee5334..9fed2b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,8 +2,6 @@ members = [ "farm-boosted-rewards-subscriber", "farm-boosted-rewards-subscriber/meta", - "subscriber", - "subscriber/meta", "subscription-fee", "subscription-fee/meta", ] diff --git a/common/common_structs/Cargo.toml b/common/common_structs/Cargo.toml new file mode 100644 index 0000000..674469a --- /dev/null +++ b/common/common_structs/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "common_structs" +version = "0.0.0" +authors = ["MultiversX "] +edition = "2021" + +[lib] +path = "src/lib.rs" + +[dependencies.multiversx-sc] +version = "=0.45.2" +features = ["esdt-token-payment-legacy-decode"] + +[dependencies.mergeable] +git = "https://github.com/multiversx/mx-exchange-sc" +rev = "1fb9a1d" diff --git a/common/common_structs/src/lib.rs b/common/common_structs/src/lib.rs new file mode 100644 index 0000000..99014fb --- /dev/null +++ b/common/common_structs/src/lib.rs @@ -0,0 +1,8 @@ +#![no_std] + +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); + +pub mod unique_payments; + +pub use unique_payments::*; diff --git a/common/common_structs/src/unique_payments.rs b/common/common_structs/src/unique_payments.rs new file mode 100644 index 0000000..5ebbf71 --- /dev/null +++ b/common/common_structs/src/unique_payments.rs @@ -0,0 +1,133 @@ +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); + +use mergeable::Mergeable; + +pub type PaymentsVec = ManagedVec>; + +#[derive(TypeAbi, TopEncode, TopDecode, NestedEncode, NestedDecode, Clone, PartialEq, Debug)] +pub struct UniquePayments { + payments: PaymentsVec, +} + +impl Default for UniquePayments { + #[inline] + fn default() -> Self { + Self { + payments: PaymentsVec::new(), + } + } +} + +impl UniquePayments { + #[inline] + pub fn new() -> Self { + Self::default() + } + + #[inline] + pub fn new_from_unique_payments(payments: PaymentsVec) -> Self { + UniquePayments { payments } + } + + pub fn new_from_payments(payments: PaymentsVec) -> Self { + let mut merged_payments = Self::new(); + for p in &payments { + merged_payments.add_payment(p); + } + + merged_payments + } + + pub fn add_payment(&mut self, new_payment: EsdtTokenPayment) { + if new_payment.amount == 0 { + return; + } + + let len = self.payments.len(); + for i in 0..len { + let mut current_payment = self.payments.get(i); + if !current_payment.can_merge_with(&new_payment) { + continue; + } + + current_payment.amount += new_payment.amount; + let _ = self.payments.set(i, ¤t_payment); + + return; + } + + self.payments.push(new_payment); + } + #[allow(clippy::result_unit_err)] + pub fn deduct_payment(&mut self, payment: &EsdtTokenPayment) -> Result<(), ()> { + if payment.amount == 0 { + return Result::Ok(()); + } + + let len = self.payments.len(); + for i in 0..len { + let mut current_payment = self.payments.get(i); + if !current_payment.can_merge_with(payment) { + continue; + } + + if current_payment.amount < payment.amount { + return Result::Err(()); + } + + current_payment.amount -= &payment.amount; + let _ = self.payments.set(i, ¤t_payment); + + return Result::Ok(()); + } + + Result::Err(()) + } + + #[inline] + pub fn into_payments(self) -> PaymentsVec { + self.payments + } +} + +impl Mergeable for UniquePayments { + #[inline] + fn can_merge_with(&self, _other: &Self) -> bool { + true + } + + fn merge_with(&mut self, mut other: Self) { + self.error_if_not_mergeable(&other); + + if self.payments.is_empty() { + self.payments = other.payments; + return; + } + if other.payments.is_empty() { + return; + } + + let first_len = self.payments.len(); + let mut second_len = other.payments.len(); + for i in 0..first_len { + let mut current_payment = self.payments.get(i); + for j in 0..second_len { + let other_payment = other.payments.get(j); + if !current_payment.can_merge_with(&other_payment) { + continue; + } + + current_payment.amount += other_payment.amount; + let _ = self.payments.set(i, ¤t_payment); + + other.payments.remove(j); + second_len -= 1; + + break; + } + } + + self.payments.append_vec(other.payments); + } +} diff --git a/common/common_subscriber/Cargo.toml b/common/common_subscriber/Cargo.toml new file mode 100644 index 0000000..30fb9aa --- /dev/null +++ b/common/common_subscriber/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "common_subscriber" +version = "0.0.0" +authors = ["MultiversX "] +edition = "2021" + +[lib] +path = "src/common_subscriber.rs" + +[dependencies.subscription-fee] +path = "../../subscription-fee" + +[dependencies.multiversx-sc] +version = "=0.45.2" diff --git a/common/common_subscriber/src/common_subscriber.rs b/common/common_subscriber/src/common_subscriber.rs new file mode 100644 index 0000000..44645ad --- /dev/null +++ b/common/common_subscriber/src/common_subscriber.rs @@ -0,0 +1,119 @@ +#![no_std] + +use subscription_fee::{ + service::ProxyTrait as _, + subtract_payments::{Epoch, ProxyTrait as _, ScResult}, +}; + +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); + +#[derive(TypeAbi, TopEncode, TopDecode)] +pub struct UserFees { + pub fees: EsdtTokenPayment, + pub epoch: Epoch, +} + +#[multiversx_sc::module] +pub trait CommonSubscriberModule { + fn base_init(&self, fees_contract_address: ManagedAddress) { + require!( + self.blockchain().is_smart_contract(&fees_contract_address), + "Invalid address" + ); + + self.fees_contract_address().set(fees_contract_address); + } + + /// Arguments are MultiValue3 of opt_payment_token, payment_amount and subscription_epochs + #[only_owner] + #[endpoint(registerService)] + fn register_service( + &self, + args: MultiValueEncoded, BigUint, Epoch>>, + ) { + let wegld_token_id = self.wegld_token_id().get(); + + for arg in args.clone() { + let (token_id_opt, _, _) = arg.into_tuple(); + require!(token_id_opt.is_some(), "Invalid payment token"); + require!( + token_id_opt.unwrap() == wegld_token_id, + "Payment token must be WEGLD" + ); + } + + let mut proxy_instance = self.get_subscription_fee_sc_proxy_instance(); + let _: () = proxy_instance + .register_service(args) + .execute_on_dest_context(); + } + + #[only_owner] + #[endpoint(unregisterService)] + fn unregister_service(&self) { + let mut proxy_instance = self.get_subscription_fee_sc_proxy_instance(); + let _: () = proxy_instance + .unregister_service() + .execute_on_dest_context(); + } + + fn subtract_user_payment( + &self, + fees_contract_address: ManagedAddress, + service_index: usize, + user_id: AddressId, + ) { + let fees_mapper = self.user_fees(service_index, user_id); + require!(fees_mapper.is_empty(), "User last fees not processed yet"); + + let subtract_result = + self.call_subtract_payment(fees_contract_address, service_index, user_id); + if let ScResult::Ok(fees) = subtract_result { + let current_epoch = self.blockchain().get_block_epoch(); + let user_fees = UserFees { + fees, + epoch: current_epoch, + }; + + fees_mapper.set(user_fees); + } + } + + fn call_subtract_payment( + &self, + fee_contract_address: ManagedAddress, + service_index: usize, + user_id: AddressId, + ) -> ScResult { + self.fee_contract_proxy_obj(fee_contract_address) + .subtract_payment(service_index, user_id) + .execute_on_dest_context() + } + + fn get_subscription_fee_sc_proxy_instance(&self) -> subscription_fee::Proxy { + let fees_contract_address = self.fees_contract_address().get(); + self.fee_contract_proxy_obj(fees_contract_address) + } + + #[proxy] + fn fee_contract_proxy_obj( + &self, + sc_address: ManagedAddress, + ) -> subscription_fee::Proxy; + + #[view(getFeesContractAddress)] + #[storage_mapper("feesContractAddress")] + fn fees_contract_address(&self) -> SingleValueMapper; + + #[storage_mapper("wegldTokenId")] + fn wegld_token_id(&self) -> SingleValueMapper; + + #[view(getUserFees)] + #[storage_mapper("userFees")] + fn user_fees( + &self, + service_index: usize, + user_id: AddressId, + ) -> SingleValueMapper>; +} diff --git a/farm-boosted-rewards-subscriber/Cargo.toml b/farm-boosted-rewards-subscriber/Cargo.toml index 69913a1..e7e0b13 100644 --- a/farm-boosted-rewards-subscriber/Cargo.toml +++ b/farm-boosted-rewards-subscriber/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "farm-boosted-rewards-subscriber" version = "0.0.0" -authors = [ "you",] +authors = ["you"] edition = "2018" publish = false @@ -9,42 +9,69 @@ publish = false path = "src/lib.rs" [dependencies.multiversx-sc] -version = "=0.43.2" +version = "=0.45.2" [dependencies.multiversx-sc-modules] -version = "=0.43.2" - -[dependencies.auto-farm] -git = "https://github.com/multiversx/mx-exchange-tools-sc" -rev = "39e355f" +version = "=0.45.2" [dependencies.subscription-fee] path = "../subscription-fee" -[dependencies.subscriber] -path = "../subscriber" +[dependencies.common_subscriber] +path = "../common/common_subscriber" + +[dependencies.common_structs] +path = "../common/common_structs" [dependencies.energy-query] git = "https://github.com/multiversx/mx-exchange-sc" -rev = "7f25a72" +rev = "1fb9a1d" [dependencies.energy-factory] git = "https://github.com/multiversx/mx-exchange-sc" -rev = "7f25a72" +rev = "1fb9a1d" [dependencies.pair] git = "https://github.com/multiversx/mx-exchange-sc" -rev = "7f25a72" +rev = "1fb9a1d" -[dev-dependencies.pausable] +[dependencies.farm-with-locked-rewards] git = "https://github.com/multiversx/mx-exchange-sc" -rev = "7f25a72" +rev = "1fb9a1d" -[dev-dependencies.multiversx-sc-scenario] -version = "=0.43.2" +[dependencies.config] +git = "https://github.com/multiversx/mx-exchange-sc" +rev = "1fb9a1d" [dev-dependencies] num-bigint = "0.4.2" num-traits = "0.2" hex = "0.4" hex-literal = "0.3.4" + +[dev-dependencies.farm-boosted-yields] +git = "https://github.com/multiversx/mx-exchange-sc" +rev = "1fb9a1d" + +[dev-dependencies.pausable] +git = "https://github.com/multiversx/mx-exchange-sc" +rev = "1fb9a1d" + +[dev-dependencies.farm_token] +git = "https://github.com/multiversx/mx-exchange-sc" +rev = "1fb9a1d" + +[dev-dependencies.sc_whitelist_module] +git = "https://github.com/multiversx/mx-exchange-sc" +rev = "1fb9a1d" + +[dev-dependencies.simple-lock] +git = "https://github.com/multiversx/mx-exchange-sc" +rev = "1fb9a1d" + +[dev-dependencies.locking_module] +git = "https://github.com/multiversx/mx-exchange-sc" +rev = "1fb9a1d" + +[dev-dependencies.multiversx-sc-scenario] +version = "=0.45.2" diff --git a/farm-boosted-rewards-subscriber/meta/Cargo.toml b/farm-boosted-rewards-subscriber/meta/Cargo.toml index e7c5204..65a5734 100644 --- a/farm-boosted-rewards-subscriber/meta/Cargo.toml +++ b/farm-boosted-rewards-subscriber/meta/Cargo.toml @@ -3,7 +3,7 @@ name = "farm-boosted-rewards-subscriber-meta" version = "0.0.0" edition = "2018" publish = false -authors = [ "you",] +authors = ["you"] [dev-dependencies] @@ -11,4 +11,5 @@ authors = [ "you",] path = ".." [dependencies.multiversx-sc-meta] -version = "=0.43.2" +version = "=0.45.2" +default-features = false diff --git a/farm-boosted-rewards-subscriber/src/buy_mex.rs b/farm-boosted-rewards-subscriber/src/buy_mex.rs deleted file mode 100644 index 1d3b62b..0000000 --- a/farm-boosted-rewards-subscriber/src/buy_mex.rs +++ /dev/null @@ -1,280 +0,0 @@ -use auto_farm::common::unique_payments::UniquePayments; -use multiversx_sc_modules::ongoing_operation::{CONTINUE_OP, STOP_OP}; -use subscription_fee::subtract_payments::Epoch; - -multiversx_sc::imports!(); -multiversx_sc::derive_imports!(); - -pub type Percentage = u32; -pub const TOTAL_PERCENTAGE: Percentage = 10_000; -pub const BUY_MEX_COST: u64 = 20_000_000; -pub const LOCK_GAS_PER_USER: u64 = 7_000_000; - -#[derive(TypeAbi, TopEncode, TopDecode)] -pub struct MexActionsPercentages { - pub lock: Percentage, - pub fees: Percentage, - pub mex_burn: Percentage, -} - -pub struct MexActionsValue { - pub lock: BigUint, - pub fees: BigUint, - pub mex_burn: BigUint, -} - -impl MexActionsPercentages { - pub fn is_valid(&self) -> bool { - self.lock + self.fees + self.mex_burn == TOTAL_PERCENTAGE - } - - pub fn get_amounts_per_category( - &self, - total: &BigUint, - ) -> MexActionsValue { - let lock_amount = total * self.lock / TOTAL_PERCENTAGE; - let fees_amount = total * self.fees / TOTAL_PERCENTAGE; - let mex_burn_amount = total - &lock_amount - &fees_amount; - - MexActionsValue { - lock: lock_amount, - fees: fees_amount, - mex_burn: mex_burn_amount, - } - } -} - -impl MexActionsValue { - pub fn get_total_mex(&self) -> BigUint { - &self.lock + &self.mex_burn - } -} - -// dummy data is there so we don't accidentally deserialize another struct -#[derive(Default, TopEncode, TopDecode)] -pub struct MexOperationsProgress { - pub service_index: usize, - pub user_index: usize, - pub dummy_data: u8, -} - -#[multiversx_sc::module] -pub trait BuyMexModule: - subscriber::service::ServiceModule - + subscriber::common_storage::CommonStorageModule - + multiversx_sc_modules::ongoing_operation::OngoingOperationModule -{ - #[only_owner] - #[endpoint(addMexPair)] - fn add_mex_pair(&self, token_id: TokenIdentifier, pair_address: ManagedAddress) { - require!(token_id.is_valid_esdt_identifier(), "Invalid token ID"); - require!( - self.blockchain().is_smart_contract(&pair_address), - "Invalid pair address" - ); - - self.mex_pairs(&token_id).set(pair_address); - } - - #[only_owner] - #[endpoint(removeMexPair)] - fn remove_mex_pair(&self, token_id: TokenIdentifier) { - self.mex_pairs(&token_id).clear(); - } - - #[only_owner] - #[endpoint(performMexOperations)] - fn perform_mex_operations_endpoint(&self, service_index: usize) -> OperationCompletionStatus { - let actions_percentage = if service_index == 0 { - self.normal_user_percentage().get() - } else { - self.premium_user_percentage().get() - }; - - let mut gas_per_user = BUY_MEX_COST; - if actions_percentage.lock > 0 { - gas_per_user += LOCK_GAS_PER_USER; - } - - let mut progress = self.load_operation::(); - if progress.user_index == 0 { - progress.user_index = 1; - progress.service_index = service_index; - } else { - require!( - progress.service_index == service_index, - "Another operation in progress" - ); - } - - let own_address = self.blockchain().get_sc_address(); - let fees_contract_address = self.fees_contract_address().get(); - let service_id = self - .service_id() - .get_id_at_address_non_zero(&fees_contract_address, &own_address); - - let users_mapper = self.subscribed_users(service_id, service_index); - let total_users = users_mapper.len_at_address(&fees_contract_address); - - let mut total_gas_cost = 0; - let _ = self.run_while_it_has_gas(0, || { - let remaining_gas = self.blockchain().get_gas_left(); - if total_gas_cost + gas_per_user > remaining_gas || progress.user_index > total_users { - return STOP_OP; - } - - total_gas_cost += gas_per_user; - - let user_id = - users_mapper.get_by_index_at_address(&fees_contract_address, progress.user_index); - progress.user_index += 1; - - let opt_user_address = self - .user_id() - .get_address_at_address(&fees_contract_address, user_id); - if opt_user_address.is_none() { - return CONTINUE_OP; - } - - let fee_mapper = self.user_fees(service_index, user_id); - if fee_mapper.is_empty() { - return CONTINUE_OP; - } - - let fee = fee_mapper.take(); - let token_id = if fee.fees.token_identifier.is_egld() { - // TODO: Wrap egld and take cost into consideration - TokenIdentifier::from("PLACEHOLDER") - } else { - fee.fees.token_identifier.unwrap_esdt() - }; - - let user_address = unsafe { opt_user_address.unwrap_unchecked() }; - self.perform_mex_operations( - user_address, - token_id, - fee.fees.amount, - &actions_percentage, - ); - - CONTINUE_OP - }); - - if progress.user_index <= total_users { - self.save_progress(&progress); - - OperationCompletionStatus::InterruptedBeforeOutOfGas - } else { - OperationCompletionStatus::Completed - } - } - - fn perform_mex_operations( - &self, - user_address: ManagedAddress, - token_id: TokenIdentifier, - total_tokens: BigUint, - actions_percentages: &MexActionsPercentages, - ) { - let actions_value = actions_percentages.get_amounts_per_category(&total_tokens); - let total_mex_to_buy = actions_value.get_total_mex(); - - if actions_value.fees > 0 { - self.total_fees().update(|fees| { - fees.add_payment(EsdtTokenPayment::new( - token_id.clone(), - 0, - actions_value.fees.clone(), - )) - }); - } - - let bought_mex = self.buy_mex(token_id, total_mex_to_buy); - let mex_to_lock = &bought_mex.amount * actions_percentages.lock / TOTAL_PERCENTAGE; - let mex_to_burn = bought_mex.amount - &mex_to_lock; - - if mex_to_burn > 0 { - self.send() - .esdt_local_burn(&bought_mex.token_identifier, 0, &mex_to_burn); - } - - if mex_to_lock == 0 { - return; - } - - let simple_lock_address = self.simple_lock_address().get(); - let lock_period = self.lock_period().get(); - let _ = self.call_lock_tokens( - simple_lock_address, - EsdtTokenPayment::new(bought_mex.token_identifier, 0, mex_to_lock), - lock_period, - user_address, - ); - } - - fn buy_mex(&self, token_id: TokenIdentifier, amount: BigUint) -> EsdtTokenPayment { - let pair_mapper = self.mex_pairs(&token_id); - require!(!pair_mapper.is_empty(), "No pair set for token"); - - let mex_token_id = self.mex_token_id().get(); - let pair_address = pair_mapper.get(); - - self.call_swap_to_mex(pair_address, mex_token_id, token_id, amount) - } - - fn call_swap_to_mex( - &self, - pair_address: ManagedAddress, - mex_token_id: TokenIdentifier, - input_token_id: TokenIdentifier, - amount: BigUint, - ) -> EsdtTokenPayment { - self.other_pair_proxy(pair_address) - .swap_tokens_fixed_input(mex_token_id, BigUint::from(1u32)) - .with_esdt_transfer(EsdtTokenPayment::new(input_token_id, 0, amount)) - .execute_on_dest_context() - } - - fn call_lock_tokens( - &self, - simple_lock_address: ManagedAddress, - input_tokens: EsdtTokenPayment, - lock_epochs: Epoch, - destination: ManagedAddress, - ) -> EsdtTokenPayment { - self.simple_lock_proxy(simple_lock_address) - .lock_tokens_endpoint(lock_epochs, destination) - .with_esdt_transfer(input_tokens) - .execute_on_dest_context() - } - - #[proxy] - fn other_pair_proxy(&self, sc_address: ManagedAddress) -> pair::Proxy; - - #[proxy] - fn simple_lock_proxy(&self, sc_address: ManagedAddress) -> energy_factory::Proxy; - - #[storage_mapper("mexTokenId")] - fn mex_token_id(&self) -> SingleValueMapper; - - #[storage_mapper("mexPairs")] - fn mex_pairs(&self, token_id: &TokenIdentifier) -> SingleValueMapper; - - #[storage_mapper("simpleLockAddress")] - fn simple_lock_address(&self) -> SingleValueMapper; - - #[storage_mapper("lockPeriod")] - fn lock_period(&self) -> SingleValueMapper; - - #[view(getNormalUserPercentage)] - #[storage_mapper("normalUserPercentage")] - fn normal_user_percentage(&self) -> SingleValueMapper; - - #[view(getPremiumUserPercentage)] - #[storage_mapper("premiumUserPercentage")] - fn premium_user_percentage(&self) -> SingleValueMapper; - - #[view(getTotalFees)] - #[storage_mapper("totalFees")] - fn total_fees(&self) -> SingleValueMapper>; -} diff --git a/farm-boosted-rewards-subscriber/src/claim_farm_boosted.rs b/farm-boosted-rewards-subscriber/src/claim_farm_boosted.rs index 3dd75e8..7ffee7b 100644 --- a/farm-boosted-rewards-subscriber/src/claim_farm_boosted.rs +++ b/farm-boosted-rewards-subscriber/src/claim_farm_boosted.rs @@ -1,40 +1,83 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); -mod claim_farm_boosted_rewards_proxy { - multiversx_sc::imports!(); +use crate::events; +use crate::events::ClaimRewardsOperation; +use crate::service; +use crate::subscriber_config; +use crate::subscriber_config::SubscriptionUserType; - #[multiversx_sc::proxy] - pub trait ClaimFarmBoostedRewardsProxy { - #[endpoint(claimBoostedRewards)] - fn claim_boosted_rewards(&self, user: ManagedAddress) -> EsdtTokenPayment; - } -} +#[multiversx_sc::module] +pub trait ClaimFarmBoostedRewardsModule: + subscriber_config::SubscriberConfigModule + + service::ServiceModule + + common_subscriber::CommonSubscriberModule + + energy_query::EnergyQueryModule + + events::EventsModule +{ + #[only_owner] + #[endpoint(addFarm)] + fn add_farm(&self, farm_address: ManagedAddress) -> AddressId { + require!( + self.blockchain().is_smart_contract(&farm_address), + "Invalid farm address" + ); -#[derive(ManagedVecItem, Clone)] -pub struct AdditionalFarmData { - pub dummy_data: u8, -} + self.farm_id().insert_new(&farm_address) + } -#[multiversx_sc::module] -pub trait ClaimFarmBoostedRewardsModule { - fn claim_farm_boosted_rewards( - &self, - farm_address: ManagedAddress, - user: ManagedAddress, - ) -> EsdtTokenPayment { - self.farm_proxy_obj(farm_address) - .claim_boosted_rewards(user) - .execute_on_dest_context() + #[only_owner] + #[endpoint(removeFarm)] + fn remove_farm(&self, farm_address: ManagedAddress) -> AddressId { + self.farm_id().remove_by_address(&farm_address) } - #[proxy] - fn farm_proxy_obj( + #[endpoint(performClaimRewardsOperations)] + fn perform_claim_rewards_operations_endpoint( &self, - sc_address: ManagedAddress, - ) -> claim_farm_boosted_rewards_proxy::Proxy; + service_index: usize, + user_farms_pairs_to_claim: MultiValueEncoded>>, + ) { + require!( + service_index == SubscriptionUserType::Normal as usize + || service_index == SubscriptionUserType::Premium as usize, + "Invalid service index" + ); - #[view(getEnergyThreshold)] - #[storage_mapper("energyThreshold")] - fn energy_threshold(&self) -> SingleValueMapper; + let fees_contract_address = self.fees_contract_address().get(); + + let mut claim_reward_operations = ManagedVec::new(); + for user_farms_pair in user_farms_pairs_to_claim { + let (user_id, farms_ids) = user_farms_pair.into_tuple(); + + let opt_user = self + .user_id() + .get_address_at_address(&fees_contract_address, user_id); + if opt_user.is_none() { + continue; + } + let user = opt_user.unwrap(); + + let mut processed_farms = ManagedVec::new(); + for farm_id in &farms_ids { + let farm_address_opt = self.farm_id().get_address(farm_id); + if farm_address_opt.is_some() { + let farm_address = farm_address_opt.unwrap(); + if !self + .get_user_allow_claim_boosted_rewards(farm_address.clone(), user.clone()) + { + continue; + } + self.claim_boosted_rewards(farm_address, user.clone()); + processed_farms.push(farm_id); + } + } + + if !processed_farms.is_empty() { + claim_reward_operations.push(ClaimRewardsOperation::new(user, processed_farms)); + } + } + + self.emit_claim_rewards_event(claim_reward_operations); + } } diff --git a/farm-boosted-rewards-subscriber/src/events.rs b/farm-boosted-rewards-subscriber/src/events.rs new file mode 100644 index 0000000..23a9e29 --- /dev/null +++ b/farm-boosted-rewards-subscriber/src/events.rs @@ -0,0 +1,64 @@ +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); + +#[derive(ManagedVecItem, TypeAbi, TopEncode, NestedEncode)] +pub struct ClaimRewardsOperation { + user: ManagedAddress, + farm_ids: ManagedVec, +} + +impl ClaimRewardsOperation { + pub fn new(user: ManagedAddress, farm_ids: ManagedVec) -> Self { + ClaimRewardsOperation { user, farm_ids } + } +} + +#[multiversx_sc::module] +pub trait EventsModule { + fn emit_claim_rewards_event( + self, + claim_rewards_operations: ManagedVec>, + ) { + let caller = self.blockchain().get_caller(); + let epoch = self.blockchain().get_block_epoch(); + self.claim_rewards_event(caller, epoch, claim_rewards_operations) + } + + fn emit_subtract_payment_event(self, service_index: usize, user_ids: ManagedVec) { + let caller = self.blockchain().get_caller(); + let epoch = self.blockchain().get_block_epoch(); + self.subtract_payment_event(caller, epoch, service_index, user_ids) + } + + fn emit_mex_operation_event(self, service_index: usize, user_ids: ManagedVec) { + let caller = self.blockchain().get_caller(); + let epoch = self.blockchain().get_block_epoch(); + self.mex_operation_event(caller, epoch, service_index, user_ids) + } + + #[event("claimRewardsEvent")] + fn claim_rewards_event( + self, + #[indexed] caller: ManagedAddress, + #[indexed] epoch: u64, + claim_rewards_operations: ManagedVec>, + ); + + #[event("subtractPaymentEvent")] + fn subtract_payment_event( + self, + #[indexed] caller: ManagedAddress, + #[indexed] epoch: u64, + #[indexed] service_index: usize, + user_ids: ManagedVec, + ); + + #[event("mexOperationEvent")] + fn mex_operation_event( + self, + #[indexed] caller: ManagedAddress, + #[indexed] epoch: u64, + #[indexed] service_index: usize, + user_ids: ManagedVec, + ); +} diff --git a/farm-boosted-rewards-subscriber/src/lib.rs b/farm-boosted-rewards-subscriber/src/lib.rs index 6c64fb2..3903bc2 100644 --- a/farm-boosted-rewards-subscriber/src/lib.rs +++ b/farm-boosted-rewards-subscriber/src/lib.rs @@ -1,33 +1,25 @@ #![no_std] -#![feature(trait_alias)] - -use core::marker::PhantomData; - -use auto_farm::common::{address_to_id_mapper::AddressId, unique_payments::UniquePayments}; -use buy_mex::MexActionsPercentages; -use subscriber::base_functions::{AllBaseTraits, InterpretedResult, SubscriberContract}; -use subscription_fee::{service::ServiceInfo, subtract_payments::Epoch}; - -use crate::claim_farm_boosted::AdditionalFarmData; multiversx_sc::imports!(); multiversx_sc::derive_imports!(); -pub const GAS_TO_SAVE_PERFORM_ACTION_PROGRESS: u64 = 100_000; +use common_structs::UniquePayments; +use subscriber_config::MexActionsPercentages; +use subscription_fee::subtract_payments::Epoch; -pub mod buy_mex; pub mod claim_farm_boosted; +pub mod events; +pub mod service; +pub mod subscriber_config; #[multiversx_sc::contract] pub trait SubscriberContractMain: - claim_farm_boosted::ClaimFarmBoostedRewardsModule - + buy_mex::BuyMexModule - + subscriber::base_init::BaseInitModule - + subscriber::service::ServiceModule - + subscriber::daily_operations::DailyOperationsModule - + subscriber::common_storage::CommonStorageModule + subscriber_config::SubscriberConfigModule + + claim_farm_boosted::ClaimFarmBoostedRewardsModule + + service::ServiceModule + + common_subscriber::CommonSubscriberModule + energy_query::EnergyQueryModule - + multiversx_sc_modules::ongoing_operation::OngoingOperationModule + + events::EventsModule { /// Percentages must add up to 10,000 each, where 10,000 = 100% /// Lock period is number of epochs the tokens should be locked for @@ -37,12 +29,18 @@ pub trait SubscriberContractMain: fees_contract_address: ManagedAddress, energy_threshold: BigUint, mex_token_id: TokenIdentifier, + wegld_token_id: TokenIdentifier, normal_user_percentages: MexActionsPercentages, premium_user_percentages: MexActionsPercentages, simple_lock_address: ManagedAddress, + mex_pair_address: ManagedAddress, lock_period: Epoch, ) { require!(mex_token_id.is_valid_esdt_identifier(), "Invalid token ID"); + require!( + wegld_token_id.is_valid_esdt_identifier(), + "Invalid token ID" + ); require!( normal_user_percentages.is_valid() && premium_user_percentages.is_valid(), "Invalid percentages" @@ -51,91 +49,49 @@ pub trait SubscriberContractMain: self.blockchain().is_smart_contract(&simple_lock_address), "Invalid address" ); + require!( + self.blockchain().is_smart_contract(&mex_pair_address), + "Invalid pair address" + ); - self.base_init(fees_contract_address); - self.energy_threshold().set(energy_threshold); - self.mex_token_id().set(mex_token_id); - self.normal_user_percentage().set(normal_user_percentages); - self.premium_user_percentage().set(premium_user_percentages); - self.simple_lock_address().set(simple_lock_address); - self.lock_period().set(lock_period); - - self.total_fees().set(UniquePayments::new()); - } - - #[endpoint(performAction)] - fn perform_action_endpoint( - &self, - service_index: usize, - users_to_claim: MultiValueEncoded, - ) -> OperationCompletionStatus { - require!(service_index <= 1, "invalid index"); - - let total_users = users_to_claim.len(); - let mut args_vec = ManagedVec::new(); - for _ in 0..total_users { - args_vec.push(AdditionalFarmData { dummy_data: 0 }); - } - - let own_address = self.blockchain().get_sc_address(); - let fees_contract_address = self.fees_contract_address().get(); - let service_id = self - .service_id() - .get_id_at_address_non_zero(&fees_contract_address, &own_address); + let first_token_id = self.first_token_id().get_from_address(&mex_pair_address); + let second_token_id = self.second_token_id().get_from_address(&mex_pair_address); - let mut user_index = self.get_user_index(&fees_contract_address, service_id, service_index); - let run_result = self.perform_service::>( - GAS_TO_SAVE_PERFORM_ACTION_PROGRESS, - service_index, - &mut user_index, - args_vec, + require!( + first_token_id == wegld_token_id || first_token_id == mex_token_id, + "Wrong pair address" + ); + require!( + second_token_id == wegld_token_id || second_token_id == mex_token_id, + "Wrong pair address" ); - self.user_index().set(user_index); - - run_result + self.base_init(fees_contract_address); + self.energy_threshold().set_if_empty(energy_threshold); + self.mex_token_id().set_if_empty(mex_token_id); + self.wegld_token_id().set_if_empty(wegld_token_id); + self.normal_user_percentage() + .set_if_empty(normal_user_percentages); + self.premium_user_percentage() + .set_if_empty(premium_user_percentages); + self.simple_lock_address().set_if_empty(simple_lock_address); + self.mex_pair().set_if_empty(mex_pair_address); + self.lock_period().set_if_empty(lock_period); + self.total_fees().set_if_empty(UniquePayments::new()); } -} -pub struct FarmClaimBoostedWrapper< - T: AllBaseTraits - + buy_mex::BuyMexModule - + claim_farm_boosted::ClaimFarmBoostedRewardsModule - + energy_query::EnergyQueryModule, -> { - _phantom: PhantomData, -} - -impl SubscriberContract for FarmClaimBoostedWrapper -where - T: AllBaseTraits - + buy_mex::BuyMexModule - + claim_farm_boosted::ClaimFarmBoostedRewardsModule - + energy_query::EnergyQueryModule, -{ - type SubSc = T; - type AdditionalDataType = AdditionalFarmData; - - fn perform_action( - sc: &Self::SubSc, - user_address: ManagedAddress<::Api>, - service_index: usize, - service_info: &ServiceInfo<::Api>, - _additional_data: &::AdditionalDataType, - ) -> Result::Api>, ()> { - if service_index == 1 { - let user_energy = sc.get_energy_amount(&user_address); - let energy_threshold = sc.energy_threshold().get(); - if user_energy < energy_threshold { - return Result::Err(()); - } - } + #[upgrade] + fn upgrade(&self) {} - let _ = sc.claim_farm_boosted_rewards(service_info.sc_address.clone(), user_address); + #[only_owner] + #[endpoint(setLockPeriod)] + fn set_lock_period(&self, lock_period: Epoch) { + self.lock_period().set(lock_period); + } - // farm already sent rewards to user - Result::Ok(InterpretedResult { - user_rewards: ManagedVec::new(), - }) + #[only_owner] + #[endpoint(setEnergyThreshold)] + fn set_energy_threshold(&self, energy_threshold: BigUint) { + self.energy_threshold().set(energy_threshold); } } diff --git a/farm-boosted-rewards-subscriber/src/service.rs b/farm-boosted-rewards-subscriber/src/service.rs new file mode 100644 index 0000000..fa87e22 --- /dev/null +++ b/farm-boosted-rewards-subscriber/src/service.rs @@ -0,0 +1,217 @@ +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); + +use crate::{ + events, + subscriber_config::{self, MexActionsPercentages, SubscriptionUserType}, +}; + +#[derive(ManagedVecItem, TypeAbi, TopEncode, TopDecode, PartialEq)] +pub struct MexOperationItem { + pub user_address: ManagedAddress, + pub amount: BigUint, +} + +impl MexOperationItem { + pub fn new(user_address: ManagedAddress, amount: BigUint) -> Self { + MexOperationItem { + user_address, + amount, + } + } +} + +#[multiversx_sc::module] +pub trait ServiceModule: + subscriber_config::SubscriberConfigModule + + common_subscriber::CommonSubscriberModule + + energy_query::EnergyQueryModule + + events::EventsModule +{ + #[only_owner] + #[endpoint(subtractPayment)] + fn subtract_payment_endpoint( + &self, + service_index: usize, + user_ids: MultiValueEncoded, + ) { + require!( + service_index == SubscriptionUserType::Normal as usize + || service_index == SubscriptionUserType::Premium as usize, + "Invalid service index" + ); + let is_premium_service = service_index == SubscriptionUserType::Premium as usize; + let energy_threshold = self.energy_threshold().get(); + let fees_contract_address = self.fees_contract_address().get(); + let mut processed_user_ids = ManagedVec::new(); + + for user_id in user_ids { + if is_premium_service { + let opt_user_address = self + .user_id() + .get_address_at_address(&fees_contract_address, user_id); + if opt_user_address.is_none() { + continue; + } + let user = opt_user_address.unwrap(); + let user_energy = self.get_energy_amount(&user); + + if user_energy < energy_threshold { + continue; + } + } + + self.subtract_user_payment(fees_contract_address.clone(), service_index, user_id); + processed_user_ids.push(user_id); + } + + self.emit_subtract_payment_event(service_index, processed_user_ids); + } + + #[only_owner] + #[endpoint(claimFees)] + fn claim_fees(&self) -> ManagedVec { + let caller = self.blockchain().get_caller(); + let total_fees = self.total_fees().take().into_payments(); + self.send().direct_multi(&caller, &total_fees); + + total_fees + } + + #[only_owner] + #[endpoint(performMexOperations)] + fn perform_mex_operations_endpoint( + &self, + service_index: usize, + total_min_amount_out: BigUint, + user_ids: MultiValueEncoded, + ) { + let actions_percentage = if service_index == SubscriptionUserType::Normal as usize { + self.normal_user_percentage().get() + } else if service_index == SubscriptionUserType::Premium as usize { + self.premium_user_percentage().get() + } else { + sc_panic!("Invalid service index") + }; + + let fees_contract_address = self.fees_contract_address().get(); + let wegld_token_id = self.wegld_token_id().get(); + + let mut total_fees = BigUint::zero(); + let mut mex_operations_list: ManagedVec> = ManagedVec::new(); + let mut processed_user_ids = ManagedVec::new(); + for user_id in user_ids { + let opt_user_address = self + .user_id() + .get_address_at_address(&fees_contract_address, user_id); + if opt_user_address.is_none() { + continue; + } + + let fee_mapper = self.user_fees(service_index, user_id); + if fee_mapper.is_empty() { + continue; + } + + let fee = fee_mapper.take(); + let token_id = fee.fees.token_identifier; + require!(token_id == wegld_token_id, "Invalid fee token id"); + let user_address = unsafe { opt_user_address.unwrap_unchecked() }; + + total_fees += &fee.fees.amount; + let mex_operation = MexOperationItem::new(user_address, fee.fees.amount); + mex_operations_list.push(mex_operation); + processed_user_ids.push(user_id); + } + + let total_tokens_to_lock = self.perform_mex_operation( + wegld_token_id, + total_fees.clone(), + &actions_percentage, + total_min_amount_out, + ); + + if total_tokens_to_lock.amount == 0 { + return; + } + + let simple_lock_address = self.simple_lock_address().get(); + let lock_period = self.lock_period().get(); + + // Call lock for each user to properly update their energy + let mut total_processed_amount = BigUint::zero(); + for i in 0..mex_operations_list.len() { + let mex_operation = mex_operations_list.get(i); + let user_amount = if i < mex_operations_list.len() - 1 { + let amount = &total_tokens_to_lock.amount * &mex_operation.amount / &total_fees; + total_processed_amount += &amount; + amount + } else { + &total_tokens_to_lock.amount - &total_processed_amount + }; + + if user_amount > 0 { + self.call_lock_tokens( + simple_lock_address.clone(), + EsdtTokenPayment::new( + total_tokens_to_lock.token_identifier.clone(), + 0, + user_amount, + ), + lock_period, + mex_operation.user_address, + ); + } + } + + self.emit_mex_operation_event(service_index, processed_user_ids); + } + + fn perform_mex_operation( + &self, + token_id: TokenIdentifier, + total_tokens: BigUint, + actions_percentages: &MexActionsPercentages, + total_min_amount_out: BigUint, + ) -> EsdtTokenPayment { + let actions_value = actions_percentages.get_amounts_per_category(&total_tokens); + let total_sell_amount = actions_value.get_sell_amount(); + + if actions_value.fees > 0 { + self.total_fees().update(|fees| { + fees.add_payment(EsdtTokenPayment::new( + token_id.clone(), + 0, + actions_value.fees.clone(), + )) + }); + } + + let bought_mex = self.buy_mex(token_id, total_sell_amount, total_min_amount_out); + let mex_to_lock = &bought_mex.amount * actions_percentages.lock + / (actions_percentages.lock + actions_percentages.burn); + let mex_to_burn = &bought_mex.amount - &mex_to_lock; + + if mex_to_burn > 0 { + self.send() + .esdt_local_burn(&bought_mex.token_identifier, 0, &mex_to_burn); + } + + EsdtTokenPayment::new(bought_mex.token_identifier, 0, mex_to_lock) + } + + fn buy_mex( + &self, + token_id: TokenIdentifier, + amount: BigUint, + min_amount_out: BigUint, + ) -> EsdtTokenPayment { + let pair_mapper = self.mex_pair(); + require!(!pair_mapper.is_empty(), "The MEX pair is not set"); + + let mex_token_id = self.mex_token_id().get(); + let pair_address = pair_mapper.get(); + + self.call_swap_to_mex(pair_address, mex_token_id, token_id, amount, min_amount_out) + } +} diff --git a/farm-boosted-rewards-subscriber/src/subscriber_config.rs b/farm-boosted-rewards-subscriber/src/subscriber_config.rs new file mode 100644 index 0000000..21ec7f1 --- /dev/null +++ b/farm-boosted-rewards-subscriber/src/subscriber_config.rs @@ -0,0 +1,163 @@ +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); + +use common_structs::UniquePayments; +use config::ProxyTrait as _; +use subscription_fee::subtract_payments::Epoch; + +pub type Percentage = u32; +pub const TOTAL_PERCENTAGE: Percentage = 10_000; + +#[derive(TypeAbi, TopEncode, TopDecode, PartialEq)] +pub enum SubscriptionUserType { + Normal, + Premium, +} + +#[derive(TypeAbi, TopEncode, TopDecode)] +pub struct MexActionsPercentages { + pub lock: Percentage, + pub fees: Percentage, + pub burn: Percentage, +} + +pub struct MexActionsValue { + pub lock: BigUint, + pub fees: BigUint, + pub burn: BigUint, +} + +impl MexActionsPercentages { + pub fn is_valid(&self) -> bool { + self.lock + self.fees + self.burn == TOTAL_PERCENTAGE + && self.lock <= TOTAL_PERCENTAGE + && self.fees <= TOTAL_PERCENTAGE + && self.burn <= TOTAL_PERCENTAGE + } + + pub fn get_amounts_per_category( + &self, + total: &BigUint, + ) -> MexActionsValue { + let lock_amount = total * self.lock / TOTAL_PERCENTAGE; + let fees_amount = total * self.fees / TOTAL_PERCENTAGE; + let burn_amount = total - &lock_amount - &fees_amount; + + MexActionsValue { + lock: lock_amount, + fees: fees_amount, + burn: burn_amount, + } + } +} + +impl MexActionsValue { + pub fn get_sell_amount(&self) -> BigUint { + &self.lock + &self.burn + } +} + +#[multiversx_sc::module] +pub trait SubscriberConfigModule { + fn call_swap_to_mex( + &self, + pair_address: ManagedAddress, + mex_token_id: TokenIdentifier, + input_token_id: TokenIdentifier, + amount: BigUint, + min_amount_out: BigUint, + ) -> EsdtTokenPayment { + self.other_pair_proxy(pair_address) + .swap_tokens_fixed_input(mex_token_id, min_amount_out) + .with_esdt_transfer(EsdtTokenPayment::new(input_token_id, 0, amount)) + .execute_on_dest_context() + } + + fn call_lock_tokens( + &self, + simple_lock_address: ManagedAddress, + input_tokens: EsdtTokenPayment, + lock_epochs: Epoch, + destination: ManagedAddress, + ) -> EsdtTokenPayment { + self.simple_lock_proxy(simple_lock_address) + .lock_tokens_endpoint(lock_epochs, destination) + .with_esdt_transfer(input_tokens) + .execute_on_dest_context() + } + + fn claim_boosted_rewards( + &self, + sc_address: ManagedAddress, + user: ManagedAddress, + ) -> EsdtTokenPayment { + self.farm_proxy_obj(sc_address) + .claim_boosted_rewards(user) + .execute_on_dest_context() + } + + fn get_user_allow_claim_boosted_rewards( + &self, + sc_address: ManagedAddress, + user: ManagedAddress, + ) -> bool { + self.farm_proxy_obj(sc_address) + .get_allow_external_claim_rewards(user) + .execute_on_dest_context() + } + + #[proxy] + fn other_pair_proxy(&self, sc_address: ManagedAddress) -> pair::Proxy; + + #[proxy] + fn simple_lock_proxy(&self, sc_address: ManagedAddress) -> energy_factory::Proxy; + + #[proxy] + fn farm_proxy_obj( + &self, + sc_address: ManagedAddress, + ) -> farm_with_locked_rewards::Proxy; + + #[storage_mapper("mexTokenId")] + fn mex_token_id(&self) -> SingleValueMapper; + + #[storage_mapper("mexPair")] + fn mex_pair(&self) -> SingleValueMapper; + + #[view(getSimpleLockAddress)] + #[storage_mapper("simpleLockAddress")] + fn simple_lock_address(&self) -> SingleValueMapper; + + #[view(getLockPeriod)] + #[storage_mapper("lockPeriod")] + fn lock_period(&self) -> SingleValueMapper; + + #[view(getNormalUserPercentage)] + #[storage_mapper("normalUserPercentage")] + fn normal_user_percentage(&self) -> SingleValueMapper; + + #[view(getPremiumUserPercentage)] + #[storage_mapper("premiumUserPercentage")] + fn premium_user_percentage(&self) -> SingleValueMapper; + + #[view(getTotalFees)] + #[storage_mapper("totalFees")] + fn total_fees(&self) -> SingleValueMapper>; + + #[view(getEnergyThreshold)] + #[storage_mapper("energyThreshold")] + fn energy_threshold(&self) -> SingleValueMapper; + + #[storage_mapper("farmId")] + fn farm_id(&self) -> AddressToIdMapper; + + // used for external storage read + #[storage_mapper("userId")] + fn user_id(&self) -> AddressToIdMapper; + + #[storage_mapper("first_token_id")] + fn first_token_id(&self) -> SingleValueMapper; + + #[storage_mapper("second_token_id")] + fn second_token_id(&self) -> SingleValueMapper; +} diff --git a/farm-boosted-rewards-subscriber/tests/farm_setup/mod.rs b/farm-boosted-rewards-subscriber/tests/farm_setup/mod.rs new file mode 100644 index 0000000..68e5828 --- /dev/null +++ b/farm-boosted-rewards-subscriber/tests/farm_setup/mod.rs @@ -0,0 +1,306 @@ +#![allow(deprecated)] + +use std::cell::RefCell; +use std::rc::Rc; + +use multiversx_sc::codec::multi_types::OptionalValue; +use multiversx_sc::storage::mappers::StorageTokenWrapper; +use multiversx_sc::types::{Address, BigInt, EsdtLocalRole, ManagedAddress, MultiValueEncoded}; +use multiversx_sc_modules::pause::PauseModule; +use multiversx_sc_scenario::testing_framework::TxResult; +use multiversx_sc_scenario::{ + managed_address, managed_biguint, managed_token_id, rust_biguint, + testing_framework::{BlockchainStateWrapper, ContractObjWrapper}, + DebugApi, +}; + +use config::ConfigModule; +use energy_factory::{energy::EnergyModule, *}; +use energy_query::{Energy, EnergyQueryModule}; +use farm_boosted_yields::{ + boosted_yields_factors::BoostedYieldsFactorsModule, FarmBoostedYieldsModule, +}; +use farm_token::FarmTokenModule; +use farm_with_locked_rewards::*; +use locking_module::lock_with_energy_module::LockWithEnergyModule; +use pausable::{PausableModule, State}; +use sc_whitelist_module::SCWhitelistModule; +use simple_lock::locked_token::LockedTokenModule; + +const DIV_SAFETY: u64 = 1_000_000_000_000_000_000; +const PER_BLOCK_REWARD_AMOUNT: u64 = 1_000; +const EPOCHS_IN_YEAR: u64 = 360; +static LOCK_OPTIONS: &[u64] = &[EPOCHS_IN_YEAR, 2 * EPOCHS_IN_YEAR, 4 * EPOCHS_IN_YEAR]; +static PENALTY_PERCENTAGES: &[u64] = &[4_000, 6_000, 8_000]; +const MAX_REWARDS_FACTOR: u64 = 10; +const USER_REWARDS_ENERGY_CONST: u64 = 3; +const USER_REWARDS_FARM_CONST: u64 = 2; +const MIN_ENERGY_AMOUNT_FOR_BOOSTED_YIELDS: u64 = 1; +const MIN_FARM_AMOUNT_FOR_BOOSTED_YIELDS: u64 = 1; + +static FARM_TOKEN_ID: &[u8] = b"FARM-123456"; + +pub struct FarmSetup +where + FarmObjBuilder: 'static + Copy + Fn() -> farm_with_locked_rewards::ContractObj, + EnergyFactoryBuilder: 'static + Copy + Fn() -> energy_factory::ContractObj, +{ + pub b_mock: Rc>, + pub farm_wrapper: + ContractObjWrapper, FarmObjBuilder>, + pub energy_factory_wrapper: + ContractObjWrapper, EnergyFactoryBuilder>, +} + +impl FarmSetup +where + FarmObjBuilder: 'static + Copy + Fn() -> farm_with_locked_rewards::ContractObj, + EnergyFactoryBuilder: 'static + Copy + Fn() -> energy_factory::ContractObj, +{ + #[allow(clippy::too_many_arguments)] + pub fn new( + b_mock: Rc>, + owner: &Address, + reward_token_id: &[u8], + locked_token_id: &[u8], + farming_token_id: &[u8], + boosted_yields_percentage: u64, + pair_address: &Address, + farm_builder: FarmObjBuilder, + energy_factory_builder: EnergyFactoryBuilder, + ) -> Self { + let rust_zero = rust_biguint!(0u64); + let farm_wrapper = b_mock.borrow_mut().create_sc_account( + &rust_zero, + Some(owner), + farm_builder, + "farm-with-locked-rewards", + ); + + let energy_factory_wrapper = b_mock.borrow_mut().create_sc_account( + &rust_zero, + Some(owner), + energy_factory_builder, + "energy-factory", + ); + + b_mock + .borrow_mut() + .execute_tx(owner, &energy_factory_wrapper, &rust_zero, |sc| { + let mut lock_options = MultiValueEncoded::new(); + for (option, penalty) in LOCK_OPTIONS.iter().zip(PENALTY_PERCENTAGES.iter()) { + lock_options.push((*option, *penalty).into()); + } + + sc.init( + managed_token_id!(reward_token_id), + managed_token_id!(reward_token_id), + managed_address!(energy_factory_wrapper.address_ref()), + 0, + lock_options, + ); + + sc.locked_token() + .set_token_id(managed_token_id!(locked_token_id)); + sc.unpause_endpoint(); + }) + .assert_ok(); + + b_mock + .borrow_mut() + .execute_tx(owner, &farm_wrapper, &rust_zero, |sc| { + sc.init( + managed_token_id!(reward_token_id), + managed_token_id!(farming_token_id), + managed_biguint!(DIV_SAFETY), + managed_address!(pair_address), + managed_address!(owner), + MultiValueEncoded::>::new(), + ); + + sc.farm_token() + .set_token_id(managed_token_id!(FARM_TOKEN_ID)); + sc.state().set(State::Active); + + sc.set_locking_sc_address(managed_address!(energy_factory_wrapper.address_ref())); + sc.set_lock_epochs(EPOCHS_IN_YEAR); + + sc.per_block_reward_amount() + .set(&managed_biguint!(PER_BLOCK_REWARD_AMOUNT)); + + sc.state().set(State::Active); + sc.produce_rewards_enabled().set(true); + sc.set_energy_factory_address(managed_address!( + energy_factory_wrapper.address_ref() + )); + }) + .assert_ok(); + + let lp_token_roles = [EsdtLocalRole::Mint, EsdtLocalRole::Burn]; + b_mock.borrow_mut().set_esdt_local_roles( + farm_wrapper.address_ref(), + farming_token_id, + &lp_token_roles[..], + ); + + let farm_token_roles = [ + EsdtLocalRole::NftCreate, + EsdtLocalRole::NftAddQuantity, + EsdtLocalRole::NftBurn, + ]; + b_mock.borrow_mut().set_esdt_local_roles( + farm_wrapper.address_ref(), + FARM_TOKEN_ID, + &farm_token_roles[..], + ); + + let farming_token_roles = [EsdtLocalRole::Burn]; + b_mock.borrow_mut().set_esdt_local_roles( + farm_wrapper.address_ref(), + farming_token_id, + &farming_token_roles[..], + ); + + let locked_reward_token_roles = [ + EsdtLocalRole::NftCreate, + EsdtLocalRole::NftAddQuantity, + EsdtLocalRole::NftBurn, + EsdtLocalRole::Transfer, + ]; + b_mock.borrow_mut().set_esdt_local_roles( + energy_factory_wrapper.address_ref(), + locked_token_id, + &locked_reward_token_roles[..], + ); + + b_mock.borrow_mut().set_esdt_local_roles( + energy_factory_wrapper.address_ref(), + reward_token_id, + &farming_token_roles[..], + ); + + b_mock + .borrow_mut() + .execute_tx(owner, &energy_factory_wrapper, &rust_zero, |sc| { + sc.sc_whitelist_addresses() + .add(&managed_address!(farm_wrapper.address_ref())); + }) + .assert_ok(); + + b_mock + .borrow_mut() + .execute_tx(owner, &farm_wrapper, &rust_biguint!(0), |sc| { + sc.set_boosted_yields_rewards_percentage(boosted_yields_percentage); + + 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(); + + FarmSetup { + b_mock, + farm_wrapper, + energy_factory_wrapper, + } + } + + pub fn enter_farm( + &mut self, + user: &Address, + farming_token_id: &[u8], + farming_token_amount: u64, + ) { + self.b_mock + .borrow_mut() + .execute_esdt_transfer( + user, + &self.farm_wrapper, + farming_token_id, + 0, + &rust_biguint!(farming_token_amount), + |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.amount, + managed_biguint!(farming_token_amount) + ); + }, + ) + .assert_ok(); + } + + pub fn claim_rewards( + &mut self, + user: &Address, + farm_token_nonce: u64, + farm_token_amount: u64, + ) -> u64 { + let mut result = 0; + self.b_mock + .borrow_mut() + .execute_esdt_transfer( + user, + &self.farm_wrapper, + FARM_TOKEN_ID, + farm_token_nonce, + &rust_biguint!(farm_token_amount), + |sc| { + let (out_farm_token, out_reward_token) = + sc.claim_rewards_endpoint(OptionalValue::None).into_tuple(); + assert_eq!( + out_farm_token.token_identifier, + managed_token_id!(FARM_TOKEN_ID) + ); + assert_eq!(out_farm_token.amount, managed_biguint!(farm_token_amount)); + + result = out_reward_token.amount.to_u64().unwrap(); + }, + ) + .assert_ok(); + + result + } + + pub fn set_user_energy( + &mut self, + user: &Address, + energy: u64, + last_update_epoch: u64, + locked_tokens: u64, + ) { + self.b_mock + .borrow_mut() + .execute_tx( + user, + &self.energy_factory_wrapper, + &rust_biguint!(0), + |sc| { + sc.user_energy(&managed_address!(user)).set(&Energy::new( + BigInt::from(managed_biguint!(energy)), + last_update_epoch, + managed_biguint!(locked_tokens), + )); + }, + ) + .assert_ok(); + } + + pub fn call_allow_external_claim_boosted_rewards( + &mut self, + user: &Address, + allow_external_claim_boosted_rewards: bool, + ) -> TxResult { + self.b_mock + .borrow_mut() + .execute_tx(user, &self.farm_wrapper, &rust_biguint!(0), |sc| { + sc.allow_external_claim_boosted_rewards(allow_external_claim_boosted_rewards); + }) + } +} diff --git a/subscriber/tests/pair_setup/mod.rs b/farm-boosted-rewards-subscriber/tests/pair_setup/mod.rs similarity index 100% rename from subscriber/tests/pair_setup/mod.rs rename to farm-boosted-rewards-subscriber/tests/pair_setup/mod.rs diff --git a/farm-boosted-rewards-subscriber/tests/subscriber_setup/mod.rs b/farm-boosted-rewards-subscriber/tests/subscriber_setup/mod.rs new file mode 100644 index 0000000..c83c583 --- /dev/null +++ b/farm-boosted-rewards-subscriber/tests/subscriber_setup/mod.rs @@ -0,0 +1,227 @@ +#![allow(clippy::too_many_arguments)] + +use std::{cell::RefCell, rc::Rc}; + +use common_subscriber::CommonSubscriberModule; +use energy_query::EnergyQueryModule; +use farm_boosted_rewards_subscriber::{ + claim_farm_boosted::ClaimFarmBoostedRewardsModule, service::ServiceModule, + subscriber_config::MexActionsPercentages, SubscriberContractMain, +}; +use multiversx_sc::{ + codec::multi_types::MultiValue2, + storage::mappers::AddressId, + types::{Address, EsdtLocalRole, ManagedVec, MultiValueEncoded}, +}; +use multiversx_sc_scenario::{ + managed_address, managed_biguint, managed_token_id, rust_biguint, + testing_framework::{BlockchainStateWrapper, ContractObjWrapper, TxResult}, + DebugApi, +}; + +pub const ENERGT_THRESHOLD: u64 = 1_000; +pub const LOCKING_PERIOD: u64 = 1_440; + +pub struct SubscriberSetup +where + SubscriberObjBuilder: + 'static + Copy + Fn() -> farm_boosted_rewards_subscriber::ContractObj, +{ + pub b_mock: Rc>, + pub owner_addr: Address, + pub sub_wrapper: ContractObjWrapper< + farm_boosted_rewards_subscriber::ContractObj, + SubscriberObjBuilder, + >, +} + +impl SubscriberSetup +where + SubscriberObjBuilder: + 'static + Copy + Fn() -> farm_boosted_rewards_subscriber::ContractObj, +{ + pub fn new( + b_mock: Rc>, + builder: SubscriberObjBuilder, + fee_contract_address: &Address, + mex_pair_address: &Address, + energy_factory_address: &Address, + owner_addr: &Address, + reward_token_id: &[u8], + wegld_token_id: &[u8], + ) -> Self { + let rust_zero = rust_biguint!(0); + let sub_wrapper = b_mock.borrow_mut().create_sc_account( + &rust_zero, + Some(owner_addr), + builder, + "some other wasm path", + ); + + b_mock + .borrow_mut() + .execute_tx(owner_addr, &sub_wrapper, &rust_zero, |sc| { + let standard_mex_actions_percentages = MexActionsPercentages { + lock: 9_000, + fees: 800, + burn: 200, + }; + let premium_mex_actions_percentages = MexActionsPercentages { + lock: 9_500, + fees: 300, + burn: 200, + }; + + sc.init( + managed_address!(fee_contract_address), + managed_biguint!(ENERGT_THRESHOLD), + managed_token_id!(reward_token_id), + managed_token_id!(wegld_token_id), + standard_mex_actions_percentages, + premium_mex_actions_percentages, + managed_address!(energy_factory_address), + managed_address!(mex_pair_address), + LOCKING_PERIOD, + ); + + sc.set_energy_factory_address(managed_address!(energy_factory_address)); + }) + .assert_ok(); + + let mex_token_roles = [EsdtLocalRole::Burn]; + b_mock.borrow_mut().set_esdt_local_roles( + sub_wrapper.address_ref(), + reward_token_id, + &mex_token_roles[..], + ); + + Self { + b_mock, + owner_addr: owner_addr.clone(), + sub_wrapper, + } + } + + pub fn call_register_service(&mut self, args: Vec<(Option>, u64, u64)>) -> TxResult { + self.b_mock.borrow_mut().execute_tx( + &self.owner_addr, + &self.sub_wrapper, + &rust_biguint!(0), + |sc| { + let mut args_encoded = MultiValueEncoded::new(); + for arg in args { + let (opt_token_id, value, subscription_epochs) = arg; + args_encoded.push( + ( + opt_token_id.map(|token_id| managed_token_id!(token_id)), + managed_biguint!(value), + subscription_epochs, + ) + .into(), + ); + } + + sc.register_service(args_encoded); + }, + ) + } + + // pub fn call_unregister_service(&mut self) -> TxResult { + // self.b_mock.borrow_mut().execute_tx( + // &self.owner_addr, + // &self.sub_wrapper, + // &rust_biguint!(0), + // |sc| { + // sc.unregister_service(); + // }, + // ) + // } + + pub fn call_add_farm(&mut self, farm_address: &Address) -> u64 { + let mut farm_id = 0u64; + let _ = self.b_mock.borrow_mut().execute_tx( + &self.owner_addr, + &self.sub_wrapper, + &rust_biguint!(0), + |sc| { + farm_id = sc.add_farm(managed_address!(farm_address)); + }, + ); + + farm_id + } + + pub fn call_subtract_payment( + &mut self, + service_index: usize, + user_ids_vec: Vec, + ) -> TxResult { + self.b_mock.borrow_mut().execute_tx( + &self.owner_addr, + &self.sub_wrapper, + &rust_biguint!(0), + |sc| { + let mut user_ids = MultiValueEncoded::new(); + for user_id in user_ids_vec { + user_ids.push(user_id); + } + sc.subtract_payment_endpoint(service_index, user_ids); + }, + ) + } + + pub fn call_perform_claim_boosted( + &mut self, + service_index: usize, + user_id: AddressId, + farms_list: Vec, + ) -> TxResult { + self.b_mock.borrow_mut().execute_tx( + &self.owner_addr, + &self.sub_wrapper, + &rust_biguint!(0), + |sc| { + let mut user_farms_pairs_to_claim = MultiValueEncoded::new(); + let user_farms = ManagedVec::from(farms_list); + user_farms_pairs_to_claim.push(MultiValue2::from((user_id, user_farms))); + + sc.perform_claim_rewards_operations_endpoint( + service_index, + user_farms_pairs_to_claim, + ); + }, + ) + } + + pub fn call_perform_mex_operation( + &mut self, + service_index: usize, + users_list: Vec, + ) -> TxResult { + self.b_mock.borrow_mut().execute_tx( + &self.owner_addr, + &self.sub_wrapper, + &rust_biguint!(0), + |sc| { + let mut user_ids = MultiValueEncoded::new(); + for user_id in users_list { + user_ids.push(user_id); + } + + sc.perform_mex_operations_endpoint(service_index, managed_biguint!(1u64), user_ids); + }, + ) + } + + pub fn call_claim_fees(&mut self, expected_output_payments_no: usize) -> TxResult { + self.b_mock.borrow_mut().execute_tx( + &self.owner_addr, + &self.sub_wrapper, + &rust_biguint!(0), + |sc| { + let result = sc.claim_fees(); + assert_eq!(result.len(), expected_output_payments_no); + }, + ) + } +} diff --git a/farm-boosted-rewards-subscriber/tests/subscriber_test.rs b/farm-boosted-rewards-subscriber/tests/subscriber_test.rs new file mode 100644 index 0000000..8c4bb09 --- /dev/null +++ b/farm-boosted-rewards-subscriber/tests/subscriber_test.rs @@ -0,0 +1,752 @@ +#![allow(deprecated)] + +use std::{cell::RefCell, rc::Rc}; + +use farm_setup::FarmSetup; +use multiversx_sc_scenario::{ + managed_address, managed_token_id, rust_biguint, testing_framework::BlockchainStateWrapper, + DebugApi, +}; +use pair_setup::PairSetup; +use simple_lock::locked_token::LockedTokenAttributes; +use subscriber_setup::SubscriberSetup; +use subscription_fee::pair_actions::PairActionsModule; +use subscription_setup::SubscriptionSetup; + +mod farm_setup; +mod pair_setup; +mod subscriber_setup; +mod subscription_setup; + +static USDC_TOKEN_ID: &[u8] = b"USDC-123456"; +static WEGLD_TOKEN_ID: &[u8] = b"WEGLD-123456"; +static LP_TOKEN_ID: &[u8] = b"LPTOK-123456"; +static STABLE_LP_TOKEN_ID: &[u8] = b"SLPTOK-123456"; +static REWARD_TOKEN_ID: &[u8] = b"MEX-123456"; +static LOCKED_TOKEN_ID: &[u8] = b"XMEX-123456"; +const DEFAULT_BOOSTED_YIELDS_PERCENTAGE: u64 = 2_500; // 25% +pub const WEEKLY_SUBSCRIPTION_EPOCHS: u64 = 7; + +#[allow(clippy::type_complexity)] +fn init_all< + PairBuilder: 'static + Copy + Fn() -> pair::ContractObj, + FarmBuilder: 'static + Copy + Fn() -> farm_with_locked_rewards::ContractObj, + EnergyFactoryBuilder: 'static + Copy + Fn() -> energy_factory::ContractObj, + SubscriptionObjBuilder: 'static + Copy + Fn() -> subscription_fee::ContractObj, + SubscriberBuilder: 'static + Copy + Fn() -> farm_boosted_rewards_subscriber::ContractObj, +>( + pair_builder: PairBuilder, + farm_builder: FarmBuilder, + energy_factory_builder: EnergyFactoryBuilder, + sub_builder: SubscriptionObjBuilder, + subscriber_builder: SubscriberBuilder, +) -> ( + Rc>, + PairSetup, + PairSetup, + FarmSetup, + SubscriptionSetup, + SubscriberSetup, +) { + let mut b_mock = BlockchainStateWrapper::new(); + let owner = b_mock.create_user_account(&rust_biguint!(0)); + + let b_mock_ref = RefCell::new(b_mock); + let b_mock_rc = Rc::new(b_mock_ref); + let mex_pair_setup = PairSetup::new( + b_mock_rc.clone(), + pair_builder, + &owner, + WEGLD_TOKEN_ID, + REWARD_TOKEN_ID, + LP_TOKEN_ID, + 1_000_000_000, + 2_000_000_000, + ); + let stable_pair_setup = PairSetup::new( + b_mock_rc.clone(), + pair_builder, + &owner, + WEGLD_TOKEN_ID, + USDC_TOKEN_ID, + STABLE_LP_TOKEN_ID, + 1_000_000_000, + 2_000_000_000, + ); + + let farm_setup = FarmSetup::new( + b_mock_rc.clone(), + &owner, + REWARD_TOKEN_ID, + LOCKED_TOKEN_ID, + LP_TOKEN_ID, + DEFAULT_BOOSTED_YIELDS_PERCENTAGE, + mex_pair_setup.pair_wrapper.address_ref(), + farm_builder, + energy_factory_builder, + ); + + let sub_sc = SubscriptionSetup::new( + b_mock_rc.clone(), + sub_builder, + &owner, + stable_pair_setup.pair_wrapper.address_ref(), + vec![WEGLD_TOKEN_ID.to_vec()], + ); + + b_mock_rc + .borrow_mut() + .execute_tx(&owner, &sub_sc.s_wrapper, &rust_biguint!(0), |sc| { + sc.add_pair_address( + managed_token_id!(WEGLD_TOKEN_ID), + managed_address!(stable_pair_setup.pair_wrapper.address_ref()), + ); + }) + .assert_ok(); + + let subscriber = SubscriberSetup::new( + b_mock_rc.clone(), + subscriber_builder, + sub_sc.s_wrapper.address_ref(), + mex_pair_setup.pair_wrapper.address_ref(), + farm_setup.energy_factory_wrapper.address_ref(), + &owner, + REWARD_TOKEN_ID, + WEGLD_TOKEN_ID, + ); + + ( + b_mock_rc, + mex_pair_setup, + stable_pair_setup, + farm_setup, + sub_sc, + subscriber, + ) +} + +#[test] +fn init_test() { + let _ = init_all( + pair::contract_obj, + farm_with_locked_rewards::contract_obj, + energy_factory::contract_obj, + subscription_fee::contract_obj, + farm_boosted_rewards_subscriber::contract_obj, + ); +} + +#[test] +fn claim_boosted_rewards_for_user_test() { + let ( + b_mock_rc, + _mex_pair_setup, + _stable_pair_setup, + mut farm_setup, + mut subscription_setup, + mut subscriber_setup, + ) = init_all( + pair::contract_obj, + farm_with_locked_rewards::contract_obj, + energy_factory::contract_obj, + subscription_fee::contract_obj, + farm_boosted_rewards_subscriber::contract_obj, + ); + + let farm_id = subscriber_setup.call_add_farm(farm_setup.farm_wrapper.address_ref()); + let farm_list = vec![farm_id]; + + let user = b_mock_rc + .borrow_mut() + .create_user_account(&rust_biguint!(0)); + let user_id = 1; + b_mock_rc.borrow_mut().set_block_epoch(2); + + subscriber_setup + .call_register_service(vec![ + ( + Some(WEGLD_TOKEN_ID.to_vec()), + 1_000, + WEEKLY_SUBSCRIPTION_EPOCHS, + ), + ( + Some(WEGLD_TOKEN_ID.to_vec()), + 500, + WEEKLY_SUBSCRIPTION_EPOCHS, + ), + ]) + .assert_ok(); + + subscription_setup + .call_approve_service(subscriber_setup.sub_wrapper.address_ref()) + .assert_ok(); + + b_mock_rc + .borrow_mut() + .set_esdt_balance(&user, WEGLD_TOKEN_ID, &rust_biguint!(1_000_000)); + + subscription_setup + .call_deposit(&user, WEGLD_TOKEN_ID, 1_000_000) + .assert_ok(); + + let normal_service = 0; + subscription_setup + .call_subscribe(&user, vec![(1, normal_service)]) + .assert_ok(); + + // Generate farm rewards + let user_token_amount = 100_000_000; + b_mock_rc + .borrow_mut() + .set_esdt_balance(&user, LP_TOKEN_ID, &rust_biguint!(user_token_amount)); + farm_setup.set_user_energy(&user, 1_000, 2, 1); + farm_setup.enter_farm(&user, LP_TOKEN_ID, user_token_amount); + let _ = farm_setup.claim_rewards(&user, 1, user_token_amount); + b_mock_rc.borrow_mut().set_block_nonce(10); + b_mock_rc.borrow_mut().set_block_epoch(6); + farm_setup.set_user_energy(&user, 1_000, 6, 1); + farm_setup.claim_rewards(&user, 2, user_token_amount); + + let base_rewards = 7_500; + b_mock_rc + .borrow() + .check_nft_balance::>( + &user, + LOCKED_TOKEN_ID, + 1, + &rust_biguint!(base_rewards), + None, + ); + + b_mock_rc.borrow_mut().set_block_epoch(10); + farm_setup.set_user_energy(&user, 1_000, 10, 1); + + farm_setup + .call_allow_external_claim_boosted_rewards(&user, true) + .assert_ok(); + + subscriber_setup + .call_subtract_payment(0, vec![user_id]) + .assert_ok(); + subscriber_setup + .call_perform_claim_boosted(0, user_id, farm_list.clone()) + .assert_ok(); + + // Check that the subscriber claimed the boosted amount for the user + let boosted_rewards = 2_500; + b_mock_rc + .borrow() + .check_nft_balance::>( + &user, + LOCKED_TOKEN_ID, + 1, + &rust_biguint!(base_rewards + boosted_rewards), // base rewards are minted with the same nonce + None, + ); + + b_mock_rc.borrow().check_esdt_balance( + subscriber_setup.sub_wrapper.address_ref(), + WEGLD_TOKEN_ID, + &rust_biguint!(1_000), + ); + + // try perform operation again, same epoch + subscriber_setup + .call_perform_claim_boosted(0, user_id, farm_list.clone()) + .assert_ok(); + + // user has the same balance + b_mock_rc + .borrow() + .check_nft_balance::>( + &user, + LOCKED_TOKEN_ID, + 1, + &rust_biguint!(base_rewards + boosted_rewards), // base rewards are minted with the same nonce + None, + ); + + // still same subscriber balance, no funds subtracted + b_mock_rc.borrow().check_esdt_balance( + subscriber_setup.sub_wrapper.address_ref(), + WEGLD_TOKEN_ID, + &rust_biguint!(1_000), + ); + + b_mock_rc.borrow_mut().set_block_epoch(11); + + subscriber_setup + .call_perform_claim_boosted(0, user_id, farm_list) + .assert_ok(); + + // still same balance, subtraction is done manually once per month + b_mock_rc.borrow().check_esdt_balance( + subscriber_setup.sub_wrapper.address_ref(), + WEGLD_TOKEN_ID, + &rust_biguint!(1_000), + ); +} + +#[test] +fn claim_boosted_rewards_for_user_multiple_farms_test() { + let ( + b_mock_rc, + mex_pair_setup, + _stable_pair_setup, + mut farm_setup, + mut subscription_setup, + mut subscriber_setup, + ) = init_all( + pair::contract_obj, + farm_with_locked_rewards::contract_obj, + energy_factory::contract_obj, + subscription_fee::contract_obj, + farm_boosted_rewards_subscriber::contract_obj, + ); + + let mut farm_setup2 = FarmSetup::new( + b_mock_rc.clone(), + &subscriber_setup.owner_addr, + REWARD_TOKEN_ID, + LOCKED_TOKEN_ID, + LP_TOKEN_ID, + 7_500u64, + mex_pair_setup.pair_wrapper.address_ref(), + farm_with_locked_rewards::contract_obj, + energy_factory::contract_obj, + ); + let farm_id1 = subscriber_setup.call_add_farm(farm_setup.farm_wrapper.address_ref()); + let farm_id2 = subscriber_setup.call_add_farm(farm_setup2.farm_wrapper.address_ref()); + let farm_list = vec![farm_id1, farm_id2]; + + let user = b_mock_rc + .borrow_mut() + .create_user_account(&rust_biguint!(0)); + let user_id = 1; + b_mock_rc.borrow_mut().set_block_epoch(2); + + subscriber_setup + .call_register_service(vec![ + ( + Some(WEGLD_TOKEN_ID.to_vec()), + 1_000, + WEEKLY_SUBSCRIPTION_EPOCHS, + ), + ( + Some(WEGLD_TOKEN_ID.to_vec()), + 500, + WEEKLY_SUBSCRIPTION_EPOCHS, + ), + ]) + .assert_ok(); + + subscription_setup + .call_approve_service(subscriber_setup.sub_wrapper.address_ref()) + .assert_ok(); + + b_mock_rc + .borrow_mut() + .set_esdt_balance(&user, WEGLD_TOKEN_ID, &rust_biguint!(1_000_000)); + + subscription_setup + .call_deposit(&user, WEGLD_TOKEN_ID, 1_000_000) + .assert_ok(); + + let normal_service = 0; + subscription_setup + .call_subscribe(&user, vec![(1, normal_service)]) + .assert_ok(); + + // Generate farm rewards + let user_token_amount = 100_000_000; + b_mock_rc.borrow_mut().set_esdt_balance( + &user, + LP_TOKEN_ID, + &rust_biguint!(user_token_amount * 2), + ); + + farm_setup.set_user_energy(&user, 1_000, 2, 1); + farm_setup.enter_farm(&user, LP_TOKEN_ID, user_token_amount); + let _ = farm_setup.claim_rewards(&user, 1, user_token_amount); + + farm_setup2.set_user_energy(&user, 1_000, 2, 1); + farm_setup2.enter_farm(&user, LP_TOKEN_ID, user_token_amount); + let _ = farm_setup2.claim_rewards(&user, 1, user_token_amount); + + b_mock_rc.borrow_mut().set_block_nonce(10); + b_mock_rc.borrow_mut().set_block_epoch(6); + + farm_setup.set_user_energy(&user, 1_000, 6, 1); + farm_setup.claim_rewards(&user, 2, user_token_amount); + farm_setup2.set_user_energy(&user, 1_000, 6, 1); + farm_setup2.claim_rewards(&user, 2, user_token_amount); + + let farm1_base_rewards = 7_500; + let farm2_base_rewards = 2_500; + b_mock_rc + .borrow() + .check_nft_balance::>( + &user, + LOCKED_TOKEN_ID, + 1, + &rust_biguint!(farm1_base_rewards + farm2_base_rewards), + None, + ); + + b_mock_rc.borrow_mut().set_block_epoch(10); + farm_setup.set_user_energy(&user, 1_000, 10, 1); + farm_setup2.set_user_energy(&user, 1_000, 10, 1); + + farm_setup + .call_allow_external_claim_boosted_rewards(&user, true) + .assert_ok(); + farm_setup2 + .call_allow_external_claim_boosted_rewards(&user, true) + .assert_ok(); + + // Call subscriber action + subscriber_setup + .call_subtract_payment(0, vec![user_id]) + .assert_ok(); + subscriber_setup + .call_perform_claim_boosted(0, user_id, farm_list.clone()) + .assert_ok(); + + // Check that the subscriber claimed the boosted amount for the user, for both farms + let farm1_boosted_rewards = 2_500; + let farm2_boosted_rewards = 7_500; + b_mock_rc + .borrow() + .check_nft_balance::>( + &user, + LOCKED_TOKEN_ID, + 1, + &rust_biguint!( + farm1_base_rewards + + farm2_base_rewards + + farm1_boosted_rewards + + farm2_boosted_rewards + ), // base rewards are minted with the same nonce + None, + ); + + b_mock_rc.borrow().check_esdt_balance( + subscriber_setup.sub_wrapper.address_ref(), + WEGLD_TOKEN_ID, + &rust_biguint!(1_000), + ); + + // try perform operation again, same epoch + subscriber_setup + .call_perform_claim_boosted(0, user_id, farm_list.clone()) + .assert_ok(); + + // user has the same balance + b_mock_rc + .borrow() + .check_nft_balance::>( + &user, + LOCKED_TOKEN_ID, + 1, + &rust_biguint!( + farm1_base_rewards + + farm2_base_rewards + + farm1_boosted_rewards + + farm2_boosted_rewards + ), + None, + ); + + // still same subscriber balance, no funds subtracted + b_mock_rc.borrow().check_esdt_balance( + subscriber_setup.sub_wrapper.address_ref(), + WEGLD_TOKEN_ID, + &rust_biguint!(1_000), + ); + + b_mock_rc.borrow_mut().set_block_epoch(11); + + subscriber_setup + .call_perform_claim_boosted(0, user_id, farm_list) + .assert_ok(); + + // still same balance, subtraction is done manually once per month + b_mock_rc.borrow().check_esdt_balance( + subscriber_setup.sub_wrapper.address_ref(), + WEGLD_TOKEN_ID, + &rust_biguint!(1_000), + ); +} + +#[test] +fn claim_boosted_rewards_for_premium_user_test() { + let ( + b_mock_rc, + _mex_pair_setup, + _stable_pair_setup, + mut farm_setup, + mut subscription_setup, + mut subscriber_setup, + ) = init_all( + pair::contract_obj, + farm_with_locked_rewards::contract_obj, + energy_factory::contract_obj, + subscription_fee::contract_obj, + farm_boosted_rewards_subscriber::contract_obj, + ); + + let farm_id = subscriber_setup.call_add_farm(farm_setup.farm_wrapper.address_ref()); + let farm_list = vec![farm_id]; + + let user = b_mock_rc + .borrow_mut() + .create_user_account(&rust_biguint!(0)); + let user_id = 1; + b_mock_rc.borrow_mut().set_block_epoch(2); + + subscriber_setup + .call_register_service(vec![ + ( + Some(WEGLD_TOKEN_ID.to_vec()), + 1_000, + WEEKLY_SUBSCRIPTION_EPOCHS, + ), + ( + Some(WEGLD_TOKEN_ID.to_vec()), + 500, + WEEKLY_SUBSCRIPTION_EPOCHS, + ), + ]) + .assert_ok(); + + subscription_setup + .call_approve_service(subscriber_setup.sub_wrapper.address_ref()) + .assert_ok(); + + b_mock_rc + .borrow_mut() + .set_esdt_balance(&user, WEGLD_TOKEN_ID, &rust_biguint!(1_000_000)); + + subscription_setup + .call_deposit(&user, WEGLD_TOKEN_ID, 1_000_000) + .assert_ok(); + + // Subscribe to premium service + let premium_service = 1; + subscription_setup + .call_subscribe(&user, vec![(1, premium_service)]) + .assert_ok(); + + // Generate farm rewards + let user_token_amount = 100_000_000; + b_mock_rc + .borrow_mut() + .set_esdt_balance(&user, LP_TOKEN_ID, &rust_biguint!(user_token_amount)); + farm_setup.set_user_energy(&user, 1_000, 2, 1); + farm_setup.enter_farm(&user, LP_TOKEN_ID, user_token_amount); + let _ = farm_setup.claim_rewards(&user, 1, user_token_amount); + b_mock_rc.borrow_mut().set_block_nonce(10); + b_mock_rc.borrow_mut().set_block_epoch(6); + farm_setup.set_user_energy(&user, 1_000, 6, 1); + farm_setup.claim_rewards(&user, 2, user_token_amount); + + let base_rewards = 7_500; + b_mock_rc + .borrow() + .check_nft_balance::>( + &user, + LOCKED_TOKEN_ID, + 1, + &rust_biguint!(base_rewards), + None, + ); + + b_mock_rc.borrow_mut().set_block_epoch(10); + farm_setup.set_user_energy(&user, 1_000, 10, 1); + + farm_setup + .call_allow_external_claim_boosted_rewards(&user, true) + .assert_ok(); + + subscriber_setup + .call_subtract_payment(premium_service, vec![user_id]) + .assert_ok(); + subscriber_setup + .call_perform_claim_boosted(premium_service, user_id, farm_list.clone()) + .assert_ok(); + + // Check that the subscriber claimed the boosted amount for the user + let boosted_rewards = 2_500; + b_mock_rc + .borrow() + .check_nft_balance::>( + &user, + LOCKED_TOKEN_ID, + 1, + &rust_biguint!(base_rewards + boosted_rewards), // base rewards are minted with the same nonce + None, + ); + + // Different price for premium users + b_mock_rc.borrow().check_esdt_balance( + subscriber_setup.sub_wrapper.address_ref(), + WEGLD_TOKEN_ID, + &rust_biguint!(500), + ); + + // try perform operation again, same epoch + subscriber_setup + .call_perform_claim_boosted(premium_service, user_id, farm_list.clone()) + .assert_ok(); + + // user has the same balance + b_mock_rc + .borrow() + .check_nft_balance::>( + &user, + LOCKED_TOKEN_ID, + 1, + &rust_biguint!(base_rewards + boosted_rewards), // base rewards are minted with the same nonce + None, + ); + + // still same subscriber balance, no funds subtracted + b_mock_rc.borrow().check_esdt_balance( + subscriber_setup.sub_wrapper.address_ref(), + WEGLD_TOKEN_ID, + &rust_biguint!(500), + ); + + b_mock_rc.borrow_mut().set_block_epoch(11); + + subscriber_setup + .call_perform_claim_boosted(premium_service, user_id, farm_list) + .assert_ok(); + + // still same balance, subtraction is done manually once per month + b_mock_rc.borrow().check_esdt_balance( + subscriber_setup.sub_wrapper.address_ref(), + WEGLD_TOKEN_ID, + &rust_biguint!(500), + ); +} + +#[test] +fn mex_operation_with_claim_fees_test() { + let ( + b_mock_rc, + _mex_pair_setup, + _stable_pair_setup, + _farm_setup, + mut subscription_setup, + mut subscriber_setup, + ) = init_all( + pair::contract_obj, + farm_with_locked_rewards::contract_obj, + energy_factory::contract_obj, + subscription_fee::contract_obj, + farm_boosted_rewards_subscriber::contract_obj, + ); + + let first_user = b_mock_rc + .borrow_mut() + .create_user_account(&rust_biguint!(0)); + let second_user = b_mock_rc + .borrow_mut() + .create_user_account(&rust_biguint!(0)); + let first_user_id = 1; + let second_user_id = 2; + + b_mock_rc.borrow_mut().set_block_epoch(2); + + subscriber_setup + .call_register_service(vec![ + ( + Some(WEGLD_TOKEN_ID.to_vec()), + 1_000, + WEEKLY_SUBSCRIPTION_EPOCHS, + ), + ( + Some(WEGLD_TOKEN_ID.to_vec()), + 500, + WEEKLY_SUBSCRIPTION_EPOCHS, + ), + ]) + .assert_ok(); + + subscription_setup + .call_approve_service(subscriber_setup.sub_wrapper.address_ref()) + .assert_ok(); + + b_mock_rc + .borrow_mut() + .set_esdt_balance(&first_user, WEGLD_TOKEN_ID, &rust_biguint!(1_000_000)); + + subscription_setup + .call_deposit(&first_user, WEGLD_TOKEN_ID, 1_000_000) + .assert_ok(); + + b_mock_rc.borrow_mut().set_esdt_balance( + &second_user, + WEGLD_TOKEN_ID, + &rust_biguint!(1_000_000), + ); + + subscription_setup + .call_deposit(&second_user, WEGLD_TOKEN_ID, 1_000_000) + .assert_ok(); + + // Subscribe to standard service + let standard_service = 0; + subscription_setup + .call_subscribe(&first_user, vec![(1, standard_service)]) + .assert_ok(); + subscription_setup + .call_subscribe(&second_user, vec![(1, standard_service)]) + .assert_ok(); + + subscriber_setup + .call_subtract_payment(standard_service, vec![first_user_id, second_user_id]) + .assert_ok(); + + subscriber_setup + .call_perform_mex_operation(standard_service, vec![first_user_id, second_user_id]) + .assert_ok(); + + // Expected locked tokens balance: 1799 + b_mock_rc + .borrow() + .check_nft_balance::>( + &first_user, + LOCKED_TOKEN_ID, + 1, + &rust_biguint!(1799), + None, + ); + + // Expected locked tokens balance: 1800 - the last user is computed by difference + b_mock_rc + .borrow() + .check_nft_balance::>( + &second_user, + LOCKED_TOKEN_ID, + 1, + &rust_biguint!(1800), + None, + ); + + b_mock_rc.borrow().check_esdt_balance( + &subscriber_setup.owner_addr, + WEGLD_TOKEN_ID, + &rust_biguint!(0), + ); + + let expected_fee_amount = 160; + subscriber_setup.call_claim_fees(1).assert_ok(); + + b_mock_rc.borrow().check_esdt_balance( + &subscriber_setup.owner_addr, + WEGLD_TOKEN_ID, + &rust_biguint!(expected_fee_amount), + ); +} diff --git a/subscriber/tests/subscription_setup/mod.rs b/farm-boosted-rewards-subscriber/tests/subscription_setup/mod.rs similarity index 72% rename from subscriber/tests/subscription_setup/mod.rs rename to farm-boosted-rewards-subscriber/tests/subscription_setup/mod.rs index a8466c1..91816e9 100644 --- a/subscriber/tests/subscription_setup/mod.rs +++ b/farm-boosted-rewards-subscriber/tests/subscription_setup/mod.rs @@ -2,20 +2,18 @@ use std::{cell::RefCell, rc::Rc}; -use auto_farm::common::address_to_id_mapper::AddressId; -use multiversx_sc::types::{ - Address, EgldOrEsdtTokenIdentifier, MultiValueEncoded, TokenIdentifier, +use multiversx_sc::{ + storage::mappers::AddressId, + types::{Address, MultiValueEncoded}, }; use multiversx_sc_scenario::{ - managed_address, rust_biguint, + managed_address, managed_token_id, rust_biguint, testing_framework::{BlockchainStateWrapper, ContractObjWrapper, TxResult}, DebugApi, }; -use subscription_fee::{ - fees::FeesModule, - service::{ServiceModule, SubscriptionType}, - SubscriptionFee, -}; +use subscription_fee::{fees::FeesModule, service::ServiceModule, SubscriptionFee}; + +use crate::{USDC_TOKEN_ID, WEGLD_TOKEN_ID}; pub struct SubscriptionSetup where @@ -51,16 +49,15 @@ where .execute_tx(owner_addr, &s_wrapper, &rust_zero, |sc| { let mut args = MultiValueEncoded::new(); for arg in accepted_tokens { - if &arg == b"EGLD" { - let token_id = EgldOrEsdtTokenIdentifier::egld(); - args.push(token_id); - } else { - let token_id = TokenIdentifier::from_esdt_bytes(arg); - args.push(EgldOrEsdtTokenIdentifier::esdt(token_id)); - } + args.push(managed_token_id!(arg)); } - sc.init(managed_address!(pair_address), args); + sc.init( + managed_token_id!(USDC_TOKEN_ID), + managed_token_id!(WEGLD_TOKEN_ID), + managed_address!(pair_address), + args, + ); }) .assert_ok(); @@ -95,17 +92,13 @@ where ) } - pub fn call_subscribe( - &mut self, - caller: &Address, - args: Vec<(AddressId, usize, SubscriptionType)>, - ) -> TxResult { + pub fn call_subscribe(&mut self, caller: &Address, args: Vec<(AddressId, usize)>) -> TxResult { self.b_mock .borrow_mut() .execute_tx(caller, &self.s_wrapper, &rust_biguint!(0), |sc| { let mut managed_args = MultiValueEncoded::new(); for arg in args { - managed_args.push((arg.0, arg.1, arg.2).into()); + managed_args.push((arg.0, arg.1).into()); } sc.subscribe(managed_args); diff --git a/farm-boosted-rewards-subscriber/wasm/Cargo.lock b/farm-boosted-rewards-subscriber/wasm/Cargo.lock index f101bfe..2577620 100644 --- a/farm-boosted-rewards-subscriber/wasm/Cargo.lock +++ b/farm-boosted-rewards-subscriber/wasm/Cargo.lock @@ -4,15 +4,22 @@ version = 3 [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", "once_cell", "version_check", + "zerocopy", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "arrayvec" version = "0.7.4" @@ -27,9 +34,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" -version = "1.3.2" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "cfg-if" @@ -38,33 +45,300 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "empty" +name = "common-types" version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ "multiversx-sc", ] [[package]] -name = "empty-wasm" +name = "common_errors" version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" dependencies = [ - "empty", - "multiversx-sc-wasm-adapter", + "multiversx-sc", +] + +[[package]] +name = "common_structs" +version = "0.0.0" +dependencies = [ + "mergeable", + "multiversx-sc", ] +[[package]] +name = "common_structs" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "fixed-supply-token", + "math", + "mergeable", + "multiversx-sc", + "unwrappable", +] + +[[package]] +name = "common_subscriber" +version = "0.0.0" +dependencies = [ + "multiversx-sc", + "subscription-fee", +] + +[[package]] +name = "config" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_errors", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", + "multiversx-sc", + "pausable", + "permissions_module", + "token_send", +] + +[[package]] +name = "contexts" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_errors", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", + "config", + "farm_token", + "multiversx-sc", + "multiversx-sc-modules", + "pausable", + "permissions_module", + "rewards", + "token_merge_helper", + "token_send", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + [[package]] name = "endian-type" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" +[[package]] +name = "energy-factory" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", + "legacy_token_decode_module", + "math", + "mergeable", + "multiversx-sc", + "multiversx-sc-modules", + "sc_whitelist_module", + "simple-lock", + "unwrappable", + "utils", +] + +[[package]] +name = "energy-query" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "energy-factory", + "multiversx-sc", +] + +[[package]] +name = "events" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", + "contexts", + "multiversx-sc", +] + +[[package]] +name = "farm" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_errors", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", + "config", + "contexts", + "energy-query", + "events", + "farm-boosted-yields", + "farm_base_impl", + "farm_token", + "fixed-supply-token", + "mergeable", + "multiversx-sc", + "multiversx-sc-modules", + "pair", + "pausable", + "permissions_module", + "rewards", + "sc_whitelist_module", + "token_send", + "utils", + "week-timekeeping", + "weekly-rewards-splitting", +] + +[[package]] +name = "farm-boosted-rewards-subscriber" +version = "0.0.0" +dependencies = [ + "common_structs 0.0.0", + "common_subscriber", + "config", + "energy-factory", + "energy-query", + "farm-with-locked-rewards", + "multiversx-sc", + "multiversx-sc-modules", + "pair", + "subscription-fee", +] + +[[package]] +name = "farm-boosted-rewards-subscriber-wasm" +version = "0.0.0" +dependencies = [ + "farm-boosted-rewards-subscriber", + "multiversx-sc-wasm-adapter", +] + +[[package]] +name = "farm-boosted-yields" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common-types", + "config", + "energy-query", + "multiversx-sc", + "pausable", + "permissions_module", + "week-timekeeping", + "weekly-rewards-splitting", +] + +[[package]] +name = "farm-with-locked-rewards" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_errors", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", + "config", + "contexts", + "energy-factory", + "energy-query", + "events", + "farm", + "farm-boosted-yields", + "farm_base_impl", + "farm_token", + "fixed-supply-token", + "locking_module", + "mergeable", + "multiversx-sc", + "multiversx-sc-modules", + "pausable", + "permissions_module", + "rewards", + "sc_whitelist_module", + "token_send", + "utils", + "week-timekeeping", + "weekly-rewards-splitting", +] + +[[package]] +name = "farm_base_impl" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_errors", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", + "config", + "contexts", + "events", + "farm_token", + "fixed-supply-token", + "mergeable", + "multiversx-sc", + "multiversx-sc-modules", + "pausable", + "permissions_module", + "rewards", + "token_merge_helper", + "token_send", + "utils", +] + +[[package]] +name = "farm_token" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_errors", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", + "config", + "multiversx-sc", + "multiversx-sc-modules", + "pausable", + "permissions_module", + "token_send", +] + +[[package]] +name = "fees-collector" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common-types", + "common_errors", + "energy-factory", + "energy-query", + "locking_module", + "multiversx-sc", + "multiversx-sc-modules", + "sc_whitelist_module", + "simple-lock", + "utils", + "week-timekeeping", + "weekly-rewards-splitting", +] + +[[package]] +name = "fixed-supply-token" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "multiversx-sc", +] + [[package]] name = "hashbrown" -version = "0.13.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ "ahash", + "allocator-api2", ] [[package]] @@ -75,13 +349,60 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hex-literal" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" +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" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", + "multiversx-sc", + "utils", +] + +[[package]] +name = "locking_module" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "energy-factory", + "multiversx-sc", + "simple-lock", +] + +[[package]] +name = "math" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "mergeable" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "multiversx-sc", +] [[package]] name = "multiversx-sc" -version = "0.43.2" +version = "0.45.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2bdb196b3ff2b9f8c744ec2e026c22c8e02bc91e5c6ed09951415c47fef6b8" dependencies = [ "bitflags", "hashbrown", @@ -93,7 +414,9 @@ dependencies = [ [[package]] name = "multiversx-sc-codec" -version = "0.18.1" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19908153158c03df4582af08f47c0eb39fb52a7dff4736b301a66acbbb9955d3" dependencies = [ "arrayvec", "multiversx-sc-codec-derive", @@ -101,7 +424,9 @@ dependencies = [ [[package]] name = "multiversx-sc-codec-derive" -version = "0.18.1" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b03b43f9cad320992f54ed162de2ed63e3ec83ed01361e57ee9c1865fba5a2" dependencies = [ "hex", "proc-macro2", @@ -111,7 +436,9 @@ dependencies = [ [[package]] name = "multiversx-sc-derive" -version = "0.43.2" +version = "0.45.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e60b5dce707f61376f74d713218f75326121d9f6a5f09a3a63de7aea2a92be9" dependencies = [ "hex", "proc-macro2", @@ -120,9 +447,20 @@ dependencies = [ "syn", ] +[[package]] +name = "multiversx-sc-modules" +version = "0.45.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5833f8bc88104357d38a8952d2a16c3e66080e2e512c0e7001c0c003006c475" +dependencies = [ + "multiversx-sc", +] + [[package]] name = "multiversx-sc-wasm-adapter" -version = "0.43.2" +version = "0.45.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4299660d5413d9f120bfddda8105b1f9d28f0345a72f53e5dc90732c4983e45" dependencies = [ "multiversx-sc", ] @@ -151,11 +489,46 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "pair" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_errors", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", + "fees-collector", + "itertools", + "multiversx-sc", + "pausable", + "permissions_module", + "simple-lock", + "token_send", +] + +[[package]] +name = "pausable" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "multiversx-sc", + "permissions_module", +] + +[[package]] +name = "permissions_module" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "bitflags", + "common_errors", + "multiversx-sc", +] + [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] @@ -179,31 +552,155 @@ dependencies = [ "nibble_vec", ] +[[package]] +name = "rewards" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_errors", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", + "config", + "farm_token", + "multiversx-sc", + "multiversx-sc-modules", + "pausable", + "permissions_module", + "token_send", +] + +[[package]] +name = "sc_whitelist_module" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_errors", + "multiversx-sc", +] + +[[package]] +name = "simple-lock" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", + "multiversx-sc", + "multiversx-sc-modules", +] + [[package]] name = "smallvec" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +[[package]] +name = "subscription-fee" +version = "0.0.0" +dependencies = [ + "common_structs 0.0.0", + "multiversx-sc", + "multiversx-sc-modules", +] + [[package]] name = "syn" -version = "1.0.109" +version = "2.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "token_merge_helper" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_errors", + "multiversx-sc", +] + +[[package]] +name = "token_send" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_errors", + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", + "multiversx-sc", +] + [[package]] name = "unicode-ident" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +[[package]] +name = "unwrappable" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "utils" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common_structs 0.0.0 (git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d)", + "fixed-supply-token", + "mergeable", + "multiversx-sc", +] + [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "week-timekeeping" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common-types", + "multiversx-sc", +] + +[[package]] +name = "weekly-rewards-splitting" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "common-types", + "energy-query", + "math", + "multiversx-sc", + "unwrappable", + "week-timekeeping", +] + +[[package]] +name = "zerocopy" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/farm-boosted-rewards-subscriber/wasm/Cargo.toml b/farm-boosted-rewards-subscriber/wasm/Cargo.toml index 16f45f6..80ebcc4 100644 --- a/farm-boosted-rewards-subscriber/wasm/Cargo.toml +++ b/farm-boosted-rewards-subscriber/wasm/Cargo.toml @@ -1,17 +1,17 @@ +# Code generated by the multiversx-sc build system. DO NOT EDIT. + +# ########################################## +# ############## AUTO-GENERATED ############# +# ########################################## + [package] name = "farm-boosted-rewards-subscriber-wasm" version = "0.0.0" edition = "2018" publish = false -authors = [ "you",] [lib] -crate-type = [ "cdylib",] - -[workspace] -members = [ ".",] - -[dev-dependencies] +crate-type = ["cdylib"] [profile.release] codegen-units = 1 @@ -19,9 +19,13 @@ opt-level = "z" lto = true debug = false panic = "abort" +overflow-checks = false [dependencies.farm-boosted-rewards-subscriber] path = ".." [dependencies.multiversx-sc-wasm-adapter] -version = "=0.43.2" +version = "=0.45.2" + +[workspace] +members = ["."] diff --git a/farm-boosted-rewards-subscriber/wasm/src/lib.rs b/farm-boosted-rewards-subscriber/wasm/src/lib.rs index 8ea5e5e..2456234 100644 --- a/farm-boosted-rewards-subscriber/wasm/src/lib.rs +++ b/farm-boosted-rewards-subscriber/wasm/src/lib.rs @@ -1,25 +1,48 @@ -// Code generated by the multiversx-sc multi-contract system. DO NOT EDIT. +// Code generated by the multiversx-sc build system. DO NOT EDIT. //////////////////////////////////////////////////// ////////////////// AUTO-GENERATED ////////////////// //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 0 +// Endpoints: 21 // Async Callback (empty): 1 -// Total number of exported functions: 2 +// Total number of exported functions: 23 #![no_std] -#![allow(internal_features)] + +// Configuration that works with rustc < 1.73.0. +// TODO: Recommended rustc version: 1.73.0 or newer. #![feature(lang_items)] multiversx_sc_wasm_adapter::allocator!(); multiversx_sc_wasm_adapter::panic_handler!(); multiversx_sc_wasm_adapter::endpoints! { - empty + farm_boosted_rewards_subscriber ( init => init + upgrade => upgrade + setLockPeriod => set_lock_period + setEnergyThreshold => set_energy_threshold + getSimpleLockAddress => simple_lock_address + getLockPeriod => lock_period + getNormalUserPercentage => normal_user_percentage + getPremiumUserPercentage => premium_user_percentage + getTotalFees => total_fees + getEnergyThreshold => energy_threshold + addFarm => add_farm + removeFarm => remove_farm + performClaimRewardsOperations => perform_claim_rewards_operations_endpoint + subtractPayment => subtract_payment_endpoint + claimFees => claim_fees + performMexOperations => perform_mex_operations_endpoint + registerService => register_service + unregisterService => unregister_service + getFeesContractAddress => fees_contract_address + getUserFees => user_fees + setEnergyFactoryAddress => set_energy_factory_address + getEnergyFactoryAddress => energy_factory_address ) } diff --git a/subscriber/.gitignore b/subscriber/.gitignore deleted file mode 100644 index 2c76bc9..0000000 --- a/subscriber/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# Generated by Cargo -# will have compiled files and executables -/target/ -*/target/ - -# The mxpy output -/output*/ diff --git a/subscriber/Cargo.toml b/subscriber/Cargo.toml deleted file mode 100644 index 136ee10..0000000 --- a/subscriber/Cargo.toml +++ /dev/null @@ -1,39 +0,0 @@ -[package] -name = "subscriber" -version = "0.0.0" -authors = [ "you",] -edition = "2018" -publish = false - -[lib] -path = "src/lib.rs" - -[dependencies.multiversx-sc] -version = "=0.43.2" - -[dependencies.multiversx-sc-modules] -version = "=0.43.2" - -[dependencies.auto-farm] -git = "https://github.com/multiversx/mx-exchange-tools-sc" -rev = "39e355f" - -[dependencies.subscription-fee] -path = "../subscription-fee" - -[dev-dependencies.pair] -git = "https://github.com/multiversx/mx-exchange-sc" -rev = "7f25a72" - -[dev-dependencies.pausable] -git = "https://github.com/multiversx/mx-exchange-sc" -rev = "7f25a72" - -[dev-dependencies.multiversx-sc-scenario] -version = "=0.43.2" - -[dev-dependencies] -num-bigint = "0.4.2" -num-traits = "0.2" -hex = "0.4" -hex-literal = "0.3.4" diff --git a/subscriber/meta/Cargo.toml b/subscriber/meta/Cargo.toml deleted file mode 100644 index c3a358a..0000000 --- a/subscriber/meta/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "subscriber-meta" -version = "0.0.0" -edition = "2018" -publish = false -authors = [ "you",] - -[dev-dependencies] - -[dependencies.subscriber] -path = ".." - -[dependencies.multiversx-sc-meta] -version = "=0.43.2" diff --git a/subscriber/meta/src/main.rs b/subscriber/meta/src/main.rs deleted file mode 100644 index 44a5804..0000000 --- a/subscriber/meta/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - multiversx_sc_meta::cli_main::(); -} diff --git a/subscriber/multiversx.json b/subscriber/multiversx.json deleted file mode 100644 index 7365539..0000000 --- a/subscriber/multiversx.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "language": "rust" -} \ No newline at end of file diff --git a/subscriber/src/base_functions.rs b/subscriber/src/base_functions.rs deleted file mode 100644 index ac2026f..0000000 --- a/subscriber/src/base_functions.rs +++ /dev/null @@ -1,27 +0,0 @@ -use subscription_fee::service::ServiceInfo; - -multiversx_sc::imports!(); -multiversx_sc::derive_imports!(); - -pub trait AllBaseTraits = crate::service::ServiceModule - + crate::common_storage::CommonStorageModule - + multiversx_sc_modules::ongoing_operation::OngoingOperationModule; - -#[derive(TypeAbi, TopEncode, TopDecode)] -pub struct InterpretedResult { - pub user_rewards: ManagedVec>, -} - -pub trait SubscriberContract { - type SubSc: AllBaseTraits; - type AdditionalDataType: ManagedVecItem + Clone; - - #[allow(clippy::result_unit_err)] - fn perform_action( - sc: &Self::SubSc, - user_address: ManagedAddress<::Api>, - service_index: usize, - service_info: &ServiceInfo<::Api>, - additional_data: &::AdditionalDataType, - ) -> Result::Api>, ()>; -} diff --git a/subscriber/src/base_init.rs b/subscriber/src/base_init.rs deleted file mode 100644 index 52cd620..0000000 --- a/subscriber/src/base_init.rs +++ /dev/null @@ -1,13 +0,0 @@ -multiversx_sc::imports!(); - -#[multiversx_sc::module] -pub trait BaseInitModule: crate::common_storage::CommonStorageModule { - fn base_init(&self, fees_contract_address: ManagedAddress) { - require!( - self.blockchain().is_smart_contract(&fees_contract_address), - "Invalid address" - ); - - self.fees_contract_address().set(fees_contract_address); - } -} diff --git a/subscriber/src/common_storage.rs b/subscriber/src/common_storage.rs deleted file mode 100644 index 2e1ffc4..0000000 --- a/subscriber/src/common_storage.rs +++ /dev/null @@ -1,31 +0,0 @@ -use auto_farm::common::address_to_id_mapper::{AddressId, AddressToIdMapper}; -use subscription_fee::service::ServiceInfo; - -multiversx_sc::imports!(); - -#[multiversx_sc::module] -pub trait CommonStorageModule { - #[storage_mapper("feesContractAddress")] - fn fees_contract_address(&self) -> SingleValueMapper; - - // following storages are to be used as "get from address" from the fees_contract - - #[storage_mapper("serviceId")] - fn service_id(&self) -> AddressToIdMapper; - - #[storage_mapper("userId")] - fn user_id(&self) -> AddressToIdMapper; - - #[storage_mapper("subscribedUsers")] - fn subscribed_users( - &self, - service_id: AddressId, - service_index: usize, - ) -> UnorderedSetMapper; - - #[storage_mapper("serviceInfo")] - fn service_info( - &self, - service_id: AddressId, - ) -> SingleValueMapper>>; -} diff --git a/subscriber/src/daily_operations.rs b/subscriber/src/daily_operations.rs deleted file mode 100644 index b2dde02..0000000 --- a/subscriber/src/daily_operations.rs +++ /dev/null @@ -1,170 +0,0 @@ -use core::borrow::Borrow; - -use auto_farm::common::address_to_id_mapper::AddressId; -use multiversx_sc::api::StorageMapperApi; -use multiversx_sc_modules::ongoing_operation::{LoopOp, CONTINUE_OP, STOP_OP}; -use subscription_fee::service::ServiceInfo; - -use crate::base_functions::SubscriberContract; - -multiversx_sc::imports!(); -multiversx_sc::derive_imports!(); - -pub const FIRST_INDEX: usize = 1; - -#[derive(TypeAbi, TopEncode, TopDecode, Default)] -pub struct ClaimRewardsOperationProgress { - pub service_index: usize, - pub user_index: usize, - pub additional_data_index: usize, -} - -pub struct OperationData< - M: ManagedTypeApi + StorageMapperApi, - AdditionalDataType: ManagedVecItem + Clone, -> { - pub additional_data: ManagedVec, - pub additional_data_len: usize, - pub user_index: usize, - pub total_users: usize, - pub users_mapper: UnorderedSetMapper, - pub service_info: ServiceInfo, - pub service_index: usize, - pub fees_contract_address: ManagedAddress, -} - -#[multiversx_sc::module] -pub trait DailyOperationsModule: - crate::service::ServiceModule - + crate::common_storage::CommonStorageModule - + multiversx_sc_modules::ongoing_operation::OngoingOperationModule -{ - fn perform_service>( - &self, - gas_to_save_progress: u64, - service_index: usize, - user_index: &mut usize, - additional_data: ManagedVec, - ) -> OperationCompletionStatus { - let own_address = self.blockchain().get_sc_address(); - let fees_contract_address = self.fees_contract_address().get(); - let service_id = self - .service_id() - .get_id_at_address_non_zero(&fees_contract_address, &own_address); - - let mut progress = self.load_operation::(); - if progress.user_index == 0 { - progress.service_index = service_index; - progress.user_index = *user_index; - progress.additional_data_index = 0; - } else { - require!( - progress.service_index == service_index, - "Another operation is in progress" - ); - } - - let users_mapper = self.subscribed_users(service_id, service_index); - let total_users = users_mapper.len_at_address(&fees_contract_address); - - let mut all_data = OperationData:: { - additional_data_len: additional_data.len(), - additional_data, - user_index: *user_index, - total_users, - users_mapper, - service_info: self - .service_info(service_id) - .get_from_address(&fees_contract_address) - .get(service_index), - service_index, - fees_contract_address, - }; - - let run_result = self.run_while_it_has_gas(gas_to_save_progress, || { - self.perform_one_operation::(&mut progress, &mut all_data) - }); - - if run_result == OperationCompletionStatus::InterruptedBeforeOutOfGas { - self.save_progress(&progress); - } - - *user_index = progress.user_index; - - run_result - } - - fn perform_one_operation>( - &self, - progress: &mut ClaimRewardsOperationProgress, - all_data: &mut OperationData, - ) -> LoopOp { - if progress.additional_data_index >= all_data.additional_data_len - || progress.user_index > all_data.total_users - { - return STOP_OP; - } - - let user_data = all_data.additional_data.get(progress.additional_data_index); - progress.additional_data_index += 1; - - let user_id = all_data - .users_mapper - .get_by_index_at_address(&all_data.fees_contract_address, progress.user_index); - let opt_user_address = self - .user_id() - .get_address_at_address(&all_data.fees_contract_address, user_id); - let user_address = match opt_user_address { - Some(address) => address, - None => { - return CONTINUE_OP; - } - }; - - progress.user_index += 1; - - let action_results = SC::perform_action( - self, - user_address.clone(), - all_data.service_index, - &all_data.service_info, - user_data.borrow(), - ); - if let Result::Ok(interpreted_results) = action_results { - self.send_user_rewards(&user_address, interpreted_results.user_rewards); - } - - CONTINUE_OP - } - - fn send_user_rewards( - &self, - user_address: &ManagedAddress, - rewards: ManagedVec, - ) { - for rew in &rewards { - self.send().direct_non_zero_esdt_payment(user_address, &rew); - } - } - - fn get_user_index( - &self, - fees_contract_address: &ManagedAddress, - service_id: AddressId, - service_index: usize, - ) -> usize { - let last_user_index = self - .subscribed_users(service_id, service_index) - .len_at_address(fees_contract_address); - let stored_user_index = self.user_index().get(); - - if stored_user_index != 0 && stored_user_index < last_user_index { - stored_user_index - } else { - 1 - } - } - - #[storage_mapper("userIndex")] - fn user_index(&self) -> SingleValueMapper; -} diff --git a/subscriber/src/lib.rs b/subscriber/src/lib.rs deleted file mode 100644 index a8881a8..0000000 --- a/subscriber/src/lib.rs +++ /dev/null @@ -1,84 +0,0 @@ -#![no_std] -#![feature(trait_alias)] - -use core::marker::PhantomData; - -use base_functions::{AllBaseTraits, InterpretedResult, SubscriberContract}; -use subscription_fee::service::ServiceInfo; - -multiversx_sc::imports!(); -multiversx_sc::derive_imports!(); - -pub mod base_functions; -pub mod base_init; -pub mod common_storage; -pub mod daily_operations; -pub mod service; - -pub const DEFAULT_GAS_TO_SAVE_PROGRESS: u64 = 100_000; - -#[multiversx_sc::contract] -pub trait SubscriberContractMain: - base_init::BaseInitModule - + service::ServiceModule - + daily_operations::DailyOperationsModule - + common_storage::CommonStorageModule - + multiversx_sc_modules::ongoing_operation::OngoingOperationModule -{ - #[init] - fn init(&self, fees_contract_address: ManagedAddress) { - self.base_init(fees_contract_address); - } - - fn dummy_perform_action(&self, service_index: usize) -> OperationCompletionStatus { - let fees_contract_address = self.fees_contract_address().get(); - let mut user_index = self.get_user_index(&fees_contract_address, 1, service_index); - - let mut dummy_args = ManagedVec::new(); - for _ in 0..10 { - dummy_args.push(DummyData { dummy_data: 0 }); - } - - let run_result = self.perform_service::>( - DEFAULT_GAS_TO_SAVE_PROGRESS, - service_index, - &mut user_index, - dummy_args, - ); - - self.user_index().set(user_index); - - run_result - } -} - -pub struct DummyWrapper { - _phantom: PhantomData, -} - -#[derive(Clone, ManagedVecItem)] -pub struct DummyData { - pub dummy_data: u8, -} - -impl SubscriberContract for DummyWrapper -where - T: AllBaseTraits, -{ - type SubSc = T; - type AdditionalDataType = DummyData; - - fn perform_action( - _sc: &Self::SubSc, - _user_address: ManagedAddress<::Api>, - _service_index: usize, - _service_info: &ServiceInfo<::Api>, - _additional_data: &::AdditionalDataType, - ) -> Result::Api>, ()> { - let result = InterpretedResult { - user_rewards: ManagedVec::new(), - }; - - Result::Ok(result) - } -} diff --git a/subscriber/src/service.rs b/subscriber/src/service.rs deleted file mode 100644 index 71c9304..0000000 --- a/subscriber/src/service.rs +++ /dev/null @@ -1,217 +0,0 @@ -use auto_farm::common::address_to_id_mapper::AddressId; -use multiversx_sc::api::StorageMapperApi; -use multiversx_sc_modules::ongoing_operation::{LoopOp, CONTINUE_OP, STOP_OP}; -use subscription_fee::{ - service::ProxyTrait as _, - subtract_payments::{Epoch, MyVeryOwnScResult, ProxyTrait as _, MONTHLY_EPOCHS}, -}; - -multiversx_sc::imports!(); -multiversx_sc::derive_imports!(); - -// Careful to not have this be the exact same size as ClaimRewardsOperationProgress struct!!! -#[derive(TypeAbi, TopEncode, TopDecode, Default)] -pub struct SubtractPaymentOperation { - pub service_index: usize, - pub user_index: usize, -} - -#[derive(TypeAbi, TopEncode, TopDecode)] -pub struct UserFees { - pub fees: EgldOrEsdtTokenPayment, - pub epoch: Epoch, -} - -pub struct PaymentOperationData { - pub total_users: usize, - pub service_index: usize, - pub current_epoch: Epoch, - pub fees_contract_address: ManagedAddress, - pub users_mapper: UnorderedSetMapper, -} - -pub const GAS_TO_SAVE_PAYMENT_PROGRESS: u64 = 200_000; - -#[multiversx_sc::module] -pub trait ServiceModule: - crate::common_storage::CommonStorageModule - + multiversx_sc_modules::ongoing_operation::OngoingOperationModule -{ - /// Arguments are pairs of sc_address, opt_payment_token and payment_amount - #[only_owner] - #[endpoint(registerService)] - fn register_service( - &self, - args: MultiValueEncoded< - MultiValue3, BigUint>, - >, - ) { - let fees_contract_address = self.fees_contract_address().get(); - let _: () = self - .register_service_proxy_obj(fees_contract_address) - .register_service(args) - .execute_on_dest_context(); - } - - #[only_owner] - #[endpoint(unregisterService)] - fn unregister_service(&self) { - let fees_contract_address = self.fees_contract_address().get(); - let _: () = self - .register_service_proxy_obj(fees_contract_address) - .unregister_service() - .execute_on_dest_context(); - } - - #[only_owner] - #[endpoint(subtractPayment)] - fn subtract_payment_endpoint(&self, service_index: usize) -> OperationCompletionStatus { - let own_address = self.blockchain().get_sc_address(); - let fees_contract_address = self.fees_contract_address().get(); - let service_id = self - .service_id() - .get_id_at_address_non_zero(&fees_contract_address, &own_address); - let current_epoch = self.blockchain().get_block_epoch(); - let next_sub_epoch = self.next_subtract_epoch(service_index).get(); - require!( - current_epoch >= next_sub_epoch, - "Cannot subtract payment yet!" - ); - - let user_index = - self.get_subtract_user_index(&fees_contract_address, service_id, service_index); - let mut progress = self.load_operation::(); - if progress.user_index == 0 { - progress.service_index = service_index; - progress.user_index = user_index; - } else { - require!( - progress.service_index == service_index, - "Another operation is in progress" - ); - } - - let users_mapper = self.subscribed_users(service_id, service_index); - let total_users = users_mapper.len_at_address(&fees_contract_address); - let all_data = PaymentOperationData { - current_epoch, - fees_contract_address, - service_index, - total_users, - users_mapper, - }; - - let run_result = self.run_while_it_has_gas(GAS_TO_SAVE_PAYMENT_PROGRESS, || { - self.perform_one_sub_operation(&mut progress, &all_data) - }); - - match run_result { - OperationCompletionStatus::Completed => self - .next_subtract_epoch(service_index) - .set(current_epoch + MONTHLY_EPOCHS), - OperationCompletionStatus::InterruptedBeforeOutOfGas => self.save_progress(&progress), - } - - self.subtract_user_index().set(progress.user_index); - - run_result - } - - fn perform_one_sub_operation( - &self, - progress: &mut SubtractPaymentOperation, - all_data: &PaymentOperationData, - ) -> LoopOp { - if progress.user_index > all_data.total_users { - self.next_subtract_epoch(all_data.service_index) - .set(all_data.current_epoch + MONTHLY_EPOCHS); - - return STOP_OP; - } - - let user_id = all_data - .users_mapper - .get_by_index_at_address(&all_data.fees_contract_address, progress.user_index); - let opt_user_address = self - .user_id() - .get_address_at_address(&all_data.fees_contract_address, user_id); - if opt_user_address.is_none() { - return CONTINUE_OP; - } - - progress.user_index += 1; - - let fees_mapper = self.user_fees(all_data.service_index, user_id); - require!(fees_mapper.is_empty(), "Last fees not processed yet"); - - let subtract_result = self.call_subtract_payment( - all_data.fees_contract_address.clone(), - all_data.service_index, - user_id, - ); - if let MyVeryOwnScResult::Ok(fees) = subtract_result { - let user_fees = UserFees { - fees, - epoch: all_data.current_epoch, - }; - - fees_mapper.set(user_fees); - } - - CONTINUE_OP - } - - fn get_subtract_user_index( - &self, - fees_contract_address: &ManagedAddress, - service_id: AddressId, - service_index: usize, - ) -> usize { - let last_user_index = self - .subscribed_users(service_id, service_index) - .len_at_address(fees_contract_address); - let stored_user_index = self.subtract_user_index().get(); - - if stored_user_index != 0 && stored_user_index <= last_user_index { - stored_user_index - } else { - 1 - } - } - - fn call_subtract_payment( - &self, - fee_contract_address: ManagedAddress, - service_index: usize, - user_id: AddressId, - ) -> MyVeryOwnScResult { - self.fee_contract_proxy_obj(fee_contract_address) - .subtract_payment(service_index, user_id) - .execute_on_dest_context() - } - - #[proxy] - fn register_service_proxy_obj( - &self, - sc_address: ManagedAddress, - ) -> subscription_fee::Proxy; - - #[proxy] - fn fee_contract_proxy_obj( - &self, - sc_address: ManagedAddress, - ) -> subscription_fee::Proxy; - - #[storage_mapper("subtractUserIndex")] - fn subtract_user_index(&self) -> SingleValueMapper; - - #[storage_mapper("nextSubtractEpoch")] - fn next_subtract_epoch(&self, service_index: usize) -> SingleValueMapper; - - #[storage_mapper("userFees")] - fn user_fees( - &self, - service_index: usize, - user_id: AddressId, - ) -> SingleValueMapper>; -} diff --git a/subscriber/tests/subscriber_setup/mod.rs b/subscriber/tests/subscriber_setup/mod.rs deleted file mode 100644 index 8afb917..0000000 --- a/subscriber/tests/subscriber_setup/mod.rs +++ /dev/null @@ -1,111 +0,0 @@ -use std::{cell::RefCell, rc::Rc}; - -use multiversx_sc::types::{Address, MultiValueEncoded}; -use multiversx_sc_scenario::{ - managed_address, managed_biguint, managed_token_id_wrapped, rust_biguint, - testing_framework::{BlockchainStateWrapper, ContractObjWrapper, TxResult}, - DebugApi, -}; -use subscriber::{service::ServiceModule, SubscriberContractMain}; - -pub struct SubscriberSetup -where - SubscriberObjBuilder: 'static + Copy + Fn() -> subscriber::ContractObj, -{ - pub b_mock: Rc>, - pub owner_addr: Address, - pub sub_wrapper: ContractObjWrapper, SubscriberObjBuilder>, -} - -impl SubscriberSetup -where - SubscriberObjBuilder: 'static + Copy + Fn() -> subscriber::ContractObj, -{ - pub fn new( - b_mock: Rc>, - builder: SubscriberObjBuilder, - fee_contract_address: &Address, - owner_addr: &Address, - ) -> Self { - let rust_zero = rust_biguint!(0); - let sub_wrapper = b_mock.borrow_mut().create_sc_account( - &rust_zero, - Some(owner_addr), - builder, - "some other wasm path", - ); - - b_mock - .borrow_mut() - .execute_tx(owner_addr, &sub_wrapper, &rust_zero, |sc| { - sc.init(managed_address!(fee_contract_address)); - }) - .assert_ok(); - - Self { - b_mock, - owner_addr: owner_addr.clone(), - sub_wrapper, - } - } - - pub fn call_register_service( - &mut self, - args: Vec<(Address, Option>, u64)>, - ) -> TxResult { - self.b_mock.borrow_mut().execute_tx( - &self.owner_addr, - &self.sub_wrapper, - &rust_biguint!(0), - |sc| { - let mut args_encoded = MultiValueEncoded::new(); - for arg in args { - let (sc_address, opt_token_id, value) = arg; - args_encoded.push( - ( - managed_address!(&sc_address), - opt_token_id.map(|token_id| managed_token_id_wrapped!(token_id)), - managed_biguint!(value), - ) - .into(), - ); - } - - sc.register_service(args_encoded); - }, - ) - } - - pub fn call_unregister_service(&mut self) -> TxResult { - self.b_mock.borrow_mut().execute_tx( - &self.owner_addr, - &self.sub_wrapper, - &rust_biguint!(0), - |sc| { - sc.unregister_service(); - }, - ) - } - - pub fn call_subtract_payment(&mut self, service_index: usize) -> TxResult { - self.b_mock.borrow_mut().execute_tx( - &self.owner_addr, - &self.sub_wrapper, - &rust_biguint!(0), - |sc| { - sc.subtract_payment_endpoint(service_index); - }, - ) - } - - pub fn call_perform_action(&mut self, service_index: usize) -> TxResult { - self.b_mock.borrow_mut().execute_tx( - &self.owner_addr, - &self.sub_wrapper, - &rust_biguint!(0), - |sc| { - sc.dummy_perform_action(service_index); - }, - ) - } -} diff --git a/subscriber/tests/subscriber_test.rs b/subscriber/tests/subscriber_test.rs deleted file mode 100644 index bef9472..0000000 --- a/subscriber/tests/subscriber_test.rs +++ /dev/null @@ -1,307 +0,0 @@ -#![allow(deprecated)] - -use std::{cell::RefCell, rc::Rc}; - -use multiversx_sc_scenario::{ - managed_address, managed_token_id, rust_biguint, testing_framework::BlockchainStateWrapper, - DebugApi, -}; -use pair_setup::PairSetup; -use subscriber_setup::SubscriberSetup; -use subscription_fee::{pair_actions::PairActionsModule, service::SubscriptionType}; -use subscription_setup::SubscriptionSetup; - -mod pair_setup; -mod subscriber_setup; -mod subscription_setup; - -static FIRST_TOKEN_ID: &[u8] = b"MYTOKEN-123456"; -static USDC_TOKEN_ID: &[u8] = b"USDC-123456"; -static LP_TOKEN_ID: &[u8] = b"LPTOK-123456"; - -fn init_all< - PairBuilder: 'static + Copy + Fn() -> pair::ContractObj, - SubscriptionObjBuilder: 'static + Copy + Fn() -> subscription_fee::ContractObj, - SubscriberBuilder: 'static + Copy + Fn() -> subscriber::ContractObj, ->( - pair_builder: PairBuilder, - sub_builder: SubscriptionObjBuilder, - subscriber_builder: SubscriberBuilder, -) -> ( - Rc>, - PairSetup, - SubscriptionSetup, - SubscriberSetup, -) { - let mut b_mock = BlockchainStateWrapper::new(); - let owner = b_mock.create_user_account(&rust_biguint!(0)); - - let b_mock_ref = RefCell::new(b_mock); - let b_mock_rc = Rc::new(b_mock_ref); - let pair_setup = PairSetup::new( - b_mock_rc.clone(), - pair_builder, - &owner, - FIRST_TOKEN_ID, - USDC_TOKEN_ID, - LP_TOKEN_ID, - 1_000_000_000, - 2_000_000_000, - ); - let sub_sc = SubscriptionSetup::new( - b_mock_rc.clone(), - sub_builder, - &owner, - pair_setup.pair_wrapper.address_ref(), - vec![FIRST_TOKEN_ID.to_vec()], - ); - - b_mock_rc - .borrow_mut() - .execute_tx(&owner, &sub_sc.s_wrapper, &rust_biguint!(0), |sc| { - sc.add_usdc_pair( - managed_token_id!(FIRST_TOKEN_ID), - managed_address!(pair_setup.pair_wrapper.address_ref()), - ); - }) - .assert_ok(); - - let subscriber = SubscriberSetup::new( - b_mock_rc.clone(), - subscriber_builder, - sub_sc.s_wrapper.address_ref(), - &owner, - ); - - (b_mock_rc, pair_setup, sub_sc, subscriber) -} - -#[test] -fn init_test() { - let _ = init_all( - pair::contract_obj, - subscription_fee::contract_obj, - subscriber::contract_obj, - ); -} - -#[test] -fn register_service_test() { - let (_, _, mut subscription_setup, mut subscriber_setup) = init_all( - pair::contract_obj, - subscription_fee::contract_obj, - subscriber::contract_obj, - ); - - subscriber_setup - .call_register_service(vec![ - ( - subscriber_setup.sub_wrapper.address_ref().clone(), - Some(FIRST_TOKEN_ID.to_vec()), - 1_000, - ), - ( - subscriber_setup.sub_wrapper.address_ref().clone(), - Some(FIRST_TOKEN_ID.to_vec()), - 500, - ), - ]) - .assert_ok(); - - subscription_setup - .call_approve_service(subscriber_setup.sub_wrapper.address_ref()) - .assert_ok(); -} - -#[test] -fn unregister_test() { - let (_, _, mut subscription_setup, mut subscriber_setup) = init_all( - pair::contract_obj, - subscription_fee::contract_obj, - subscriber::contract_obj, - ); - - subscriber_setup - .call_register_service(vec![ - ( - subscriber_setup.sub_wrapper.address_ref().clone(), - Some(FIRST_TOKEN_ID.to_vec()), - 1_000, - ), - ( - subscriber_setup.sub_wrapper.address_ref().clone(), - Some(FIRST_TOKEN_ID.to_vec()), - 500, - ), - ]) - .assert_ok(); - - subscription_setup - .call_approve_service(subscriber_setup.sub_wrapper.address_ref()) - .assert_ok(); - - subscriber_setup.call_unregister_service().assert_ok(); -} - -#[test] -fn try_subscribe_after_unregister() { - let (b_mock_rc, _, mut subscription_setup, mut subscriber_setup) = init_all( - pair::contract_obj, - subscription_fee::contract_obj, - subscriber::contract_obj, - ); - - subscriber_setup - .call_register_service(vec![ - ( - subscriber_setup.sub_wrapper.address_ref().clone(), - Some(FIRST_TOKEN_ID.to_vec()), - 1_000, - ), - ( - subscriber_setup.sub_wrapper.address_ref().clone(), - Some(FIRST_TOKEN_ID.to_vec()), - 500, - ), - ]) - .assert_ok(); - - subscription_setup - .call_approve_service(subscriber_setup.sub_wrapper.address_ref()) - .assert_ok(); - - subscriber_setup.call_unregister_service().assert_ok(); - - let user = b_mock_rc - .borrow_mut() - .create_user_account(&rust_biguint!(0)); - b_mock_rc - .borrow_mut() - .set_esdt_balance(&user, FIRST_TOKEN_ID, &rust_biguint!(1_000_000)); - - subscription_setup - .call_deposit(&user, FIRST_TOKEN_ID, 1_000_000) - .assert_ok(); - - subscription_setup - .call_subscribe(&user, vec![(1, 0, SubscriptionType::Daily)]) - .assert_user_error("Invalid service index"); -} - -#[test] -fn subscribe_ok_test() { - let (b_mock_rc, _, mut subscription_setup, mut subscriber_setup) = init_all( - pair::contract_obj, - subscription_fee::contract_obj, - subscriber::contract_obj, - ); - - subscriber_setup - .call_register_service(vec![ - ( - subscriber_setup.sub_wrapper.address_ref().clone(), - Some(FIRST_TOKEN_ID.to_vec()), - 1_000, - ), - ( - subscriber_setup.sub_wrapper.address_ref().clone(), - Some(FIRST_TOKEN_ID.to_vec()), - 500, - ), - ]) - .assert_ok(); - - subscription_setup - .call_approve_service(subscriber_setup.sub_wrapper.address_ref()) - .assert_ok(); - - let user = b_mock_rc - .borrow_mut() - .create_user_account(&rust_biguint!(0)); - b_mock_rc - .borrow_mut() - .set_esdt_balance(&user, FIRST_TOKEN_ID, &rust_biguint!(1_000_000)); - - subscription_setup - .call_deposit(&user, FIRST_TOKEN_ID, 1_000_000) - .assert_ok(); - - subscription_setup - .call_subscribe(&user, vec![(1, 0, SubscriptionType::Daily)]) - .assert_ok(); -} - -#[test] -fn perform_daily_action_test() { - let (b_mock_rc, _, mut subscription_setup, mut subscriber_setup) = init_all( - pair::contract_obj, - subscription_fee::contract_obj, - subscriber::contract_obj, - ); - - subscriber_setup - .call_register_service(vec![ - ( - subscriber_setup.sub_wrapper.address_ref().clone(), - Some(FIRST_TOKEN_ID.to_vec()), - 1_000, - ), - ( - subscriber_setup.sub_wrapper.address_ref().clone(), - Some(FIRST_TOKEN_ID.to_vec()), - 500, - ), - ]) - .assert_ok(); - - subscription_setup - .call_approve_service(subscriber_setup.sub_wrapper.address_ref()) - .assert_ok(); - - let user = b_mock_rc - .borrow_mut() - .create_user_account(&rust_biguint!(0)); - b_mock_rc - .borrow_mut() - .set_esdt_balance(&user, FIRST_TOKEN_ID, &rust_biguint!(1_000_000)); - - subscription_setup - .call_deposit(&user, FIRST_TOKEN_ID, 1_000_000) - .assert_ok(); - - subscription_setup - .call_subscribe(&user, vec![(1, 0, SubscriptionType::Daily)]) - .assert_ok(); - - b_mock_rc.borrow_mut().set_block_epoch(10); - - subscriber_setup.call_subtract_payment(0).assert_ok(); - subscriber_setup.call_perform_action(0).assert_ok(); - - b_mock_rc.borrow().check_esdt_balance( - subscriber_setup.sub_wrapper.address_ref(), - FIRST_TOKEN_ID, - &rust_biguint!(1_000 * 30), - ); - - // try perform operation again, same epoch - subscriber_setup.call_perform_action(0).assert_ok(); - - // still same balance, no funds subtracted - b_mock_rc.borrow().check_esdt_balance( - subscriber_setup.sub_wrapper.address_ref(), - FIRST_TOKEN_ID, - &rust_biguint!(1_000 * 30), - ); - - b_mock_rc.borrow_mut().set_block_epoch(11); - - subscriber_setup.call_perform_action(0).assert_ok(); - - // still same balance, subtraction is done manually once per month - b_mock_rc.borrow().check_esdt_balance( - subscriber_setup.sub_wrapper.address_ref(), - FIRST_TOKEN_ID, - &rust_biguint!(1_000 * 30), - ); -} diff --git a/subscriber/wasm/Cargo.lock b/subscriber/wasm/Cargo.lock deleted file mode 100644 index f101bfe..0000000 --- a/subscriber/wasm/Cargo.lock +++ /dev/null @@ -1,209 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ahash" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", -] - -[[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 = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "empty" -version = "0.0.0" -dependencies = [ - "multiversx-sc", -] - -[[package]] -name = "empty-wasm" -version = "0.0.0" -dependencies = [ - "empty", - "multiversx-sc-wasm-adapter", -] - -[[package]] -name = "endian-type" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" - -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash", -] - -[[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.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" - -[[package]] -name = "multiversx-sc" -version = "0.43.2" -dependencies = [ - "bitflags", - "hashbrown", - "hex-literal", - "multiversx-sc-codec", - "multiversx-sc-derive", - "num-traits", -] - -[[package]] -name = "multiversx-sc-codec" -version = "0.18.1" -dependencies = [ - "arrayvec", - "multiversx-sc-codec-derive", -] - -[[package]] -name = "multiversx-sc-codec-derive" -version = "0.18.1" -dependencies = [ - "hex", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "multiversx-sc-derive" -version = "0.43.2" -dependencies = [ - "hex", - "proc-macro2", - "quote", - "radix_trie", - "syn", -] - -[[package]] -name = "multiversx-sc-wasm-adapter" -version = "0.43.2" -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.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "proc-macro2" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -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.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" diff --git a/subscriber/wasm/Cargo.toml b/subscriber/wasm/Cargo.toml deleted file mode 100644 index ad2bf66..0000000 --- a/subscriber/wasm/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "subscriber-wasm" -version = "0.0.0" -edition = "2018" -publish = false -authors = [ "you",] - -[lib] -crate-type = [ "cdylib",] - -[workspace] -members = [ ".",] - -[dev-dependencies] - -[profile.release] -codegen-units = 1 -opt-level = "z" -lto = true -debug = false -panic = "abort" - -[dependencies.subscriber] -path = ".." - -[dependencies.multiversx-sc-wasm-adapter] -version = "=0.43.2" diff --git a/subscriber/wasm/src/lib.rs b/subscriber/wasm/src/lib.rs deleted file mode 100644 index 8ea5e5e..0000000 --- a/subscriber/wasm/src/lib.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by the multiversx-sc multi-contract system. DO NOT EDIT. - -//////////////////////////////////////////////////// -////////////////// AUTO-GENERATED ////////////////// -//////////////////////////////////////////////////// - -// Init: 1 -// Endpoints: 0 -// Async Callback (empty): 1 -// Total number of exported functions: 2 - -#![no_std] -#![allow(internal_features)] -#![feature(lang_items)] - -multiversx_sc_wasm_adapter::allocator!(); -multiversx_sc_wasm_adapter::panic_handler!(); - -multiversx_sc_wasm_adapter::endpoints! { - empty - ( - init => init - ) -} - -multiversx_sc_wasm_adapter::async_callback_empty! {} diff --git a/subscription-fee/Cargo.toml b/subscription-fee/Cargo.toml index fe7376f..e5dab04 100644 --- a/subscription-fee/Cargo.toml +++ b/subscription-fee/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "subscription-fee" version = "0.0.0" -authors = [ "you",] +authors = ["you"] edition = "2018" publish = false @@ -9,29 +9,28 @@ publish = false path = "src/lib.rs" [dependencies.multiversx-sc] -version = "=0.43.2" +version = "=0.45.2" features = ["esdt-token-payment-legacy-decode"] [dependencies.multiversx-sc-modules] -version = "=0.43.2" +version = "=0.45.2" -[dependencies.auto-farm] -git = "https://github.com/multiversx/mx-exchange-tools-sc" -rev = "39e355f" +[dev-dependencies] +num-bigint = "0.4.2" +num-traits = "0.2" +hex = "0.4" +hex-literal = "0.3.4" + +[dependencies.common_structs] +path = "../common/common_structs" [dev-dependencies.pair] git = "https://github.com/multiversx/mx-exchange-sc" -rev = "7f25a72" +rev = "1fb9a1d" [dev-dependencies.pausable] git = "https://github.com/multiversx/mx-exchange-sc" -rev = "7f25a72" +rev = "1fb9a1d" [dev-dependencies.multiversx-sc-scenario] -version = "=0.43.2" - -[dev-dependencies] -num-bigint = "0.4.2" -num-traits = "0.2" -hex = "0.4" -hex-literal = "0.3.4" +version = "=0.45.2" \ No newline at end of file diff --git a/subscription-fee/meta/Cargo.toml b/subscription-fee/meta/Cargo.toml index 49fbca4..841c459 100644 --- a/subscription-fee/meta/Cargo.toml +++ b/subscription-fee/meta/Cargo.toml @@ -3,7 +3,7 @@ name = "subscription-fee-meta" version = "0.0.0" edition = "2018" publish = false -authors = [ "you",] +authors = ["you"] [dev-dependencies] @@ -11,4 +11,5 @@ authors = [ "you",] path = ".." [dependencies.multiversx-sc-meta] -version = "=0.43.2" +version = "=0.45.2" +default-features = false diff --git a/subscription-fee/src/common_storage.rs b/subscription-fee/src/common_storage.rs new file mode 100644 index 0000000..723d0b2 --- /dev/null +++ b/subscription-fee/src/common_storage.rs @@ -0,0 +1,78 @@ +multiversx_sc::imports!(); + +use common_structs::UniquePayments; + +use crate::{service::ServiceInfo, subtract_payments::Epoch}; + +#[multiversx_sc::module] +pub trait CommonStorageModule { + #[view(getAcceptedFeesTokens)] + #[storage_mapper("acceptedFeesTokens")] + fn accepted_fees_tokens(&self) -> UnorderedSetMapper; + + #[storage_mapper("userId")] + fn user_id(&self) -> AddressToIdMapper; + + #[view(getUserDepositedFees)] + #[storage_mapper("userDepositedFees")] + fn user_deposited_fees( + &self, + user_id: AddressId, + ) -> SingleValueMapper>; + + #[view(getMinStableTokenDepositValue)] + #[storage_mapper("minStableTokenDepositValue")] + fn min_stable_token_deposit_value(&self) -> SingleValueMapper; + + #[storage_mapper("userNextPaymentEpoch")] + fn user_next_payment_epoch( + &self, + user_id: AddressId, + service_id: AddressId, + service_index: usize, + ) -> SingleValueMapper; + + #[storage_mapper("serviceId")] + fn service_id(&self) -> AddressToIdMapper; + + #[view(getPendingServices)] + #[storage_mapper("pendingServices")] + fn pending_services(&self) -> UnorderedSetMapper; + + #[storage_mapper("pendingServiceInfo")] + fn pending_service_info( + &self, + service_address: &ManagedAddress, + ) -> SingleValueMapper>>; + + // one service may have multiple options + #[view(getServiceInfo)] + #[storage_mapper("serviceInfo")] + fn service_info( + &self, + service_id: AddressId, + ) -> SingleValueMapper>>; + + #[view(getSubscribedUsers)] + #[storage_mapper("subscribedUsers")] + fn subscribed_users( + &self, + service_id: AddressId, + service_index: usize, + ) -> UnorderedSetMapper; + + #[storage_mapper("pairAddressForToken")] + fn pair_address_for_token( + &self, + token_id: &TokenIdentifier, + ) -> SingleValueMapper>; + + #[storage_mapper("stableTokenId")] + fn stable_token_id(&self) -> SingleValueMapper; + + #[storage_mapper("wegldTokenId")] + fn wegld_token_id(&self) -> SingleValueMapper; + + #[storage_mapper("priceQueryAddress")] + fn price_query_address(&self) -> SingleValueMapper; +} diff --git a/subscription-fee/src/fees.rs b/subscription-fee/src/fees.rs index aba6cd5..8a2a47b 100644 --- a/subscription-fee/src/fees.rs +++ b/subscription-fee/src/fees.rs @@ -1,88 +1,88 @@ -use auto_farm::common::{ - address_to_id_mapper::{AddressId, AddressToIdMapper}, - unique_payments::UniquePayments, -}; - multiversx_sc::imports!(); +use common_structs::UniquePayments; + +use crate::common_storage; +use crate::pair_actions; +use crate::service::MAX_USER_DEPOSITS; + #[multiversx_sc::module] -pub trait FeesModule { +pub trait FeesModule: + pair_actions::PairActionsModule + common_storage::CommonStorageModule +{ #[only_owner] #[endpoint(addAcceptedFeesTokens)] - fn add_accepted_fees_tokens( - &self, - accepted_tokens: MultiValueEncoded, - ) { + fn add_accepted_fees_tokens(&self, accepted_tokens: MultiValueEncoded) { for token in accepted_tokens { - require!(token.is_valid(), "Invalid token"); + require!(token.is_valid_esdt_identifier(), "Invalid token"); let _ = self.accepted_fees_tokens().insert(token); } } + #[only_owner] + #[endpoint(setMinDepositValue)] + fn set_min_deposit_value(&self, min_stable_token_deposit_value: BigUint) { + if min_stable_token_deposit_value == BigUint::zero() { + self.min_stable_token_deposit_value().clear(); + } else { + self.min_stable_token_deposit_value() + .set(min_stable_token_deposit_value); + } + } + #[payable("*")] #[endpoint] fn deposit(&self) { - let (payment_token, payment_amount) = self.call_value().egld_or_single_fungible_esdt(); - require!(payment_amount > 0, "No payment"); + let payment = self.call_value().single_esdt(); + require!(payment.amount > 0, "No payment"); + require!(payment.token_nonce == 0, "Can deposit only fungible tokens"); require!( - self.accepted_fees_tokens().contains(&payment_token), + self.accepted_fees_tokens() + .contains(&payment.token_identifier), "Invalid payment token" ); + let payment_value_result = + self.get_price(payment.token_identifier.clone(), payment.amount.clone()); + require!(payment_value_result.is_ok(), "Could not get payment value"); + + let payment_value = unsafe { payment_value_result.unwrap_unchecked() }; + let min_stable_token_deposit_value = self.min_stable_token_deposit_value().get(); + require!( + payment_value >= min_stable_token_deposit_value, + "Payment value is lesser than the minimum accepted" + ); + let caller = self.blockchain().get_caller(); let caller_id = self.user_id().get_id_or_insert(&caller); - self.add_user_payment( - caller_id, - EgldOrEsdtTokenPayment::new(payment_token, 0, payment_amount), - self.user_deposited_fees(caller_id), - ); + self.add_user_payment(payment, self.user_deposited_fees(caller_id)); } #[endpoint(withdrawFunds)] fn withdraw_funds( &self, - tokens_to_withdraw: MultiValueEncoded>, - ) -> MultiValue2> { + tokens_to_withdraw: MultiValueEncoded>, + ) -> ManagedVec { let caller = self.blockchain().get_caller(); let caller_id = self.user_id().get_id_non_zero(&caller); - let user_fees_mapper = self.user_deposited_fees(caller_id); let mut all_user_tokens = user_fees_mapper.get().into_payments(); - let mut egld_amount = BigUint::zero(); let mut output_payments = ManagedVec::new(); for pair in tokens_to_withdraw { let (token_id, amount) = pair.into_tuple(); - if token_id.is_egld() { - let egld_mapper = self.user_deposited_egld(caller_id); - let user_egld_amount = egld_mapper.get(); - if user_egld_amount >= amount { - self.send().direct_egld(&caller, &amount); - egld_mapper.set(&user_egld_amount - &amount); - - egld_amount += amount; - } - - continue; - } - let mut opt_found_token_index = None; for (index, user_payment) in all_user_tokens.iter().enumerate() { - if user_payment.token_identifier == token_id && user_payment.amount >= amount { - output_payments.push(EsdtTokenPayment::new( - token_id.unwrap_esdt(), - 0, - amount.clone(), - )); + if user_payment.token_identifier == token_id { + require!(user_payment.amount >= amount, "User balance not enough"); + output_payments.push(EsdtTokenPayment::new(token_id, 0, amount.clone())); opt_found_token_index = Some(index); break; } } - if opt_found_token_index.is_none() { - continue; - } + require!(opt_found_token_index.is_some(), "Payment was not found"); let token_index = unsafe { opt_found_token_index.unwrap_unchecked() }; let mut token_info = all_user_tokens.get(token_index); @@ -100,50 +100,29 @@ pub trait FeesModule { user_fees_mapper.set(&UniquePayments::new_from_unique_payments(all_user_tokens)); - (egld_amount, output_payments).into() + output_payments } fn add_user_payment( &self, - caller_id: AddressId, - payment: EgldOrEsdtTokenPayment, + payment: EsdtTokenPayment, dest_mapper: SingleValueMapper>, ) { - if payment.token_identifier.is_egld() { - self.user_deposited_egld(caller_id) - .update(|deposited_egld| *deposited_egld += payment.amount); - - return; - } - if dest_mapper.is_empty() { let user_fees = UniquePayments::::new_from_unique_payments( - ManagedVec::from_single_item(payment.unwrap_esdt()), + ManagedVec::from_single_item(payment), ); dest_mapper.set(&user_fees); } else { dest_mapper.update(|fees| { - fees.add_payment(payment.unwrap_esdt()); + fees.add_payment(payment); + + require!( + fees.clone().into_payments().len() <= MAX_USER_DEPOSITS, + "Maximum number of deposits per user reached" + ); }); } } - - #[view(getAcceptedFeesTokens)] - #[storage_mapper("acceptedFeesTokens")] - fn accepted_fees_tokens(&self) -> UnorderedSetMapper; - - #[storage_mapper("userId")] - fn user_id(&self) -> AddressToIdMapper; - - #[view(getUserDepositedFees)] - #[storage_mapper("userDepositedFees")] - fn user_deposited_fees( - &self, - user_id: AddressId, - ) -> SingleValueMapper>; - - #[view(getUserDepositedEgld)] - #[storage_mapper("userDepositedEgld")] - fn user_deposited_egld(&self, user_id: AddressId) -> SingleValueMapper; } diff --git a/subscription-fee/src/lib.rs b/subscription-fee/src/lib.rs index 21165f6..e52c237 100644 --- a/subscription-fee/src/lib.rs +++ b/subscription-fee/src/lib.rs @@ -2,6 +2,7 @@ multiversx_sc::imports!(); +pub mod common_storage; pub mod fees; pub mod pair_actions; pub mod service; @@ -10,6 +11,7 @@ pub mod subtract_payments; #[multiversx_sc::contract] pub trait SubscriptionFee: fees::FeesModule + + common_storage::CommonStorageModule + service::ServiceModule + subtract_payments::SubtractPaymentsModule + pair_actions::PairActionsModule @@ -20,15 +22,27 @@ pub trait SubscriptionFee: #[init] fn init( &self, + stable_token_id: TokenIdentifier, + wegld_token_id: TokenIdentifier, price_query_address: ManagedAddress, - accepted_tokens: MultiValueEncoded, + accepted_tokens: MultiValueEncoded, ) { + require!( + stable_token_id.is_valid_esdt_identifier(), + "Stable token not valid" + ); + require!( + wegld_token_id.is_valid_esdt_identifier(), + "WEGLD token not valid" + ); require!( self.blockchain().is_smart_contract(&price_query_address), "Invalid price query address" ); - self.price_query_address().set(price_query_address); + self.stable_token_id().set_if_empty(stable_token_id); + self.wegld_token_id().set_if_empty(wegld_token_id); + self.price_query_address().set_if_empty(price_query_address); self.add_accepted_fees_tokens(accepted_tokens); } } diff --git a/subscription-fee/src/pair_actions.rs b/subscription-fee/src/pair_actions.rs index f554a2a..f645c8b 100644 --- a/subscription-fee/src/pair_actions.rs +++ b/subscription-fee/src/pair_actions.rs @@ -1,4 +1,5 @@ multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); pub mod pair_proxy { #[multiversx_sc::proxy] @@ -13,22 +14,26 @@ pub mod pair_proxy { } #[multiversx_sc::module] -pub trait PairActionsModule { +pub trait PairActionsModule: crate::common_storage::CommonStorageModule { #[only_owner] - #[endpoint(addUsdcPair)] - fn add_usdc_pair(&self, token_id: TokenIdentifier, pair_address: ManagedAddress) { - require!(token_id.is_valid_esdt_identifier(), "Invalid token ID"); + #[endpoint(addPairAddress)] + fn add_pair_address(&self, payment_token_id: TokenIdentifier, pair_address: ManagedAddress) { + require!( + payment_token_id.is_valid_esdt_identifier(), + "Invalid token ID" + ); require!( self.blockchain().is_smart_contract(&pair_address), "Invalid pair address" ); - self.pair_address_for_token(&token_id).set(pair_address); + self.pair_address_for_token(&payment_token_id) + .set(pair_address); } #[only_owner] - #[endpoint(removeUsdcPair)] - fn remove_usdc_pair(&self, token_id: TokenIdentifier) { + #[endpoint(removePairAddress)] + fn remove_pair_address(&self, token_id: TokenIdentifier) { self.pair_address_for_token(&token_id).clear(); } @@ -39,27 +44,50 @@ pub trait PairActionsModule { } let pair_address = mapper.get(); + let stable_token_id = self.stable_token_id().get(); + let wegld_token_id = self.wegld_token_id().get(); let price_query_address = self.price_query_address().get(); - let price: EsdtTokenPayment = self - .pair_proxy(price_query_address) - .get_safe_price_by_default_offset( - pair_address, - EsdtTokenPayment::new(token_id, 0, amount), - ) - .execute_on_dest_context(); + let price: EsdtTokenPayment = if token_id == stable_token_id { + EsdtTokenPayment::new(token_id, 0, amount) + } else { + let mut query_payment: EsdtTokenPayment = self + .pair_proxy(price_query_address.clone()) + .get_safe_price_by_default_offset( + pair_address, + EsdtTokenPayment::new(token_id, 0, amount), + ) + .execute_on_dest_context(); + + if query_payment.token_identifier == wegld_token_id { + let stable_pair_data_mapper = + self.pair_address_for_token(&query_payment.token_identifier); + if stable_pair_data_mapper.is_empty() { + return Result::Err(()); + } + let stable_pair_address = stable_pair_data_mapper.get(); + query_payment = self + .pair_proxy(price_query_address) + .get_safe_price_by_default_offset( + stable_pair_address, + EsdtTokenPayment::new( + query_payment.token_identifier, + 0, + query_payment.amount, + ), + ) + .execute_on_dest_context(); + } + + query_payment + }; - Result::Ok(price.amount) + if price.token_identifier == stable_token_id { + Result::Ok(price.amount) + } else { + Result::Err(()) + } } #[proxy] fn pair_proxy(&self, sc_address: ManagedAddress) -> pair_proxy::Proxy; - - #[storage_mapper("pairAddressForToken")] - fn pair_address_for_token( - &self, - token_id: &TokenIdentifier, - ) -> SingleValueMapper; - - #[storage_mapper("priceQueryAddress")] - fn price_query_address(&self) -> SingleValueMapper; } diff --git a/subscription-fee/src/service.rs b/subscription-fee/src/service.rs index 41147bb..7aa4af8 100644 --- a/subscription-fee/src/service.rs +++ b/subscription-fee/src/service.rs @@ -1,32 +1,29 @@ -use auto_farm::common::address_to_id_mapper::{AddressId, AddressToIdMapper, NULL_ID}; - multiversx_sc::imports!(); multiversx_sc::derive_imports!(); +use crate::common_storage; +use crate::subtract_payments::Epoch; +use crate::{fees, pair_actions}; + +pub const MAX_USER_DEPOSITS: usize = 20; +pub const MAX_SERVICES_LENGTH: usize = 20; + #[derive(TypeAbi, TopEncode, TopDecode, NestedEncode, NestedDecode, ManagedVecItem)] pub struct ServiceInfo { - pub sc_address: ManagedAddress, - pub opt_payment_token: Option>, + pub opt_payment_token: Option>, pub amount: BigUint, -} - -#[derive(TypeAbi, TopEncode, TopDecode)] -pub enum SubscriptionType { - None, - Daily, - Weekly, - Monthly, + pub subscription_epochs: Epoch, } #[multiversx_sc::module] -pub trait ServiceModule: crate::fees::FeesModule { - /// Arguments are pairs of sc_address, opt_payment_token and payment_amount +pub trait ServiceModule: + fees::FeesModule + pair_actions::PairActionsModule + common_storage::CommonStorageModule +{ + /// Arguments are MultiValue3 of opt_payment_token, payment_amount and subscription_epochs #[endpoint(registerService)] fn register_service( &self, - args: MultiValueEncoded< - MultiValue3, BigUint>, - >, + args: MultiValueEncoded, BigUint, Epoch>>, ) { require!(!args.is_empty(), "No arguments provided"); @@ -36,12 +33,9 @@ pub trait ServiceModule: crate::fees::FeesModule { let mut services = ManagedVec::::new(); for arg in args { - let (sc_address, opt_payment_token, amount) = arg.into_tuple(); - require!( - self.blockchain().is_smart_contract(&sc_address) && !sc_address.is_zero(), - "Invalid SC address" - ); + let (opt_payment_token, amount, subscription_epochs) = arg.into_tuple(); + require!(subscription_epochs > 0, "Subscription epochs must be > 0"); if let Some(token_id) = &opt_payment_token { require!( self.accepted_fees_tokens().contains(token_id), @@ -50,17 +44,63 @@ pub trait ServiceModule: crate::fees::FeesModule { } services.push(ServiceInfo { - sc_address, opt_payment_token, amount, + subscription_epochs, }); } self.pending_service_info(&service_address) - .update(|existing_services| existing_services.extend(services.iter())); + .update(|existing_services| { + existing_services.extend(services.iter()); + require!( + existing_services.len() <= MAX_SERVICES_LENGTH, + "Maximum services length reached" + ); + }); let _ = self.pending_services().insert(service_address); } + #[endpoint(addExtraServices)] + fn add_extra_services( + &self, + args: MultiValueEncoded, BigUint, Epoch>>, + ) { + require!(!args.is_empty(), "No arguments provided"); + + let service_address = self.blockchain().get_caller(); + let existing_service_id = self.service_id().get_id(&service_address); + require!(existing_service_id != NULL_ID, "Service not registered"); + + let mut services = ManagedVec::::new(); + for arg in args { + let (opt_payment_token, amount, subscription_epochs) = arg.into_tuple(); + + require!(subscription_epochs > 0, "Subscription epochs must be > 0"); + if let Some(token_id) = &opt_payment_token { + require!( + self.accepted_fees_tokens().contains(token_id), + "Invalid token ID" + ); + } + + services.push(ServiceInfo { + opt_payment_token, + amount, + subscription_epochs, + }); + } + + let service_info_mapper = self.service_info(existing_service_id); + service_info_mapper.update(|existing_services| { + existing_services.extend(services.iter()); + require!( + existing_services.len() <= MAX_SERVICES_LENGTH, + "Maximum services length reached" + ); + }); + } + #[endpoint(unregisterService)] fn unregister_service(&self) { let service_address = self.blockchain().get_caller(); @@ -73,6 +113,18 @@ pub trait ServiceModule: crate::fees::FeesModule { self.pending_service_info(&service_address).clear(); } + #[only_owner] + #[endpoint(unregisterServiceByOwner)] + fn unregister_service_by_owner(&self, service_address: ManagedAddress) { + let service_id = self.service_id().remove_by_address(&service_address); + if service_id != NULL_ID { + self.service_info(service_id).clear(); + } + + let _ = self.pending_services().swap_remove(&service_address); + self.pending_service_info(&service_address).clear(); + } + #[only_owner] #[endpoint(approveService)] fn approve_service(&self, service_address: ManagedAddress) { @@ -85,32 +137,28 @@ pub trait ServiceModule: crate::fees::FeesModule { let service_info = self.pending_service_info(&service_address).take(); self.service_info(service_id).set(&service_info); + require!( + self.service_info(service_id).get().len() <= MAX_SERVICES_LENGTH, + "Maximum services lenght reached" + ); + let _ = self.pending_services().swap_remove(&service_address); } - /// subscribe with pair of service_id, service index, subscription type + /// subscribe with the following arguments: service_id, service index #[endpoint] - fn subscribe( - &self, - services: MultiValueEncoded>, - ) { + fn subscribe(&self, services: MultiValueEncoded>) { let caller = self.blockchain().get_caller(); let caller_id = self.user_id().get_id_non_zero(&caller); - for pair in services { - let (service_id, service_index, subscription_type) = pair.into_tuple(); + for service in services { + let (service_id, service_index) = service.into_tuple(); let service_options = self.service_info(service_id).get(); require!( service_index < service_options.len(), "Invalid service index" ); - require!( - !matches!(subscription_type, SubscriptionType::None), - "Invalid subscription type" - ); - self.subscription_type(caller_id, service_id, service_index) - .set(subscription_type); let _ = self .subscribed_users(service_id, service_index) .insert(caller_id); @@ -123,56 +171,14 @@ pub trait ServiceModule: crate::fees::FeesModule { let caller = self.blockchain().get_caller(); let caller_id = self.user_id().get_id_non_zero(&caller); - for pair in services { - let (service_id, service_index) = pair.into_tuple(); - let service_options = self.service_info(service_id).get(); - require!( - service_index < service_options.len(), - "Invalid service index" - ); + for service in services { + let (service_id, service_index) = service.into_tuple(); - self.subscription_type(caller_id, service_id, service_index) - .clear(); let _ = self .subscribed_users(service_id, service_index) .swap_remove(&caller_id); + self.user_next_payment_epoch(caller_id, service_id, service_index) + .clear(); } } - - #[storage_mapper("serviceId")] - fn service_id(&self) -> AddressToIdMapper; - - #[view(getPendingServices)] - #[storage_mapper("pendingServices")] - fn pending_services(&self) -> UnorderedSetMapper; - - #[storage_mapper("pendingServiceInfo")] - fn pending_service_info( - &self, - service_address: &ManagedAddress, - ) -> SingleValueMapper>>; - - // one service may have multiple options - #[view(getServiceInfo)] - #[storage_mapper("serviceInfo")] - fn service_info( - &self, - service_id: AddressId, - ) -> SingleValueMapper>>; - - #[view(getSubscribedUsers)] - #[storage_mapper("subscribedUsers")] - fn subscribed_users( - &self, - service_id: AddressId, - service_index: usize, - ) -> UnorderedSetMapper; - - #[storage_mapper("subscriptionType")] - fn subscription_type( - &self, - user_id: AddressId, - service_id: AddressId, - service_index: usize, - ) -> SingleValueMapper; } diff --git a/subscription-fee/src/subtract_payments.rs b/subscription-fee/src/subtract_payments.rs index e762770..d6f1395 100644 --- a/subscription-fee/src/subtract_payments.rs +++ b/subscription-fee/src/subtract_payments.rs @@ -1,21 +1,15 @@ -use core::hint::unreachable_unchecked; +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); -use auto_farm::common::{address_to_id_mapper::AddressId, unique_payments::UniquePayments}; +use core::hint::unreachable_unchecked; -use crate::service::SubscriptionType; +use common_structs::UniquePayments; pub type Epoch = u64; -multiversx_sc::imports!(); -multiversx_sc::derive_imports!(); - -pub const DAILY_EPOCHS: Epoch = 1; -pub const WEEKLY_EPOCHS: Epoch = 7; -pub const MONTHLY_EPOCHS: Epoch = 30; - #[must_use] #[derive(Debug, PartialEq, Eq, Clone, TopEncode, TopDecode, TypeAbi)] -pub enum MyVeryOwnScResult< +pub enum ScResult< T: NestedEncode + NestedDecode + TypeAbi, E: NestedEncode + NestedDecode + TypeAbi, > { @@ -24,10 +18,10 @@ pub enum MyVeryOwnScResult< } impl - MyVeryOwnScResult + ScResult { pub fn is_err(&self) -> bool { - matches!(*self, MyVeryOwnScResult::Err(_)) + matches!(*self, ScResult::Err(_)) } /// # Safety @@ -35,8 +29,8 @@ impl T { match self { - MyVeryOwnScResult::Ok(t) => t, - MyVeryOwnScResult::Err(_) => unreachable_unchecked(), + ScResult::Ok(t) => t, + ScResult::Err(_) => unreachable_unchecked(), } } } @@ -46,6 +40,7 @@ pub trait SubtractPaymentsModule: crate::fees::FeesModule + crate::service::ServiceModule + crate::pair_actions::PairActionsModule + + crate::common_storage::CommonStorageModule + multiversx_sc_modules::ongoing_operation::OngoingOperationModule { #[endpoint(subtractPayment)] @@ -53,50 +48,48 @@ pub trait SubtractPaymentsModule: &self, service_index: usize, user_id: AddressId, - ) -> MyVeryOwnScResult { + ) -> ScResult { let caller = self.blockchain().get_caller(); let service_id = self.service_id().get_id_non_zero(&caller); let current_epoch = self.blockchain().get_block_epoch(); - let last_action_mapper = self.user_last_action_epoch(user_id, service_id, service_index); - let last_action_epoch = last_action_mapper.get(); - if last_action_epoch > 0 { - let next_subtract_epoch = last_action_epoch + MONTHLY_EPOCHS; - require!(next_subtract_epoch <= current_epoch, "Cannot subtract yet"); + if !self + .subscribed_users(service_id, service_index) + .contains(&user_id) + { + return ScResult::Err(()); + } + + let next_payment_mapper = self.user_next_payment_epoch(user_id, service_id, service_index); + let next_payment_epoch = next_payment_mapper.get(); + require!(next_payment_epoch <= current_epoch, "Cannot subtract yet"); + + let service_info = self.service_info(service_id).get().get(service_index); + let subscription_epochs = service_info.subscription_epochs; + + if subscription_epochs == 0 { + return ScResult::Err(()); } let opt_user_address = self.user_id().get_address(user_id); if opt_user_address.is_none() { - return MyVeryOwnScResult::Err(()); + return ScResult::Err(()); } - let subscription_type = self - .subscription_type(user_id, service_id, service_index) - .get(); - let multiplier = match subscription_type { - SubscriptionType::Daily => MONTHLY_EPOCHS / DAILY_EPOCHS, - SubscriptionType::Weekly => MONTHLY_EPOCHS / WEEKLY_EPOCHS, - SubscriptionType::Monthly => 1, - SubscriptionType::None => return MyVeryOwnScResult::Err(()), - }; - - let service_info = self.service_info(service_id).get().get(service_index); let subtract_result = match service_info.opt_payment_token { - Some(token_id) => { - self.subtract_specific_token(user_id, token_id, service_info.amount * multiplier) - } - None => self.subtract_any_token(user_id, service_info.amount * multiplier), + Some(token_id) => self.subtract_specific_token(user_id, token_id, service_info.amount), + None => self.subtract_any_token(user_id, service_info.amount), }; - if let MyVeryOwnScResult::Ok(payment) = &subtract_result { - self.send().direct( + if let ScResult::Ok(payment) = &subtract_result { + self.send().direct_esdt( &caller, &payment.token_identifier, payment.token_nonce, &payment.amount, ); - } - last_action_mapper.set(current_epoch); + next_payment_mapper.set(current_epoch + subscription_epochs); + } subtract_result } @@ -104,78 +97,59 @@ pub trait SubtractPaymentsModule: fn subtract_specific_token( &self, user_id: AddressId, - token_id: EgldOrEsdtTokenIdentifier, + token_id: TokenIdentifier, amount: BigUint, - ) -> MyVeryOwnScResult { - if token_id.is_egld() { - return self.user_deposited_egld(user_id).update(|egld_value| { - if *egld_value < amount { - return MyVeryOwnScResult::Err(()); - } - - *egld_value -= &amount; - - MyVeryOwnScResult::Ok(EgldOrEsdtTokenPayment::new( - EgldOrEsdtTokenIdentifier::egld(), - 0, - amount, - )) - }); - } - - let payment = EsdtTokenPayment::new(token_id.unwrap_esdt(), 0, amount); + ) -> ScResult { + let payment = EsdtTokenPayment::new(token_id, 0, amount); let raw_result = self .user_deposited_fees(user_id) .update(|user_fees| user_fees.deduct_payment(&payment)); match raw_result { - Result::Ok(()) => MyVeryOwnScResult::Ok(payment.into()), - Result::Err(()) => MyVeryOwnScResult::Err(()), + Result::Ok(()) => ScResult::Ok(payment), + Result::Err(()) => ScResult::Err(()), } } fn subtract_any_token( &self, user_id: AddressId, - amount: BigUint, - ) -> MyVeryOwnScResult { + amount_in_stable_token: BigUint, + ) -> ScResult { let tokens_mapper = self.user_deposited_fees(user_id); if tokens_mapper.is_empty() { - return MyVeryOwnScResult::Err(()); + return ScResult::Err(()); } let mut user_tokens = tokens_mapper.get().into_payments(); for i in 0..user_tokens.len() { let mut payment = user_tokens.get(i); - let query_result = self.get_price(payment.token_identifier.clone(), amount.clone()); + let query_result = + self.get_price(payment.token_identifier.clone(), payment.amount.clone()); if query_result.is_err() { continue; } let price = unsafe { query_result.unwrap_unchecked() }; - if price > payment.amount { + // TODO + // Think about progressive deduction + if price < amount_in_stable_token { continue; } - payment.amount -= &price; + let tokens_to_pay = &payment.amount * &amount_in_stable_token / price; + + payment.amount -= &tokens_to_pay; let _ = user_tokens.set(i, &payment); tokens_mapper.set(UniquePayments::new_from_unique_payments(user_tokens)); - return MyVeryOwnScResult::Ok(EgldOrEsdtTokenPayment::new( - EgldOrEsdtTokenIdentifier::esdt(payment.token_identifier), + return ScResult::Ok(EsdtTokenPayment::new( + payment.token_identifier, 0, - price, + tokens_to_pay, )); } - MyVeryOwnScResult::Err(()) + ScResult::Err(()) } - - #[storage_mapper("userLastActionEpoch")] - fn user_last_action_epoch( - &self, - user_id: AddressId, - service_id: AddressId, - service_index: usize, - ) -> SingleValueMapper; } diff --git a/subscription-fee/tests/subscription_setup/mod.rs b/subscription-fee/tests/subscription_setup/mod.rs index de7b1ce..ff75e8d 100644 --- a/subscription-fee/tests/subscription_setup/mod.rs +++ b/subscription-fee/tests/subscription_setup/mod.rs @@ -2,22 +2,26 @@ use std::{cell::RefCell, rc::Rc}; -use auto_farm::common::address_to_id_mapper::AddressId; -use multiversx_sc::types::{ - Address, EgldOrEsdtTokenIdentifier, MultiValueEncoded, TokenIdentifier, +use multiversx_sc::{ + storage::mappers::AddressId, + types::{Address, MultiValueEncoded}, }; use multiversx_sc_scenario::{ - managed_address, managed_biguint, managed_token_id_wrapped, rust_biguint, + managed_address, managed_biguint, managed_token_id, rust_biguint, testing_framework::{BlockchainStateWrapper, ContractObjWrapper, TxResult}, DebugApi, }; use subscription_fee::{ fees::FeesModule, - service::{ServiceModule, SubscriptionType}, - subtract_payments::SubtractPaymentsModule, + service::ServiceModule, + subtract_payments::{ScResult, SubtractPaymentsModule}, SubscriptionFee, }; +use crate::{USDC_TOKEN_ID, WEGLD_TOKEN_ID}; + +pub const MIN_USER_DEPOSIT_VALUE: u64 = 1_000_000; + pub struct SubscriptionSetup where SubscriptionObjBuilder: 'static + Copy + Fn() -> subscription_fee::ContractObj, @@ -52,16 +56,18 @@ where .execute_tx(owner_addr, &s_wrapper, &rust_zero, |sc| { let mut args = MultiValueEncoded::new(); for arg in accepted_tokens { - if &arg == b"EGLD" { - let token_id = EgldOrEsdtTokenIdentifier::egld(); - args.push(token_id); - } else { - let token_id = TokenIdentifier::from_esdt_bytes(arg); - args.push(EgldOrEsdtTokenIdentifier::esdt(token_id)); - } + let token_id = managed_token_id!(arg); + args.push(token_id); } - sc.init(managed_address!(pair_address), args); + sc.init( + managed_token_id!(USDC_TOKEN_ID), + managed_token_id!(WEGLD_TOKEN_ID), + managed_address!(pair_address), + args, + ); + + sc.set_min_deposit_value(managed_biguint!(MIN_USER_DEPOSIT_VALUE)); }) .assert_ok(); @@ -75,19 +81,19 @@ where pub fn call_register_service( &mut self, caller: &Address, - args: Vec<(Address, Option>, u64)>, + args: Vec<(Option>, u64, u64)>, ) -> TxResult { self.b_mock .borrow_mut() .execute_tx(caller, &self.s_wrapper, &rust_biguint!(0), |sc| { let mut args_encoded = MultiValueEncoded::new(); for arg in args { - let (sc_address, opt_token_id, value) = arg; + let (opt_token_id, value, subscription_epochs) = arg; args_encoded.push( ( - managed_address!(&sc_address), - opt_token_id.map(|token_id| managed_token_id_wrapped!(token_id)), + opt_token_id.map(|token_id| managed_token_id!(token_id)), managed_biguint!(value), + subscription_epochs, ) .into(), ); @@ -129,17 +135,13 @@ where ) } - pub fn call_subscribe( - &mut self, - caller: &Address, - args: Vec<(AddressId, usize, SubscriptionType)>, - ) -> TxResult { + pub fn call_subscribe(&mut self, caller: &Address, args: Vec<(AddressId, usize)>) -> TxResult { self.b_mock .borrow_mut() .execute_tx(caller, &self.s_wrapper, &rust_biguint!(0), |sc| { let mut managed_args = MultiValueEncoded::new(); for arg in args { - managed_args.push((arg.0, arg.1, arg.2).into()); + managed_args.push((arg.0, arg.1).into()); } sc.subscribe(managed_args); @@ -159,6 +161,20 @@ where }) } + pub fn call_subtract_payment_with_sc_error( + &mut self, + caller: &Address, + service_index: usize, + user_id: AddressId, + ) -> TxResult { + self.b_mock + .borrow_mut() + .execute_tx(caller, &self.s_wrapper, &rust_biguint!(0), |sc| { + let result = sc.subtract_payment(service_index, user_id); + assert_eq!(result, ScResult::Err(())); + }) + } + pub fn call_withdraw_funds( &mut self, caller: &Address, @@ -169,13 +185,8 @@ where .execute_tx(caller, &self.s_wrapper, &rust_biguint!(0), |sc| { let mut managed_args = MultiValueEncoded::new(); for token in tokens { - managed_args.push( - ( - managed_token_id_wrapped!(token.0), - managed_biguint!(token.1), - ) - .into(), - ); + managed_args + .push((managed_token_id!(token.0), managed_biguint!(token.1)).into()); } let _ = sc.withdraw_funds(managed_args); diff --git a/subscription-fee/tests/subscription_test.rs b/subscription-fee/tests/subscription_test.rs index 4959c48..c67d741 100644 --- a/subscription-fee/tests/subscription_test.rs +++ b/subscription-fee/tests/subscription_test.rs @@ -7,7 +7,7 @@ use multiversx_sc_scenario::{ DebugApi, }; use pair_setup::PairSetup; -use subscription_fee::{pair_actions::PairActionsModule, service::SubscriptionType}; +use subscription_fee::pair_actions::PairActionsModule; use subscription_setup::SubscriptionSetup; mod pair_setup; @@ -15,8 +15,11 @@ mod subscription_setup; static FIRST_TOKEN_ID: &[u8] = b"MYTOKEN-123456"; static USDC_TOKEN_ID: &[u8] = b"USDC-123456"; +static WEGLD_TOKEN_ID: &[u8] = b"WEGLD-123456"; static LP_TOKEN_ID: &[u8] = b"LPTOK-123456"; +pub const DAILY_SUBSCRIPTION_EPOCHS: u64 = 1; + fn init_all< PairBuilder: 'static + Copy + Fn() -> pair::ContractObj, SubscriptionObjBuilder: 'static + Copy + Fn() -> subscription_fee::ContractObj, @@ -54,7 +57,7 @@ fn init_all< b_mock_rc .borrow_mut() .execute_tx(&owner, &sub_sc.s_wrapper, &rust_biguint!(0), |sc| { - sc.add_usdc_pair( + sc.add_pair_address( managed_token_id!(FIRST_TOKEN_ID), managed_address!(pair_setup.pair_wrapper.address_ref()), ); @@ -71,7 +74,7 @@ fn init_test() { #[test] fn register_service_test() { - let (b_mock_rc, pair_setup, mut sub_sc) = + let (b_mock_rc, _pair_setup, mut sub_sc) = init_all(pair::contract_obj, subscription_fee::contract_obj); let rust_zero = rust_biguint!(0); @@ -80,9 +83,9 @@ fn register_service_test() { .call_register_service( &rand_service, vec![( - pair_setup.pair_wrapper.address_ref().clone(), Some(FIRST_TOKEN_ID.to_vec()), 1_000, + DAILY_SUBSCRIPTION_EPOCHS, )], ) .assert_ok(); @@ -90,7 +93,7 @@ fn register_service_test() { #[test] fn approve_test() { - let (b_mock_rc, pair_setup, mut sub_sc) = + let (b_mock_rc, _pair_setup, mut sub_sc) = init_all(pair::contract_obj, subscription_fee::contract_obj); let rust_zero = rust_biguint!(0); @@ -99,9 +102,9 @@ fn approve_test() { .call_register_service( &rand_service, vec![( - pair_setup.pair_wrapper.address_ref().clone(), Some(FIRST_TOKEN_ID.to_vec()), 1_000, + DAILY_SUBSCRIPTION_EPOCHS, )], ) .assert_ok(); @@ -111,7 +114,7 @@ fn approve_test() { #[test] fn unregister_service_test() { - let (b_mock_rc, pair_setup, mut sub_sc) = + let (b_mock_rc, _pair_setup, mut sub_sc) = init_all(pair::contract_obj, subscription_fee::contract_obj); let rust_zero = rust_biguint!(0); @@ -120,9 +123,9 @@ fn unregister_service_test() { .call_register_service( &rand_service, vec![( - pair_setup.pair_wrapper.address_ref().clone(), Some(FIRST_TOKEN_ID.to_vec()), 1_000, + DAILY_SUBSCRIPTION_EPOCHS, )], ) .assert_ok(); @@ -133,7 +136,7 @@ fn unregister_service_test() { #[test] fn subscribe_before_deposit_test() { - let (b_mock_rc, pair_setup, mut sub_sc) = + let (b_mock_rc, _pair_setup, mut sub_sc) = init_all(pair::contract_obj, subscription_fee::contract_obj); let rust_zero = rust_biguint!(0); @@ -142,22 +145,22 @@ fn subscribe_before_deposit_test() { .call_register_service( &rand_service, vec![( - pair_setup.pair_wrapper.address_ref().clone(), Some(FIRST_TOKEN_ID.to_vec()), 1_000, + DAILY_SUBSCRIPTION_EPOCHS, )], ) .assert_ok(); let user = b_mock_rc.borrow_mut().create_user_account(&rust_zero); sub_sc - .call_subscribe(&user, vec![(1, 0, SubscriptionType::Daily)]) + .call_subscribe(&user, vec![(1, 0)]) .assert_user_error("Unknown address"); } #[test] fn subscribe_before_approve_test() { - let (b_mock_rc, pair_setup, mut sub_sc) = + let (b_mock_rc, _pair_setup, mut sub_sc) = init_all(pair::contract_obj, subscription_fee::contract_obj); let rust_zero = rust_biguint!(0); @@ -166,9 +169,9 @@ fn subscribe_before_approve_test() { .call_register_service( &rand_service, vec![( - pair_setup.pair_wrapper.address_ref().clone(), Some(FIRST_TOKEN_ID.to_vec()), 1_000, + DAILY_SUBSCRIPTION_EPOCHS, )], ) .assert_ok(); @@ -183,13 +186,13 @@ fn subscribe_before_approve_test() { .assert_ok(); sub_sc - .call_subscribe(&user, vec![(1, 0, SubscriptionType::Daily)]) + .call_subscribe(&user, vec![(1, 0)]) .assert_user_error("Invalid service index"); } #[test] fn subscribe_ok_test() { - let (b_mock_rc, pair_setup, mut sub_sc) = + let (b_mock_rc, _pair_setup, mut sub_sc) = init_all(pair::contract_obj, subscription_fee::contract_obj); let rust_zero = rust_biguint!(0); @@ -198,9 +201,9 @@ fn subscribe_ok_test() { .call_register_service( &rand_service, vec![( - pair_setup.pair_wrapper.address_ref().clone(), Some(FIRST_TOKEN_ID.to_vec()), 1_000, + DAILY_SUBSCRIPTION_EPOCHS, )], ) .assert_ok(); @@ -216,14 +219,12 @@ fn subscribe_ok_test() { .call_deposit(&user, FIRST_TOKEN_ID, 1_000_000) .assert_ok(); - sub_sc - .call_subscribe(&user, vec![(1, 0, SubscriptionType::Daily)]) - .assert_ok(); + sub_sc.call_subscribe(&user, vec![(1, 0)]).assert_ok(); } #[test] fn subtract_ok_test() { - let (b_mock_rc, pair_setup, mut sub_sc) = + let (b_mock_rc, _pair_setup, mut sub_sc) = init_all(pair::contract_obj, subscription_fee::contract_obj); let rust_zero = rust_biguint!(0); @@ -232,9 +233,9 @@ fn subtract_ok_test() { .call_register_service( &rand_service, vec![( - pair_setup.pair_wrapper.address_ref().clone(), Some(FIRST_TOKEN_ID.to_vec()), 1_000, + DAILY_SUBSCRIPTION_EPOCHS, )], ) .assert_ok(); @@ -250,9 +251,7 @@ fn subtract_ok_test() { .call_deposit(&user, FIRST_TOKEN_ID, 1_000_000) .assert_ok(); - sub_sc - .call_subscribe(&user, vec![(1, 0, SubscriptionType::Daily)]) - .assert_ok(); + sub_sc.call_subscribe(&user, vec![(1, 0)]).assert_ok(); b_mock_rc.borrow_mut().set_block_epoch(10); @@ -260,16 +259,14 @@ fn subtract_ok_test() { .call_subtract_payment(&rand_service, 0, 1) .assert_ok(); - b_mock_rc.borrow().check_esdt_balance( - &rand_service, - FIRST_TOKEN_ID, - &rust_biguint!(30 * 1_000), - ); + b_mock_rc + .borrow() + .check_esdt_balance(&rand_service, FIRST_TOKEN_ID, &rust_biguint!(1_000)); } #[test] fn try_subtract_twice_same_day() { - let (b_mock_rc, pair_setup, mut sub_sc) = + let (b_mock_rc, _pair_setup, mut sub_sc) = init_all(pair::contract_obj, subscription_fee::contract_obj); let rust_zero = rust_biguint!(0); @@ -278,9 +275,9 @@ fn try_subtract_twice_same_day() { .call_register_service( &rand_service, vec![( - pair_setup.pair_wrapper.address_ref().clone(), Some(FIRST_TOKEN_ID.to_vec()), 1_000, + DAILY_SUBSCRIPTION_EPOCHS, )], ) .assert_ok(); @@ -296,9 +293,7 @@ fn try_subtract_twice_same_day() { .call_deposit(&user, FIRST_TOKEN_ID, 1_000_000) .assert_ok(); - sub_sc - .call_subscribe(&user, vec![(1, 0, SubscriptionType::Daily)]) - .assert_ok(); + sub_sc.call_subscribe(&user, vec![(1, 0)]).assert_ok(); b_mock_rc.borrow_mut().set_block_epoch(10); @@ -306,27 +301,23 @@ fn try_subtract_twice_same_day() { .call_subtract_payment(&rand_service, 0, 1) .assert_ok(); - b_mock_rc.borrow().check_esdt_balance( - &rand_service, - FIRST_TOKEN_ID, - &rust_biguint!(30 * 1_000), - ); + b_mock_rc + .borrow() + .check_esdt_balance(&rand_service, FIRST_TOKEN_ID, &rust_biguint!(1_000)); sub_sc .call_subtract_payment(&rand_service, 0, 1) .assert_user_error("Cannot subtract yet"); // still same balance - b_mock_rc.borrow().check_esdt_balance( - &rand_service, - FIRST_TOKEN_ID, - &rust_biguint!(30 * 1_000), - ); + b_mock_rc + .borrow() + .check_esdt_balance(&rand_service, FIRST_TOKEN_ID, &rust_biguint!(1_000)); } #[test] fn any_token_subtract_fee_test() { - let (b_mock_rc, pair_setup, mut sub_sc) = + let (b_mock_rc, _pair_setup, mut sub_sc) = init_all(pair::contract_obj, subscription_fee::contract_obj); let rust_zero = rust_biguint!(0); @@ -334,7 +325,7 @@ fn any_token_subtract_fee_test() { sub_sc .call_register_service( &rand_service, - vec![(pair_setup.pair_wrapper.address_ref().clone(), None, 1_000)], + vec![(None, 1_000, DAILY_SUBSCRIPTION_EPOCHS)], ) .assert_ok(); @@ -349,9 +340,7 @@ fn any_token_subtract_fee_test() { .call_deposit(&user, FIRST_TOKEN_ID, 1_000_000) .assert_ok(); - sub_sc - .call_subscribe(&user, vec![(1, 0, SubscriptionType::Daily)]) - .assert_ok(); + sub_sc.call_subscribe(&user, vec![(1, 0)]).assert_ok(); b_mock_rc.borrow_mut().set_block_epoch(10); @@ -359,17 +348,15 @@ fn any_token_subtract_fee_test() { .call_subtract_payment(&rand_service, 0, 1) .assert_ok(); - // pair has 1:2 token ratio, so for 30 * 1_000 tokens, we get 30 * 2_000 of the other - b_mock_rc.borrow().check_esdt_balance( - &rand_service, - FIRST_TOKEN_ID, - &rust_biguint!(30 * 2_000), - ); + // pair has 1:2 token ratio, so to cover the 1000 USDC price, the payment consists of 500 deposited tokens + b_mock_rc + .borrow() + .check_esdt_balance(&rand_service, FIRST_TOKEN_ID, &rust_biguint!(500)); } #[test] fn withdraw_tokens_test() { - let (b_mock_rc, pair_setup, mut sub_sc) = + let (b_mock_rc, _pair_setup, mut sub_sc) = init_all(pair::contract_obj, subscription_fee::contract_obj); let rust_zero = rust_biguint!(0); @@ -378,9 +365,9 @@ fn withdraw_tokens_test() { .call_register_service( &rand_service, vec![( - pair_setup.pair_wrapper.address_ref().clone(), Some(FIRST_TOKEN_ID.to_vec()), 1_000, + DAILY_SUBSCRIPTION_EPOCHS, )], ) .assert_ok(); @@ -396,9 +383,7 @@ fn withdraw_tokens_test() { .call_deposit(&user, FIRST_TOKEN_ID, 1_000_000) .assert_ok(); - sub_sc - .call_subscribe(&user, vec![(1, 0, SubscriptionType::Daily)]) - .assert_ok(); + sub_sc.call_subscribe(&user, vec![(1, 0)]).assert_ok(); b_mock_rc.borrow_mut().set_block_epoch(10); @@ -419,3 +404,65 @@ fn withdraw_tokens_test() { .borrow() .check_esdt_balance(&rand_service, FIRST_TOKEN_ID, &rust_biguint!(0)); } + +#[test] +fn try_substract_from_unsubscribed_user_test() { + let (b_mock_rc, _pair_setup, mut sub_sc) = + init_all(pair::contract_obj, subscription_fee::contract_obj); + let rust_zero = rust_biguint!(0); + + // Create service with 2 service indexes + let rand_service = b_mock_rc.borrow_mut().create_user_account(&rust_zero); + sub_sc + .call_register_service( + &rand_service, + vec![ + ( + Some(FIRST_TOKEN_ID.to_vec()), + 1_000, + DAILY_SUBSCRIPTION_EPOCHS, + ), + ( + Some(FIRST_TOKEN_ID.to_vec()), + 500, + DAILY_SUBSCRIPTION_EPOCHS, + ), + ], + ) + .assert_ok(); + + sub_sc.call_approve_service(&rand_service).assert_ok(); + + let user = b_mock_rc.borrow_mut().create_user_account(&rust_zero); + b_mock_rc + .borrow_mut() + .set_esdt_balance(&user, FIRST_TOKEN_ID, &rust_biguint!(1_000_000)); + + sub_sc + .call_deposit(&user, FIRST_TOKEN_ID, 1_000_000) + .assert_ok(); + + // User subscribes to the second service index + sub_sc.call_subscribe(&user, vec![(1, 1)]).assert_ok(); + + b_mock_rc.borrow_mut().set_block_epoch(10); + + // The endpoint returns a ScResult::Err(()), but does not stop the execution + sub_sc + .call_subtract_payment_with_sc_error(&rand_service, 0, 1) + .assert_ok(); + + // The service was not able to substract the payment for the wrong service index + b_mock_rc + .borrow() + .check_esdt_balance(&rand_service, FIRST_TOKEN_ID, &rust_biguint!(0)); + + // The user pays the fee for the correct service index + sub_sc + .call_subtract_payment(&rand_service, 1, 1) + .assert_ok(); + // The service has sucessfully deducted the amount for the correct service index + b_mock_rc + .borrow() + .check_esdt_balance(&rand_service, FIRST_TOKEN_ID, &rust_biguint!(500)); +} diff --git a/subscription-fee/wasm/Cargo.lock b/subscription-fee/wasm/Cargo.lock index a7bde86..924b91c 100644 --- a/subscription-fee/wasm/Cargo.lock +++ b/subscription-fee/wasm/Cargo.lock @@ -2,32 +2,24 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "adder" -version = "0.0.0" -dependencies = [ - "multiversx-sc", -] - -[[package]] -name = "adder-wasm" -version = "0.0.0" -dependencies = [ - "adder", - "multiversx-sc-wasm-adapter", -] - [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", "once_cell", "version_check", + "zerocopy", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "arrayvec" version = "0.7.4" @@ -42,9 +34,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" -version = "1.3.2" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "cfg-if" @@ -52,6 +44,14 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "common_structs" +version = "0.0.0" +dependencies = [ + "mergeable", + "multiversx-sc", +] + [[package]] name = "endian-type" version = "0.1.2" @@ -60,11 +60,12 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] name = "hashbrown" -version = "0.13.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ "ahash", + "allocator-api2", ] [[package]] @@ -75,13 +76,23 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hex-literal" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "mergeable" +version = "0.0.0" +source = "git+https://github.com/multiversx/mx-exchange-sc?rev=1fb9a1d#1fb9a1dcc47d5a37079b50f8bbd0caa2ebea441e" +dependencies = [ + "multiversx-sc", +] [[package]] name = "multiversx-sc" -version = "0.43.2" +version = "0.45.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2bdb196b3ff2b9f8c744ec2e026c22c8e02bc91e5c6ed09951415c47fef6b8" dependencies = [ "bitflags", "hashbrown", @@ -93,7 +104,9 @@ dependencies = [ [[package]] name = "multiversx-sc-codec" -version = "0.18.1" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19908153158c03df4582af08f47c0eb39fb52a7dff4736b301a66acbbb9955d3" dependencies = [ "arrayvec", "multiversx-sc-codec-derive", @@ -101,7 +114,9 @@ dependencies = [ [[package]] name = "multiversx-sc-codec-derive" -version = "0.18.1" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b03b43f9cad320992f54ed162de2ed63e3ec83ed01361e57ee9c1865fba5a2" dependencies = [ "hex", "proc-macro2", @@ -111,7 +126,9 @@ dependencies = [ [[package]] name = "multiversx-sc-derive" -version = "0.43.2" +version = "0.45.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e60b5dce707f61376f74d713218f75326121d9f6a5f09a3a63de7aea2a92be9" dependencies = [ "hex", "proc-macro2", @@ -120,9 +137,20 @@ dependencies = [ "syn", ] +[[package]] +name = "multiversx-sc-modules" +version = "0.45.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5833f8bc88104357d38a8952d2a16c3e66080e2e512c0e7001c0c003006c475" +dependencies = [ + "multiversx-sc", +] + [[package]] name = "multiversx-sc-wasm-adapter" -version = "0.43.2" +version = "0.45.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4299660d5413d9f120bfddda8105b1f9d28f0345a72f53e5dc90732c4983e45" dependencies = [ "multiversx-sc", ] @@ -153,9 +181,9 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] @@ -185,11 +213,28 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +[[package]] +name = "subscription-fee" +version = "0.0.0" +dependencies = [ + "common_structs", + "multiversx-sc", + "multiversx-sc-modules", +] + +[[package]] +name = "subscription-fee-wasm" +version = "0.0.0" +dependencies = [ + "multiversx-sc-wasm-adapter", + "subscription-fee", +] + [[package]] name = "syn" -version = "1.0.109" +version = "2.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" dependencies = [ "proc-macro2", "quote", @@ -207,3 +252,23 @@ name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "zerocopy" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/subscription-fee/wasm/Cargo.toml b/subscription-fee/wasm/Cargo.toml index d00fc36..020823a 100644 --- a/subscription-fee/wasm/Cargo.toml +++ b/subscription-fee/wasm/Cargo.toml @@ -1,17 +1,17 @@ +# Code generated by the multiversx-sc build system. DO NOT EDIT. + +# ########################################## +# ############## AUTO-GENERATED ############# +# ########################################## + [package] name = "subscription-fee-wasm" version = "0.0.0" -authors = [ "you",] edition = "2018" publish = false [lib] -crate-type = [ "cdylib",] - -[workspace] -members = [ ".",] - -[dev-dependencies] +crate-type = ["cdylib"] [profile.release] codegen-units = 1 @@ -19,9 +19,13 @@ opt-level = "z" lto = true debug = false panic = "abort" +overflow-checks = false [dependencies.subscription-fee] path = ".." [dependencies.multiversx-sc-wasm-adapter] -version = "=0.43.2" +version = "=0.45.2" + +[workspace] +members = ["."] diff --git a/subscription-fee/wasm/src/lib.rs b/subscription-fee/wasm/src/lib.rs index 0e883af..0d3f0cc 100644 --- a/subscription-fee/wasm/src/lib.rs +++ b/subscription-fee/wasm/src/lib.rs @@ -1,27 +1,47 @@ -// Code generated by the multiversx-sc multi-contract system. DO NOT EDIT. +// Code generated by the multiversx-sc build system. DO NOT EDIT. //////////////////////////////////////////////////// ////////////////// AUTO-GENERATED ////////////////// //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 2 +// Endpoints: 20 // Async Callback (empty): 1 -// Total number of exported functions: 4 +// Total number of exported functions: 22 #![no_std] -#![allow(internal_features)] + +// Configuration that works with rustc < 1.73.0. +// TODO: Recommended rustc version: 1.73.0 or newer. #![feature(lang_items)] multiversx_sc_wasm_adapter::allocator!(); multiversx_sc_wasm_adapter::panic_handler!(); multiversx_sc_wasm_adapter::endpoints! { - adder + subscription_fee ( init => init - getSum => sum - add => add + addAcceptedFeesTokens => add_accepted_fees_tokens + setMinDepositValue => set_min_deposit_value + deposit => deposit + withdrawFunds => withdraw_funds + getAcceptedFeesTokens => accepted_fees_tokens + getUserDepositedFees => user_deposited_fees + getMinStableTokenDepositValue => min_stable_token_deposit_value + getPendingServices => pending_services + getServiceInfo => service_info + getSubscribedUsers => subscribed_users + registerService => register_service + addExtraServices => add_extra_services + unregisterService => unregister_service + unregisterServiceByOwner => unregister_service_by_owner + approveService => approve_service + subscribe => subscribe + unsubscribe => unsubscribe + subtractPayment => subtract_payment + addPairAddress => add_pair_address + removePairAddress => remove_pair_address ) }