diff --git a/Cargo.lock b/Cargo.lock index 01ad6b9a371..72b7e7a1a87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,7 +78,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom", + "getrandom 0.2.14", "once_cell", "version_check", "zerocopy", @@ -99,6 +99,156 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "alloy-core" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c618bd382f0bc2ac26a7e4bfae01c9b015ca8f21b37ca40059ae35a7e62b3dc6" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-rlp", + "alloy-sol-types", +] + +[[package]] +name = "alloy-dyn-abi" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41056bde53ae10ffbbf11618efbe1e0290859e5eab0fe9ef82ebdb62f12a866f" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-type-parser", + "alloy-sol-types", + "const-hex", + "itoa", + "serde", + "serde_json", + "winnow 0.6.6", +] + +[[package]] +name = "alloy-json-abi" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c357da577dfb56998d01f574d81ad7a1958d248740a7981b205d69d65a7da404" +dependencies = [ + "alloy-primitives", + "alloy-sol-type-parser", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-primitives" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6259a506ab13e1d658796c31e6e39d2e2ee89243bcc505ddc613b35732e0a430" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more 1.0.0", + "foldhash", + "hashbrown 0.15.2", + "hex-literal", + "indexmap 2.12.0", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand 0.8.5", + "ruint", + "rustc-hash 2.1.0", + "serde", + "sha3", + "tiny-keccak", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" +dependencies = [ + "arrayvec 0.7.4", + "bytes", +] + +[[package]] +name = "alloy-sol-macro" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f9c3c7bc1f4e334e5c5fc59ec8dac894973a71b11da09065affc6094025049" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46ff7aa715eb2404cb87fa94390d2c5d5addd70d9617e20b2398ee6f48cb21f0" +dependencies = [ + "alloy-sol-macro-input", + "const-hex", + "heck 0.5.0", + "indexmap 2.12.0", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.90", + "syn-solidity", + "tiny-keccak", +] + +[[package]] +name = "alloy-sol-macro-input" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f105fa700140c0cc6e2c3377adef650c389ac57b8ead8318a2e6bd52f1ae841" +dependencies = [ + "const-hex", + "dunce", + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.90", + "syn-solidity", +] + +[[package]] +name = "alloy-sol-type-parser" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c13fc168b97411e04465f03e632f31ef94cad1c7c8951bf799237fd7870d535" +dependencies = [ + "serde", + "winnow 0.7.14", +] + +[[package]] +name = "alloy-sol-types" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1174cafd6c6d810711b4e00383037bdb458efc4fe3dbafafa16567e0320c54d8" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-macro", + "const-hex", + "serde", +] + [[package]] name = "always-assert" version = "0.1.3" @@ -203,9 +353,9 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb00293ba84f51ce3bd026bd0de55899c4e68f0a39a5728cebae3a73ffdc0a4f" dependencies = [ - "ark-ec", - "ark-ff", - "ark-std", + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-std 0.4.0", ] [[package]] @@ -214,10 +364,22 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" dependencies = [ - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", +] + +[[package]] +name = "ark-bls12-381" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df4dcc01ff89867cd86b0da835f23c3f02738353aaee7dde7495af71363b8d5" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", ] [[package]] @@ -226,10 +388,10 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" dependencies = [ - "ark-ff", - "ark-poly", - "ark-serialize", - "ark-std", + "ark-ff 0.4.2", + "ark-poly 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", "hashbrown 0.13.2", "itertools 0.10.5", @@ -237,26 +399,107 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" +dependencies = [ + "ahash", + "ark-ff 0.5.0", + "ark-poly 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "educe", + "fnv", + "hashbrown 0.15.2", + "itertools 0.13.0", + "num-bigint", + "num-integer", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ed-on-bls12-381-bandersnatch" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1786b2e3832f6f0f7c8d62d5d5a282f6952a1ab99981c54cd52b6ac1d8f02df5" +dependencies = [ + "ark-bls12-381 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-std 0.5.0", +] + +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + [[package]] name = "ark-ff" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" dependencies = [ - "ark-ff-asm", - "ark-ff-macros", - "ark-serialize", - "ark-std", + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", "digest 0.10.7", "itertools 0.10.5", "num-bigint", "num-traits", "paste", - "rustc_version", + "rustc_version 0.4.0", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" +dependencies = [ + "ark-ff-asm 0.5.0", + "ark-ff-macros 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "arrayvec 0.7.4", + "digest 0.10.7", + "educe", + "itertools 0.13.0", + "num-bigint", + "num-traits", + "paste", "zeroize", ] +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "ark-ff-asm" version = "0.4.2" @@ -267,6 +510,28 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-ff-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.90", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + [[package]] name = "ark-ff-macros" version = "0.4.2" @@ -280,27 +545,78 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-ff-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "ark-poly" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" dependencies = [ - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", "hashbrown 0.13.2", ] +[[package]] +name = "ark-poly" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" +dependencies = [ + "ahash", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "educe", + "fnv", + "hashbrown 0.15.2", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + [[package]] name = "ark-serialize" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" dependencies = [ - "ark-serialize-derive", - "ark-std", + "ark-serialize-derive 0.4.2", + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" +dependencies = [ + "ark-serialize-derive 0.5.0", + "ark-std 0.5.0", + "arrayvec 0.7.4", "digest 0.10.7", "num-bigint", ] @@ -316,6 +632,27 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-serialize-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + [[package]] name = "ark-std" version = "0.4.0" @@ -323,7 +660,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", +] + +[[package]] +name = "ark-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "ark-transcript" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47c1c928edb9d8ff24cb5dcb7651d3a98494fff3099eee95c2404cd813a9139f" +dependencies = [ + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "digest 0.10.7", + "rand_core 0.6.4", + "sha3", +] + +[[package]] +name = "ark-vrf" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9501da18569b2afe0eb934fb7afd5a247d238b94116155af4dd068f319adfe6d" +dependencies = [ + "ark-bls12-381 0.5.0", + "ark-ec 0.5.0", + "ark-ed-on-bls12-381-bandersnatch", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "digest 0.10.7", + "rand_chacha 0.3.1", + "sha2 0.10.8", + "w3f-ring-proof", + "zeroize", ] [[package]] @@ -355,48 +735,36 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "asn1-rs" -version = "0.5.2" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" +checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" dependencies = [ - "asn1-rs-derive 0.4.0", - "asn1-rs-impl 0.1.0", + "asn1-rs-derive 0.5.1", + "asn1-rs-impl", "displaydoc", "nom", "num-traits", "rusticata-macros", - "thiserror", + "thiserror 1.0.69", "time", ] [[package]] name = "asn1-rs" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" +checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60" dependencies = [ - "asn1-rs-derive 0.5.1", - "asn1-rs-impl 0.2.0", + "asn1-rs-derive 0.6.0", + "asn1-rs-impl", "displaydoc", "nom", "num-traits", "rusticata-macros", - "thiserror", + "thiserror 2.0.17", "time", ] -[[package]] -name = "asn1-rs-derive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure 0.12.6", -] - [[package]] name = "asn1-rs-derive" version = "0.5.1" @@ -410,14 +778,15 @@ dependencies = [ ] [[package]] -name = "asn1-rs-impl" -version = "0.1.0" +name = "asn1-rs-derive" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.90", + "synstructure 0.13.1", ] [[package]] @@ -450,13 +819,12 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.2.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136d4d23bcc79e27423727b36823d86233aad06dfea531837b038394d11e9928" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" dependencies = [ "concurrent-queue", - "event-listener 5.3.0", - "event-listener-strategy 0.5.1", + "event-listener-strategy 0.5.4", "futures-core", "pin-project-lite", ] @@ -486,6 +854,17 @@ dependencies = [ "futures-lite 1.13.0", ] +[[package]] +name = "async-fs" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" +dependencies = [ + "async-lock 3.3.0", + "blocking", + "futures-lite 2.3.0", +] + [[package]] name = "async-io" version = "1.13.0" @@ -556,6 +935,17 @@ dependencies = [ "futures-lite 1.13.0", ] +[[package]] +name = "async-net" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" +dependencies = [ + "async-io 2.3.2", + "blocking", + "futures-lite 2.3.0", +] + [[package]] name = "async-process" version = "1.8.1" @@ -573,6 +963,24 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel 2.5.0", + "async-io 2.3.2", + "async-lock 3.3.0", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener 5.3.0", + "futures-lite 2.3.0", + "rustix 1.1.2", +] + [[package]] name = "async-signal" version = "0.2.6" @@ -599,9 +1007,9 @@ checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", @@ -621,6 +1029,19 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "asynchronous-codec" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a860072022177f903e59730004fb5dc13db9275b79bb2aef7ba8ce831956c233" +dependencies = [ + "bytes", + "futures-sink", + "futures-util", + "memchr", + "pin-project-lite", +] + [[package]] name = "atomic-take" version = "1.1.0" @@ -646,9 +1067,9 @@ dependencies = [ [[package]] name = "auto_impl" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", @@ -694,6 +1115,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" + [[package]] name = "base64" version = "0.13.1" @@ -720,7 +1147,7 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basilisk" -version = "18.0.0" +version = "19.0.0" dependencies = [ "basilisk-runtime", "clap", @@ -752,7 +1179,7 @@ dependencies = [ "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-service", - "primitives 6.6.5", + "primitives 6.7.0", "sc-basic-authorship", "sc-block-builder", "sc-chain-spec", @@ -797,13 +1224,78 @@ dependencies = [ "substrate-frame-rpc-system", "substrate-prometheus-endpoint", "substrate-state-trie-migration-rpc", - "trie-db", + "trie-db 0.29.1", +] + +[[package]] +name = "basilisk-adapters" +version = "1.4.0" +dependencies = [ + "basilisk-traits", + "cumulus-pallet-parachain-system", + "cumulus-primitives-core", + "frame-support", + "frame-system", + "hydra-dx-math", + "hydradx-traits", + "lazy_static", + "log", + "orml-tokens", + "orml-traits", + "orml-utilities", + "orml-vesting", + "orml-xcm-support", + "pallet-asset-registry", + "pallet-balances", + "pallet-broadcast", + "pallet-currencies", + "pallet-ema-oracle", + "pallet-lbp", + "pallet-liquidity-mining", + "pallet-route-executor", + "pallet-transaction-multi-payment", + "pallet-uniques", + "pallet-xyk", + "parity-scale-codec", + "polkadot-parachain-primitives", + "pretty_assertions", + "primitive-types 0.13.1", + "primitives 6.7.0", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", +] + +[[package]] +name = "basilisk-math" +version = "8.4.0" +dependencies = [ + "hydra-dx-math", + "num-traits", + "parity-scale-codec", + "primitive-types 0.13.1", + "proptest", + "rand 0.8.5", + "rug", + "scale-info", + "serde", + "sp-arithmetic", + "sp-std", + "test-case", ] [[package]] name = "basilisk-runtime" -version = "127.0.0" +version = "128.0.0" dependencies = [ + "basilisk-adapters", + "basilisk-math", + "basilisk-traits", "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", "cumulus-pallet-xcm", @@ -815,6 +1307,7 @@ dependencies = [ "cumulus-primitives-utility", "frame-benchmarking", "frame-executive", + "frame-metadata 16.0.0", "frame-support", "frame-system", "frame-system-benchmarking", @@ -822,7 +1315,6 @@ dependencies = [ "frame-try-runtime", "hex-literal", "hydra-dx-math", - "hydradx-adapters", "hydradx-traits", "log", "orml-benchmarking", @@ -833,7 +1325,7 @@ dependencies = [ "orml-xcm", "orml-xcm-support", "orml-xtokens", - "pallet-asset-registry 2.3.6", + "pallet-asset-registry", "pallet-aura", "pallet-authorship", "pallet-balances", @@ -843,7 +1335,7 @@ dependencies = [ "pallet-collective", "pallet-conviction-voting", "pallet-currencies", - "pallet-democracy 38.0.0", + "pallet-democracy 40.1.0", "pallet-duster", "pallet-elections-phragmen", "pallet-ema-oracle", @@ -861,7 +1353,7 @@ dependencies = [ "pallet-route-executor", "pallet-scheduler", "pallet-session", - "pallet-staking 4.1.0", + "pallet-staking 4.1.5", "pallet-state-trie-migration", "pallet-timestamp", "pallet-tips", @@ -881,8 +1373,8 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain-primitives", "polkadot-runtime-common", - "primitive-types", - "primitives 6.6.5", + "primitive-types 0.13.1", + "primitives 6.7.0", "scale-info", "serde", "smallvec", @@ -911,13 +1403,28 @@ dependencies = [ "xcm-runtime-apis", ] +[[package]] +name = "basilisk-traits" +version = "1.0.0" +dependencies = [ + "frame-support", + "hydradx-traits", + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "serde", + "sp-arithmetic", + "sp-std", +] + [[package]] name = "binary-merkle-tree" -version = "15.0.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "16.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "hash-db", "log", + "parity-scale-codec", ] [[package]] @@ -941,7 +1448,7 @@ dependencies = [ "lazy_static", "lazycell", "peeking_take_while", - "prettyplease 0.2.19", + "prettyplease", "proc-macro2", "quote", "regex", @@ -950,15 +1457,49 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "bip32" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db40d3dfbeab4e031d78c844642fa0caa0b0db11ce1607ac9d2986dff1405c69" +dependencies = [ + "bs58", + "hmac 0.12.1", + "k256", + "rand_core 0.6.4", + "ripemd", + "secp256k1 0.27.0", + "sha2 0.10.8", + "subtle 2.5.0", + "zeroize", +] + [[package]] name = "bip39" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" +checksum = "43d193de1f7487df1914d3a568b772458861d33f9c54249612cc2893d6915054" dependencies = [ - "bitcoin_hashes 0.11.0", + "bitcoin_hashes 0.13.0", + "serde", + "unicode-normalization", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitcoin-internals" version = "0.2.0" @@ -966,10 +1507,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" [[package]] -name = "bitcoin_hashes" -version = "0.11.0" +name = "bitcoin-io" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" [[package]] name = "bitcoin_hashes" @@ -978,7 +1519,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" dependencies = [ "bitcoin-internals", - "hex-conservative", + "hex-conservative 0.1.2", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io", + "hex-conservative 0.2.1", ] [[package]] @@ -989,9 +1540,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "bitvec" @@ -1045,7 +1596,7 @@ checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" dependencies = [ "arrayref", "arrayvec 0.7.4", - "constant_time_eq 0.3.0", + "constant_time_eq 0.3.1", ] [[package]] @@ -1056,20 +1607,20 @@ checksum = "94230421e395b9920d23df13ea5d77a20e1725331f90fbbf6df6040b33f756ae" dependencies = [ "arrayref", "arrayvec 0.7.4", - "constant_time_eq 0.3.0", + "constant_time_eq 0.3.1", ] [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "b8ee0c1824c4dea5b5f81736aff91bae041d2c07ee1192bec91054e10e3e601e" dependencies = [ "arrayref", "arrayvec 0.7.4", "cc", "cfg-if", - "constant_time_eq 0.3.0", + "constant_time_eq 0.3.1", ] [[package]] @@ -1096,7 +1647,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ - "async-channel 2.2.1", + "async-channel 2.5.0", "async-lock 3.3.0", "async-task", "fastrand 2.0.2", @@ -1108,9 +1659,9 @@ dependencies = [ [[package]] name = "bounded-collections" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32385ecb91a31bddaf908e8dcf4a15aef1bcd3913cc03ebfad02ff6d568abc1" +checksum = "64ad8a0bed7827f0b07a5d23cec2e58cc02038a99e4ca81616cb2bb2025f804d" dependencies = [ "log", "parity-scale-codec", @@ -1124,13 +1675,13 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68534a48cbf63a4b1323c433cf21238c9ec23711e0df13b08c33e5c2082663ce" dependencies = [ - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "bp-xcm-bridge-hub-router" -version = "0.14.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.17.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "scale-info", @@ -1139,18 +1690,13 @@ dependencies = [ "staging-xcm", ] -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - [[package]] name = "bs58" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ + "sha2 0.10.8", "tinyvec", ] @@ -1171,9 +1717,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byte-slice-cast" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" [[package]] name = "byte-tools" @@ -1195,9 +1741,12 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.9.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +dependencies = [ + "serde", +] [[package]] name = "bzip2-sys" @@ -1261,18 +1810,18 @@ dependencies = [ "semver 1.0.24", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "cc" -version = "1.0.95" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" +checksum = "68064e60dbf1f17005c2fde4d07c16d8baa506fd7ffed8ccab702d93617975c7" dependencies = [ "jobserver", "libc", - "once_cell", + "shlex", ] [[package]] @@ -1311,6 +1860,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chacha" version = "0.3.0" @@ -1374,15 +1929,14 @@ dependencies = [ [[package]] name = "cid" -version = "0.10.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd94671561e36e4e7de75f753f577edafb0e7c05d6e4547229fdf7938fbcd2c3" +checksum = "3147d8272e8fa0ccd29ce51194dd98f79ddfb8191ba9e3409884e751798acf3a" dependencies = [ "core2", "multibase", - "multihash 0.18.1", - "serde", - "unsigned-varint 0.7.2", + "multihash 0.19.1", + "unsigned-varint 0.8.0", ] [[package]] @@ -1475,7 +2029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" dependencies = [ "termcolor", - "unicode-width", + "unicode-width 0.1.11", ] [[package]] @@ -1496,13 +2050,12 @@ dependencies = [ [[package]] name = "comfy-table" -version = "7.1.1" +version = "7.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7" +checksum = "4a65ebfec4fb190b6f90e944a817d60499ee0744e582530e2c9900a22e591d9a" dependencies = [ - "strum 0.26.2", - "strum_macros 0.26.2", - "unicode-width", + "unicode-segmentation", + "unicode-width 0.2.2", ] [[package]] @@ -1513,9 +2066,9 @@ checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] @@ -1529,10 +2082,22 @@ dependencies = [ "encode_unicode", "lazy_static", "libc", - "unicode-width", + "unicode-width 0.1.11", "windows-sys 0.52.0", ] +[[package]] +name = "const-hex" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735" +dependencies = [ + "cfg-if", + "cpufeatures", + "proptest", + "serde_core", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -1554,11 +2119,31 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" dependencies = [ - "getrandom", + "getrandom 0.2.14", "once_cell", "tiny-keccak", ] +[[package]] +name = "const_format" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -1567,9 +2152,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "constant_time_eq" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "constcat" @@ -1585,9 +2170,19 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "core-foundation" -version = "0.9.4" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ "core-foundation-sys", "libc", @@ -1735,27 +2330,27 @@ dependencies = [ ] [[package]] -name = "crc" -version = "3.2.1" +name = "crc32fast" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ - "crc-catalog", + "cfg-if", ] [[package]] -name = "crc-catalog" -version = "2.4.0" +name = "critical-section" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] -name = "crc32fast" -version = "1.4.0" +name = "crossbeam-channel" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ - "cfg-if", + "crossbeam-utils", ] [[package]] @@ -1805,7 +2400,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array 0.14.7", - "rand_core", + "rand_core 0.6.4", "subtle 2.5.0", "zeroize", ] @@ -1817,7 +2412,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array 0.14.7", - "rand_core", + "rand_core 0.6.4", "typenum", ] @@ -1841,6 +2436,21 @@ dependencies = [ "subtle 2.5.0", ] +[[package]] +name = "crypto_secretbox" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1" +dependencies = [ + "aead", + "cipher 0.4.4", + "generic-array 0.14.7", + "poly1305", + "salsa20", + "subtle 2.5.0", + "zeroize", +] + [[package]] name = "ctr" version = "0.9.2" @@ -1852,8 +2462,8 @@ dependencies = [ [[package]] name = "cumulus-client-cli" -version = "0.18.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.23.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "clap", "parity-scale-codec", @@ -1869,8 +2479,8 @@ dependencies = [ [[package]] name = "cumulus-client-collator" -version = "0.18.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.23.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "cumulus-client-consensus-common", "cumulus-client-network", @@ -1892,8 +2502,8 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-aura" -version = "0.18.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.23.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "cumulus-client-collator", @@ -1908,6 +2518,7 @@ dependencies = [ "parking_lot 0.12.3", "polkadot-node-primitives", "polkadot-node-subsystem", + "polkadot-node-subsystem-util", "polkadot-overseer", "polkadot-primitives", "sc-client-api", @@ -1930,6 +2541,7 @@ dependencies = [ "sp-runtime", "sp-state-machine", "sp-timestamp", + "sp-trie", "substrate-prometheus-endpoint", "tokio", "tracing", @@ -1937,8 +2549,8 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-common" -version = "0.18.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.23.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "cumulus-client-pov-recovery", @@ -1967,8 +2579,8 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-proposer" -version = "0.16.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.19.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "anyhow", "async-trait", @@ -1977,13 +2589,13 @@ dependencies = [ "sp-inherents", "sp-runtime", "sp-state-machine", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "cumulus-client-network" -version = "0.18.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.23.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "cumulus-relay-chain-interface", @@ -2008,8 +2620,8 @@ dependencies = [ [[package]] name = "cumulus-client-parachain-inherent" -version = "0.12.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.17.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -2018,20 +2630,18 @@ dependencies = [ "cumulus-test-relay-sproof-builder", "parity-scale-codec", "sc-client-api", - "sp-api", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", "sp-inherents", "sp-runtime", "sp-state-machine", "sp-storage", - "sp-trie", "tracing", ] [[package]] name = "cumulus-client-pov-recovery" -version = "0.18.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.23.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -2043,7 +2653,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-overseer", "polkadot-primitives", - "rand", + "rand 0.8.5", "sc-client-api", "sc-consensus", "sp-api", @@ -2056,8 +2666,8 @@ dependencies = [ [[package]] name = "cumulus-client-service" -version = "0.19.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.24.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "cumulus-client-cli", "cumulus-client-collator", @@ -2065,7 +2675,7 @@ dependencies = [ "cumulus-client-network", "cumulus-client-pov-recovery", "cumulus-primitives-core", - "cumulus-primitives-proof-size-hostfunction 0.10.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22)", + "cumulus-primitives-proof-size-hostfunction", "cumulus-relay-chain-inprocess-interface", "cumulus-relay-chain-interface", "cumulus-relay-chain-minimal-node", @@ -2093,8 +2703,8 @@ dependencies = [ [[package]] name = "cumulus-pallet-aura-ext" -version = "0.17.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.20.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "cumulus-pallet-parachain-system", "frame-support", @@ -2110,8 +2720,8 @@ dependencies = [ [[package]] name = "cumulus-pallet-dmp-queue" -version = "0.17.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.20.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -2126,14 +2736,14 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system" -version = "0.17.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.20.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bytes", "cumulus-pallet-parachain-system-proc-macro", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", - "cumulus-primitives-proof-size-hostfunction 0.10.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22)", + "cumulus-primitives-proof-size-hostfunction", "environmental", "frame-benchmarking", "frame-support", @@ -2143,7 +2753,6 @@ dependencies = [ "pallet-message-queue", "parity-scale-codec", "polkadot-parachain-primitives", - "polkadot-runtime-common", "polkadot-runtime-parachains", "scale-info", "sp-core", @@ -2157,13 +2766,13 @@ dependencies = [ "sp-version", "staging-xcm", "staging-xcm-builder", - "trie-db", + "trie-db 0.30.0", ] [[package]] name = "cumulus-pallet-parachain-system-proc-macro" version = "0.6.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", @@ -2173,8 +2782,8 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcm" -version = "0.17.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.19.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -2188,8 +2797,8 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcmp-queue" -version = "0.17.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.20.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bounded-collections", "bp-xcm-bridge-hub-router", @@ -2213,8 +2822,8 @@ dependencies = [ [[package]] name = "cumulus-primitives-aura" -version = "0.15.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.17.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "sp-api", "sp-consensus-aura", @@ -2222,8 +2831,8 @@ dependencies = [ [[package]] name = "cumulus-primitives-core" -version = "0.16.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.18.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "polkadot-core-primitives", @@ -2238,8 +2847,8 @@ dependencies = [ [[package]] name = "cumulus-primitives-parachain-inherent" -version = "0.16.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.18.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -2252,44 +2861,18 @@ dependencies = [ [[package]] name = "cumulus-primitives-proof-size-hostfunction" -version = "0.10.0" -source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-stable2409#03832ee1cf6e8c908d7b420229acb834ea5534bd" -dependencies = [ - "sp-externalities", - "sp-runtime-interface", - "sp-trie", -] - -[[package]] -name = "cumulus-primitives-proof-size-hostfunction" -version = "0.10.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.12.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "sp-externalities", "sp-runtime-interface", "sp-trie", ] -[[package]] -name = "cumulus-primitives-storage-weight-reclaim" -version = "8.0.0" -source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-stable2409#03832ee1cf6e8c908d7b420229acb834ea5534bd" -dependencies = [ - "cumulus-primitives-core", - "cumulus-primitives-proof-size-hostfunction 0.10.0 (git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-stable2409)", - "docify", - "frame-support", - "frame-system", - "log", - "parity-scale-codec", - "scale-info", - "sp-runtime", -] - [[package]] name = "cumulus-primitives-timestamp" -version = "0.16.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.19.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "cumulus-primitives-core", "sp-inherents", @@ -2298,8 +2881,8 @@ dependencies = [ [[package]] name = "cumulus-primitives-utility" -version = "0.17.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.20.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -2315,8 +2898,8 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-inprocess-interface" -version = "0.19.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.24.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -2339,8 +2922,8 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-interface" -version = "0.18.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.23.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -2353,13 +2936,13 @@ dependencies = [ "sp-blockchain", "sp-state-machine", "sp-version", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "cumulus-relay-chain-minimal-node" -version = "0.19.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.24.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "array-bytes", "async-trait", @@ -2387,14 +2970,13 @@ dependencies = [ "sp-consensus-babe", "sp-runtime", "substrate-prometheus-endpoint", - "tokio", "tracing", ] [[package]] name = "cumulus-relay-chain-rpc-interface" -version = "0.18.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.23.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -2406,16 +2988,16 @@ dependencies = [ "parity-scale-codec", "pin-project", "polkadot-overseer", - "rand", + "prometheus", + "rand 0.8.5", "sc-client-api", "sc-rpc-api", "sc-service", "schnellru", "serde", "serde_json", - "smoldot", - "smoldot-light", - "sp-api", + "smoldot 0.11.0", + "smoldot-light 0.9.0", "sp-authority-discovery", "sp-consensus-babe", "sp-core", @@ -2423,7 +3005,8 @@ dependencies = [ "sp-state-machine", "sp-storage", "sp-version", - "thiserror", + "substrate-prometheus-endpoint", + "thiserror 1.0.69", "tokio", "tokio-util", "tracing", @@ -2432,8 +3015,8 @@ dependencies = [ [[package]] name = "cumulus-test-relay-sproof-builder" -version = "0.16.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.19.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "cumulus-primitives-core", "parity-scale-codec", @@ -2454,7 +3037,7 @@ dependencies = [ "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "rustc_version", + "rustc_version 0.4.0", "subtle 2.5.0", "zeroize", ] @@ -2478,7 +3061,7 @@ checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" dependencies = [ "byteorder", "digest 0.9.0", - "rand_core", + "rand_core 0.6.4", "subtle-ng", "zeroize", ] @@ -2527,6 +3110,41 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.90", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.90", +] + [[package]] name = "dashmap" version = "5.5.3" @@ -2534,7 +3152,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core 0.9.9", @@ -2578,11 +3196,11 @@ dependencies = [ [[package]] name = "der-parser" -version = "8.2.0" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" +checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" dependencies = [ - "asn1-rs 0.5.2", + "asn1-rs 0.6.2", "displaydoc", "nom", "num-bigint", @@ -2592,11 +3210,11 @@ dependencies = [ [[package]] name = "der-parser" -version = "9.0.0" +version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" dependencies = [ - "asn1-rs 0.6.2", + "asn1-rs 0.7.1", "displaydoc", "nom", "num-bigint", @@ -2635,6 +3253,17 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "derive-where" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -2644,7 +3273,7 @@ dependencies = [ "convert_case", "proc-macro2", "quote", - "rustc_version", + "rustc_version 0.4.0", "syn 1.0.109", ] @@ -2666,6 +3295,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.90", + "unicode-xid", ] [[package]] @@ -2674,12 +3304,6 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" -[[package]] -name = "difflib" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" - [[package]] name = "digest" version = "0.8.1" @@ -2729,6 +3353,15 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs-sys" version = "0.4.1" @@ -2765,18 +3398,18 @@ dependencies = [ [[package]] name = "docify" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a2f138ad521dc4a2ced1a4576148a6a610b4c5923933b062a263130a6802ce" +checksum = "a772b62b1837c8f060432ddcc10b17aae1453ef17617a99bc07789252d2a5896" dependencies = [ "docify_macros", ] [[package]] name = "docify_macros" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a081e51fb188742f5a7a1164ad752121abcb22874b21e2c3b0dd040c515fdad" +checksum = "60e6be249b0a462a14784a99b19bf35a667bb5e09de611738bb7362fa4c95ff7" dependencies = [ "common-path", "derive-syn-parse", @@ -2808,6 +3441,12 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "dyn-clonable" version = "0.9.0" @@ -2868,7 +3507,7 @@ checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", - "rand_core", + "rand_core 0.6.4", "serde", "sha2 0.10.8", "subtle 2.5.0", @@ -2883,18 +3522,30 @@ checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" dependencies = [ "curve25519-dalek", "ed25519", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", - "rand_core", + "rand_core 0.6.4", "sha2 0.10.8", "zeroize", ] +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "either" -version = "1.11.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "elliptic-curve" @@ -2909,7 +3560,7 @@ dependencies = [ "generic-array 0.14.7", "group", "pkcs8", - "rand_core", + "rand_core 0.6.4", "sec1", "serdect", "subtle 2.5.0", @@ -2924,23 +3575,31 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "enum-as-inner" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.90", ] [[package]] -name = "enum-as-inner" -version = "0.6.0" +name = "enum-ordinalize" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ - "heck 0.4.1", "proc-macro2", "quote", "syn 2.0.90", @@ -2948,18 +3607,18 @@ dependencies = [ [[package]] name = "enumflags2" -version = "0.7.9" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3278c9d5fb675e0a51dabcf4c0d355f692b064171535ba72361be1528a9d8e8d" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" dependencies = [ "enumflags2_derive", ] [[package]] name = "enumflags2_derive" -version = "0.7.9" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", @@ -3004,61 +3663,53 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] -name = "ethbloom" -version = "0.13.0" +name = "ethabi-decode" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +checksum = "52029c4087f9f01108f851d0d02df9c21feb5660a19713466724b7f95bd2d773" dependencies = [ - "crunchy", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", + "ethereum-types", "tiny-keccak", ] [[package]] -name = "ethereum" -version = "0.15.0" +name = "ethbloom" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e04d24d20b8ff2235cffbf242d5092de3aa45f77c5270ddbfadd2778ca13fea" +checksum = "8c321610643004cf908ec0f5f2aa0d8f1f8e14b540562a2887a1111ff1ecbf7b" dependencies = [ - "bytes", - "ethereum-types", - "hash-db", - "hash256-std-hasher", - "parity-scale-codec", - "rlp", + "crunchy", + "fixed-hash", + "impl-codec 0.7.1", + "impl-rlp", + "impl-serde", "scale-info", - "serde", - "sha3", - "trie-root", + "tiny-keccak", ] [[package]] name = "ethereum-types" -version = "0.14.1" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +checksum = "1ab15ed80916029f878e0267c3a9f92b67df55e79af370bf66199059ae2b4ee3" dependencies = [ "ethbloom", "fixed-hash", - "impl-codec", + "impl-codec 0.7.1", "impl-rlp", "impl-serde", - "primitive-types", + "primitive-types 0.13.1", "scale-info", - "uint", + "uint 0.10.0", ] [[package]] @@ -3112,68 +3763,14 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332f51cb23d20b0de8458b86580878211da09bcd4503cb579c225b3d124cabb3" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ "event-listener 5.3.0", "pin-project-lite", ] -[[package]] -name = "evm" -version = "0.41.2" -source = "git+https://github.com/moonbeam-foundation/evm?branch=moonbeam-polkadot-stable2409#aeff7f361687b4c6a7fcbe1cf6e4fe5f2aea32b5" -dependencies = [ - "auto_impl", - "environmental", - "ethereum", - "evm-core", - "evm-gasometer", - "evm-runtime", - "log", - "parity-scale-codec", - "primitive-types", - "rlp", - "scale-info", - "serde", - "sha3", -] - -[[package]] -name = "evm-core" -version = "0.41.0" -source = "git+https://github.com/moonbeam-foundation/evm?branch=moonbeam-polkadot-stable2409#aeff7f361687b4c6a7fcbe1cf6e4fe5f2aea32b5" -dependencies = [ - "parity-scale-codec", - "primitive-types", - "scale-info", - "serde", -] - -[[package]] -name = "evm-gasometer" -version = "0.41.0" -source = "git+https://github.com/moonbeam-foundation/evm?branch=moonbeam-polkadot-stable2409#aeff7f361687b4c6a7fcbe1cf6e4fe5f2aea32b5" -dependencies = [ - "environmental", - "evm-core", - "evm-runtime", - "primitive-types", -] - -[[package]] -name = "evm-runtime" -version = "0.41.0" -source = "git+https://github.com/moonbeam-foundation/evm?branch=moonbeam-polkadot-stable2409#aeff7f361687b4c6a7fcbe1cf6e4fe5f2aea32b5" -dependencies = [ - "auto_impl", - "environmental", - "evm-core", - "primitive-types", - "sha3", -] - [[package]] name = "exit-future" version = "0.2.0" @@ -3224,6 +3821,28 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec 0.7.4", + "auto_impl", + "bytes", +] + +[[package]] +name = "fastrlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" +dependencies = [ + "arrayvec 0.7.4", + "auto_impl", + "bytes", +] + [[package]] name = "fatality" version = "0.1.1" @@ -3231,7 +3850,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec6f82451ff7f0568c6181287189126d492b5654e30a788add08027b6363d019" dependencies = [ "fatality-proc-macro", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3241,7 +3860,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb42427514b063d97ce21d5199f36c0c307d981434a6be32582bc79fe5bd2303" dependencies = [ "expander", - "indexmap 2.2.6", + "indexmap 2.12.0", "proc-macro-crate 3.1.0", "proc-macro2", "quote", @@ -3255,7 +3874,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e182f7dbc2ef73d9ef67351c5fbbea084729c48362d3ce9dd44c28e32e277fe5" dependencies = [ "libc", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3264,7 +3883,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "rand_core", + "rand_core 0.6.4", "subtle 2.5.0", ] @@ -3298,9 +3917,9 @@ dependencies = [ [[package]] name = "finality-grandpa" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36530797b9bf31cd4ff126dcfee8170f86b00cfdcea3269d73133cc0415945c3" +checksum = "b4f8f43dc520133541781ec03a8cab158ae8b7f7169cdf22e9050aa6cf0fbdfc" dependencies = [ "either", "futures", @@ -3332,7 +3951,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ "byteorder", - "rand", + "rand 0.8.5", "rustc-hex", "static_assertions", ] @@ -3343,15 +3962,6 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" -[[package]] -name = "float-cmp" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" -dependencies = [ - "num-traits", -] - [[package]] name = "fnv" version = "1.0.7" @@ -3364,25 +3974,10 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "fork-tree" -version = "13.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "13.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", ] @@ -3403,42 +3998,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8835f84f38484cc86f110a805655697908257fb9a7af005234060891557198e9" dependencies = [ "nonempty", - "thiserror", -] - -[[package]] -name = "fp-account" -version = "1.0.0-dev" -source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-stable2409#48028bbad21d66b2b9d467a5343a8707e00c8b6c" -dependencies = [ - "hex", - "impl-serde", - "libsecp256k1", - "log", - "parity-scale-codec", - "scale-info", - "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-runtime-interface", - "staging-xcm", -] - -[[package]] -name = "fp-evm" -version = "3.0.0-dev" -source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-stable2409#48028bbad21d66b2b9d467a5343a8707e00c8b6c" -dependencies = [ - "environmental", - "evm", - "frame-support", - "num_enum", - "parity-scale-codec", - "scale-info", - "serde", - "sp-core", - "sp-runtime", + "thiserror 1.0.69", ] [[package]] @@ -3449,8 +4009,8 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" [[package]] name = "frame-benchmarking" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.2.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-support", "frame-support-procedural", @@ -3473,25 +4033,28 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" -version = "43.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "48.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "Inflector", "array-bytes", "chrono", "clap", "comfy-table", + "cumulus-client-parachain-inherent", + "cumulus-primitives-proof-size-hostfunction", "frame-benchmarking", "frame-support", "frame-system", "gethostname", "handlebars", "itertools 0.11.0", - "lazy_static", "linked-hash-map", "log", "parity-scale-codec", - "rand", + "polkadot-parachain-primitives", + "polkadot-primitives", + "rand 0.8.5", "rand_pcg", "sc-block-builder", "sc-chain-spec", @@ -3499,11 +4062,13 @@ dependencies = [ "sc-client-api", "sc-client-db", "sc-executor", + "sc-runtime-utilities", "sc-service", "sc-sysinfo", "serde", "serde_json", "sp-api", + "sp-block-builder", "sp-blockchain", "sp-core", "sp-database", @@ -3515,16 +4080,35 @@ dependencies = [ "sp-runtime", "sp-state-machine", "sp-storage", + "sp-timestamp", + "sp-transaction-pool", "sp-trie", + "sp-version", "sp-wasm-interface", - "thiserror", + "subxt", + "subxt-signer", + "thiserror 1.0.69", "thousands", ] +[[package]] +name = "frame-decode" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6027a409bac4fe95b4d107f965fcdbc252fc89d884a360d076b3070b6128c094" +dependencies = [ + "frame-metadata 17.0.0", + "parity-scale-codec", + "scale-decode", + "scale-info", + "scale-type-resolver", + "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "frame-election-provider-solution-type" -version = "14.0.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "16.1.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", @@ -3534,8 +4118,8 @@ dependencies = [ [[package]] name = "frame-election-provider-support" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.1.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-election-provider-solution-type", "frame-support", @@ -3550,8 +4134,8 @@ dependencies = [ [[package]] name = "frame-executive" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "aquamarine", "frame-support", @@ -3571,6 +4155,29 @@ name = "frame-metadata" version = "16.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87cf1549fba25a6fcac22785b61698317d958e96cac72a59102ea45b9ae64692" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "frame-metadata" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "701bac17e9b55e0f95067c428ebcb46496587f08e8cf4ccc0fe5903bea10dbb8" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "frame-metadata" +version = "20.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26de808fa6461f2485dc51811aefed108850064994fb4a62b3ac21ffa62ac8df" dependencies = [ "cfg-if", "parity-scale-codec", @@ -3580,10 +4187,11 @@ dependencies = [ [[package]] name = "frame-metadata-hash-extension" -version = "0.6.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.8.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "array-bytes", + "const-hex", "docify", "frame-support", "frame-system", @@ -3595,15 +4203,16 @@ dependencies = [ [[package]] name = "frame-support" -version = "38.2.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "aquamarine", "array-bytes", + "binary-merkle-tree", "bitflags 1.3.2", "docify", "environmental", - "frame-metadata", + "frame-metadata 20.0.0", "frame-support-procedural", "impl-trait-for-tuples", "k256", @@ -3614,7 +4223,6 @@ dependencies = [ "scale-info", "serde", "serde_json", - "smallvec", "sp-api", "sp-arithmetic", "sp-core", @@ -3629,15 +4237,15 @@ dependencies = [ "sp-state-machine", "sp-std", "sp-tracing", + "sp-trie", "sp-weights", - "static_assertions", "tt-call", ] [[package]] name = "frame-support-procedural" -version = "30.0.3" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "33.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "Inflector", "cfg-expr", @@ -3647,17 +4255,17 @@ dependencies = [ "frame-support-procedural-tools", "itertools 0.11.0", "macro_magic", - "proc-macro-warning 1.0.2", + "proc-macro-warning", "proc-macro2", "quote", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", "syn 2.0.90", ] [[package]] name = "frame-support-procedural-tools" -version = "13.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "13.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate 3.1.0", @@ -3669,7 +4277,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" version = "12.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "proc-macro2", "quote", @@ -3678,8 +4286,8 @@ dependencies = [ [[package]] name = "frame-system" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.2.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "cfg-if", "docify", @@ -3691,15 +4299,14 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", "sp-version", "sp-weights", ] [[package]] name = "frame-system-benchmarking" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -3712,8 +4319,8 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" -version = "34.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "36.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "docify", "parity-scale-codec", @@ -3722,8 +4329,8 @@ dependencies = [ [[package]] name = "frame-try-runtime" -version = "0.44.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.46.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-support", "parity-scale-codec", @@ -3768,9 +4375,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -3783,9 +4390,9 @@ dependencies = [ [[package]] name = "futures-bounded" -version = "0.1.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b07bbbe7d7e78809544c6f718d875627addc73a7c3582447abc052cd3dc67e0" +checksum = "91f328e7fb845fc832912fb6a34f40cf6d1888c92f974d1893a54e97b5ff542e" dependencies = [ "futures-timer", "futures-util", @@ -3793,9 +4400,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -3803,15 +4410,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -3821,9 +4428,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" @@ -3855,9 +4462,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -3866,25 +4473,26 @@ dependencies = [ [[package]] name = "futures-rustls" -version = "0.24.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd3cf68c183738046838e300353e4716c674dc5e56890de4826801a6622a28" +checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" dependencies = [ "futures-io", - "rustls 0.21.11", + "rustls", + "rustls-pki-types", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-timer" @@ -3894,9 +4502,9 @@ checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -3919,6 +4527,20 @@ dependencies = [ "byteorder", ] +[[package]] +name = "generator" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" +dependencies = [ + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows 0.61.3", +] + [[package]] name = "generic-array" version = "0.12.4" @@ -3956,8 +4578,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasip2", + "wasm-bindgen", ] [[package]] @@ -3966,8 +4604,8 @@ version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9" dependencies = [ - "rand", - "rand_core", + "rand 0.8.5", + "rand_core 0.6.4", ] [[package]] @@ -3996,6 +4634,12 @@ name = "gimli" version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" dependencies = [ "fallible-iterator 0.3.0", "stable_deref_trait", @@ -4007,6 +4651,16 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "gmp-mpfr-sys" +version = "1.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "781d258743e6e07d38c5bcd7468cfaa068d56789d10e8de0d3836d5bb338b5d7" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "governor" version = "0.6.3" @@ -4022,7 +4676,7 @@ dependencies = [ "parking_lot 0.12.3", "portable-atomic", "quanta", - "rand", + "rand 0.8.5", "smallvec", "spinning_top", ] @@ -4034,7 +4688,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand_core", + "rand_core 0.6.4", "subtle 2.5.0", ] @@ -4050,7 +4704,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.2.6", + "indexmap 2.12.0", "slab", "tokio", "tokio-util", @@ -4069,7 +4723,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.2.0", - "indexmap 2.2.6", + "indexmap 2.12.0", "slab", "tokio", "tokio-util", @@ -4093,7 +4747,7 @@ dependencies = [ "pest_derive", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4128,9 +4782,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", @@ -4146,15 +4800,22 @@ dependencies = [ "allocator-api2", "equivalent", "foldhash", + "serde", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + [[package]] name = "hashlink" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -4187,12 +4848,113 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec 0.7.4", +] + [[package]] name = "hex-literal" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" +[[package]] +name = "hickory-proto" +version = "0.24.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92652067c9ce6f66ce53cc38d1169daa36e6e7eb7dd3b63b5103bd9d97117248" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna", + "ipnet", + "once_cell", + "rand 0.8.5", + "socket2 0.5.10", + "thiserror 1.0.69", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-proto" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna", + "ipnet", + "once_cell", + "rand 0.9.2", + "ring 0.17.8", + "thiserror 2.0.17", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.24.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto 0.24.4", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot 0.12.3", + "rand 0.8.5", + "resolv-conf", + "smallvec", + "thiserror 1.0.69", + "tokio", + "tracing", +] + +[[package]] +name = "hickory-resolver" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto 0.25.2", + "ipconfig", + "moka", + "once_cell", + "parking_lot 0.12.3", + "rand 0.9.2", + "resolv-conf", + "smallvec", + "thiserror 2.0.17", + "tokio", + "tracing", +] + [[package]] name = "hkdf" version = "0.12.4" @@ -4232,15 +4994,6 @@ dependencies = [ "hmac 0.8.1", ] -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "hostname" version = "0.3.1" @@ -4327,86 +5080,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] -name = "hydra-dx-build-script-utils" -version = "1.0.4" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +name = "humantime-serde" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a3db5ea5923d99402c94e9feb261dc5ee9b4efa158b0315f788cf549cc200c" dependencies = [ - "cargo-lock", - "platforms", + "humantime", + "serde", ] [[package]] -name = "hydra-dx-math" -version = "8.3.0" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +name = "hydra-dx-build-script-utils" +version = "1.0.4" +source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2503-11-snek#59ae6bfb45c4e37c38c95eead4c9f29e26bc478b" dependencies = [ - "fixed", - "num-traits", - "parity-scale-codec", - "primitive-types", - "scale-info", - "serde", - "sp-arithmetic", - "sp-std", + "cargo-lock", + "platforms", ] [[package]] -name = "hydradx-adapters" -version = "1.3.10" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +name = "hydra-dx-math" +version = "10.4.1" +source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2503-11-snek#59ae6bfb45c4e37c38c95eead4c9f29e26bc478b" dependencies = [ - "cumulus-pallet-parachain-system", - "cumulus-primitives-core", - "frame-support", - "frame-system", - "hydra-dx-math", - "hydradx-traits", - "log", - "orml-tokens", - "orml-traits", - "orml-utilities", - "orml-vesting", - "orml-xcm-support", - "pallet-asset-registry 3.3.0", - "pallet-balances", - "pallet-bonds", - "pallet-broadcast", - "pallet-circuit-breaker", - "pallet-currencies", - "pallet-dynamic-fees", - "pallet-ema-oracle", - "pallet-lbp", - "pallet-liquidity-mining", - "pallet-omnipool", - "pallet-omnipool-liquidity-mining", - "pallet-referrals", - "pallet-route-executor", - "pallet-stableswap", - "pallet-staking 4.1.0", - "pallet-transaction-multi-payment", - "pallet-uniques", + "fixed", + "num-traits", "parity-scale-codec", - "polkadot-parachain-primitives", - "primitive-types", - "primitives 6.1.0", + "primitive-types 0.13.1", "scale-info", + "serde", + "sp-arithmetic", "sp-core", - "sp-io", - "sp-runtime", "sp-std", - "staging-xcm", - "staging-xcm-builder", - "staging-xcm-executor", ] [[package]] name = "hydradx-traits" -version = "3.12.0" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "4.2.0" +source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2503-11-snek#59ae6bfb45c4e37c38c95eead4c9f29e26bc478b" dependencies = [ "frame-support", "impl-trait-for-tuples", "parity-scale-codec", + "primitives 6.1.2", "scale-info", "serde", "sp-arithmetic", @@ -4430,7 +5146,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.8", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -4455,22 +5171,25 @@ dependencies = [ "pin-project-lite", "smallvec", "tokio", + "want", ] [[package]] name = "hyper-rustls" -version = "0.24.2" +version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "futures-util", - "http 0.2.12", - "hyper 0.14.31", + "http 1.2.0", + "hyper 1.5.1", + "hyper-util", "log", - "rustls 0.21.11", - "rustls-native-certs 0.6.3", + "rustls", + "rustls-native-certs 0.8.2", + "rustls-pki-types", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls", + "tower-service", ] [[package]] @@ -4480,13 +5199,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", + "futures-channel", "futures-util", "http 1.2.0", "http-body 1.0.1", "hyper 1.5.1", "pin-project-lite", + "socket2 0.5.10", "tokio", "tower-service", + "tracing", ] [[package]] @@ -4500,7 +5222,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.51.1", ] [[package]] @@ -4513,34 +5235,111 @@ dependencies = [ ] [[package]] -name = "idna" -version = "0.2.3" +name = "icu_collections" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", ] [[package]] -name = "idna" -version = "0.4.0" +name = "icu_locale_core" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", ] +[[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.5.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] @@ -4560,7 +5359,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6b0422c86d7ce0e97169cc42e04ae643caf278874a7a3c87b8150a220dc7e1e" dependencies = [ "async-io 2.3.2", - "core-foundation", + "core-foundation 0.9.4", "fnv", "futures", "if-addrs", @@ -4569,7 +5368,7 @@ dependencies = [ "rtnetlink", "system-configuration", "tokio", - "windows", + "windows 0.51.1", ] [[package]] @@ -4585,7 +5384,7 @@ dependencies = [ "http 0.2.12", "hyper 0.14.31", "log", - "rand", + "rand 0.8.5", "tokio", "url", "xmltree", @@ -4600,33 +5399,53 @@ dependencies = [ "parity-scale-codec", ] +[[package]] +name = "impl-codec" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d40b9d5e17727407e55028eafc22b2dc68781786e6d7eb8a21103f5058e3a14" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-num-traits" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "803d15461ab0dcc56706adf266158acbc44ccf719bf7d0af30705f58b90a4b8c" +dependencies = [ + "integer-sqrt", + "num-traits", + "uint 0.10.0", +] + [[package]] name = "impl-rlp" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +checksum = "54ed8ad1f3877f7e775b8cbf30ed1bd3209a95401817f19a0eb4402d13f8cf90" dependencies = [ - "rlp", + "rlp 0.6.1", ] [[package]] name = "impl-serde" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +checksum = "4a143eada6a1ec4aefa5049037a26a6d597bfd64f8c026d07b77133e02b7dd0b" dependencies = [ "serde", ] [[package]] name = "impl-trait-for-tuples" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.90", ] [[package]] @@ -4661,12 +5480,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.16.0", + "serde", + "serde_core", ] [[package]] @@ -4693,12 +5514,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "integer-encoding" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" - [[package]] name = "integer-sqrt" version = "0.1.5" @@ -4731,7 +5546,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.5.8", + "socket2 0.5.10", "widestring", "windows-sys 0.48.0", "winreg", @@ -4790,6 +5605,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -4806,7 +5630,7 @@ dependencies = [ "combine", "jni-sys", "log", - "thiserror", + "thiserror 1.0.69", "walkdir", ] @@ -4827,10 +5651,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -4840,6 +5665,7 @@ version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5c71d8c1a731cc4227c2f698d377e7848ca12c8a48866fc5e6951c43a4db843" dependencies = [ + "jsonrpsee-client-transport", "jsonrpsee-core", "jsonrpsee-proc-macros", "jsonrpsee-server", @@ -4860,13 +5686,13 @@ dependencies = [ "http 1.2.0", "jsonrpsee-core", "pin-project", - "rustls 0.23.20", + "rustls", "rustls-pki-types", "rustls-platform-verifier", "soketto 0.8.1", - "thiserror", + "thiserror 1.0.69", "tokio", - "tokio-rustls 0.26.1", + "tokio-rustls", "tokio-util", "tracing", "url", @@ -4888,11 +5714,11 @@ dependencies = [ "jsonrpsee-types", "parking_lot 0.12.3", "pin-project", - "rand", + "rand 0.8.5", "rustc-hash 2.1.0", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "tracing", @@ -4930,7 +5756,7 @@ dependencies = [ "serde", "serde_json", "soketto 0.8.1", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "tokio-util", @@ -4947,7 +5773,7 @@ dependencies = [ "http 1.2.0", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4965,9 +5791,9 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", "ecdsa", @@ -4986,6 +5812,26 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "keccak-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + +[[package]] +name = "keccak-hash" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e1b8590eb6148af2ea2d75f38e7d29f5ca970d5a4df456b3ef19b8b415d0264" +dependencies = [ + "primitive-types 0.13.1", + "tiny-keccak", +] + [[package]] name = "keystream" version = "1.0.0" @@ -5033,7 +5879,7 @@ checksum = "9baa9eeb6e315942429397e617a190f4fdc696ef1ee0342939d641029cbb4ea7" dependencies = [ "enumflags2", "libc", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -5041,6 +5887,9 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "lazycell" @@ -5050,9 +5899,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.168" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libloading" @@ -5072,16 +5921,15 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libp2p" -version = "0.52.4" +version = "0.54.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94495eb319a85b70a68b85e2389a95bb3555c71c49025b78c691a854a7e6464" +checksum = "bbbe80f9c7e00526cd6b838075b9c171919404a4732cb2fa8ece0a093223bfc4" dependencies = [ "bytes", "either", "futures", "futures-timer", - "getrandom", - "instant", + "getrandom 0.2.14", "libp2p-allow-block-list", "libp2p-connection-limits", "libp2p-core", @@ -5098,20 +5946,19 @@ dependencies = [ "libp2p-swarm", "libp2p-tcp", "libp2p-upnp", - "libp2p-wasm-ext", "libp2p-websocket", "libp2p-yamux", "multiaddr 0.18.2", "pin-project", "rw-stream-sink", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "libp2p-allow-block-list" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55b46558c5c0bf99d3e2a1a38fd54ff5476ca66dd1737b12466a1824dd219311" +checksum = "d1027ccf8d70320ed77e984f273bc8ce952f623762cb9bf2d126df73caef8041" dependencies = [ "libp2p-core", "libp2p-identity", @@ -5121,9 +5968,9 @@ dependencies = [ [[package]] name = "libp2p-connection-limits" -version = "0.2.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f5107ad45cb20b2f6c3628c7b6014b996fcb13a88053f4569c872c6e30abf58" +checksum = "8d003540ee8baef0d254f7b6bfd79bac3ddf774662ca0abf69186d517ef82ad8" dependencies = [ "libp2p-core", "libp2p-identity", @@ -5133,17 +5980,15 @@ dependencies = [ [[package]] name = "libp2p-core" -version = "0.40.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd44289ab25e4c9230d9246c475a22241e301b23e8f4061d3bdef304a1a99713" +checksum = "a61f26c83ed111104cd820fe9bc3aaabbac5f1652a1d213ed6e900b7918a1298" dependencies = [ "either", "fnv", "futures", "futures-timer", - "instant", "libp2p-identity", - "log", "multiaddr 0.18.2", "multihash 0.19.1", "multistream-select", @@ -5151,37 +5996,39 @@ dependencies = [ "parking_lot 0.12.3", "pin-project", "quick-protobuf", - "rand", + "rand 0.8.5", "rw-stream-sink", "smallvec", - "thiserror", - "unsigned-varint 0.7.2", + "thiserror 1.0.69", + "tracing", + "unsigned-varint 0.8.0", "void", + "web-time", ] [[package]] name = "libp2p-dns" -version = "0.40.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6a18db73084b4da2871438f6239fef35190b05023de7656e877c18a00541a3b" +checksum = "97f37f30d5c7275db282ecd86e54f29dd2176bd3ac656f06abf43bedb21eb8bd" dependencies = [ "async-trait", "futures", + "hickory-resolver 0.24.4", "libp2p-core", "libp2p-identity", - "log", "parking_lot 0.12.3", "smallvec", - "trust-dns-resolver", + "tracing", ] [[package]] name = "libp2p-identify" -version = "0.43.1" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a96638a0a176bec0a4bcaebc1afa8cf909b114477209d7456ade52c61cd9cd" +checksum = "1711b004a273be4f30202778856368683bd9a83c4c7dcc8f848847606831a4e3" dependencies = [ - "asynchronous-codec", + "asynchronous-codec 0.7.0", "either", "futures", "futures-bounded", @@ -5189,12 +6036,12 @@ dependencies = [ "libp2p-core", "libp2p-identity", "libp2p-swarm", - "log", "lru 0.12.5", "quick-protobuf", "quick-protobuf-codec", "smallvec", - "thiserror", + "thiserror 1.0.69", + "tracing", "void", ] @@ -5204,133 +6051,135 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "257b5621d159b32282eac446bed6670c39c7dc68a200a992d8f056afa0066f6d" dependencies = [ - "bs58 0.5.1", + "bs58", "ed25519-dalek", "hkdf", "multihash 0.19.1", "quick-protobuf", - "rand", + "rand 0.8.5", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.69", "tracing", "zeroize", ] [[package]] name = "libp2p-kad" -version = "0.44.6" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16ea178dabba6dde6ffc260a8e0452ccdc8f79becf544946692fff9d412fc29d" +checksum = "ced237d0bd84bbebb7c2cad4c073160dacb4fe40534963c32ed6d4c6bb7702a3" dependencies = [ "arrayvec 0.7.4", - "asynchronous-codec", + "asynchronous-codec 0.7.0", "bytes", "either", "fnv", "futures", + "futures-bounded", "futures-timer", - "instant", "libp2p-core", "libp2p-identity", "libp2p-swarm", - "log", "quick-protobuf", "quick-protobuf-codec", - "rand", + "rand 0.8.5", "sha2 0.10.8", "smallvec", - "thiserror", - "uint", - "unsigned-varint 0.7.2", + "thiserror 1.0.69", + "tracing", + "uint 0.9.5", "void", + "web-time", ] [[package]] name = "libp2p-mdns" -version = "0.44.0" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42a2567c305232f5ef54185e9604579a894fd0674819402bb0ac0246da82f52a" +checksum = "14b8546b6644032565eb29046b42744aee1e9f261ed99671b2c93fb140dba417" dependencies = [ "data-encoding", "futures", + "hickory-proto 0.24.4", "if-watch", "libp2p-core", "libp2p-identity", "libp2p-swarm", - "log", - "rand", + "rand 0.8.5", "smallvec", - "socket2 0.5.8", + "socket2 0.5.10", "tokio", - "trust-dns-proto 0.22.0", + "tracing", "void", ] [[package]] name = "libp2p-metrics" -version = "0.13.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239ba7d28f8d0b5d77760dc6619c05c7e88e74ec8fbbe97f856f20a56745e620" +checksum = "77ebafa94a717c8442d8db8d3ae5d1c6a15e30f2d347e0cd31d057ca72e42566" dependencies = [ - "instant", + "futures", "libp2p-core", "libp2p-identify", "libp2p-identity", "libp2p-kad", "libp2p-ping", "libp2p-swarm", - "once_cell", + "pin-project", "prometheus-client", + "web-time", ] [[package]] name = "libp2p-noise" -version = "0.43.2" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2eeec39ad3ad0677551907dd304b2f13f17208ccebe333bef194076cd2e8921" +checksum = "36b137cb1ae86ee39f8e5d6245a296518912014eaa87427d24e6ff58cfc1b28c" dependencies = [ + "asynchronous-codec 0.7.0", "bytes", "curve25519-dalek", "futures", "libp2p-core", "libp2p-identity", - "log", "multiaddr 0.18.2", "multihash 0.19.1", "once_cell", "quick-protobuf", - "rand", + "rand 0.8.5", "sha2 0.10.8", "snow", "static_assertions", - "thiserror", + "thiserror 1.0.69", + "tracing", "x25519-dalek", "zeroize", ] [[package]] name = "libp2p-ping" -version = "0.43.1" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e702d75cd0827dfa15f8fd92d15b9932abe38d10d21f47c50438c71dd1b5dae3" +checksum = "005a34420359223b974ee344457095f027e51346e992d1e0dcd35173f4cdd422" dependencies = [ "either", "futures", "futures-timer", - "instant", "libp2p-core", "libp2p-identity", "libp2p-swarm", - "log", - "rand", + "rand 0.8.5", + "tracing", "void", + "web-time", ] [[package]] name = "libp2p-quic" -version = "0.9.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "130d451d83f21b81eb7b35b360bc7972aeafb15177784adc56528db082e6b927" +checksum = "46352ac5cd040c70e88e7ff8257a2ae2f891a4076abad2c439584a31c15fd24e" dependencies = [ "bytes", "futures", @@ -5339,66 +6188,68 @@ dependencies = [ "libp2p-core", "libp2p-identity", "libp2p-tls", - "log", "parking_lot 0.12.3", - "quinn 0.10.2", - "rand", - "ring 0.16.20", - "rustls 0.21.11", - "socket2 0.5.8", - "thiserror", + "quinn", + "rand 0.8.5", + "ring 0.17.8", + "rustls", + "socket2 0.5.10", + "thiserror 1.0.69", "tokio", + "tracing", ] [[package]] name = "libp2p-request-response" -version = "0.25.3" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e3b4d67870478db72bac87bfc260ee6641d0734e0e3e275798f089c3fecfd4" +checksum = "1356c9e376a94a75ae830c42cdaea3d4fe1290ba409a22c809033d1b7dcab0a6" dependencies = [ "async-trait", "futures", - "instant", + "futures-bounded", + "futures-timer", "libp2p-core", "libp2p-identity", "libp2p-swarm", - "log", - "rand", + "rand 0.8.5", "smallvec", + "tracing", "void", + "web-time", ] [[package]] name = "libp2p-swarm" -version = "0.43.7" +version = "0.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "580189e0074af847df90e75ef54f3f30059aedda37ea5a1659e8b9fca05c0141" +checksum = "d7dd6741793d2c1fb2088f67f82cf07261f25272ebe3c0b0c311e0c6b50e851a" dependencies = [ "either", "fnv", "futures", "futures-timer", - "instant", "libp2p-core", "libp2p-identity", "libp2p-swarm-derive", - "log", + "lru 0.12.5", "multistream-select", "once_cell", - "rand", + "rand 0.8.5", "smallvec", "tokio", + "tracing", "void", + "web-time", ] [[package]] name = "libp2p-swarm-derive" -version = "0.33.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4d5ec2a3df00c7836d7696c136274c9c59705bac69133253696a6c932cd1d74" +checksum = "206e0aa0ebe004d778d79fb0966aa0de996c19894e2c0605ba2f8524dd4443d8" dependencies = [ - "heck 0.4.1", - "proc-macro-warning 0.4.2", + "heck 0.5.0", "proc-macro2", "quote", "syn 2.0.90", @@ -5406,9 +6257,9 @@ dependencies = [ [[package]] name = "libp2p-tcp" -version = "0.40.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b558dd40d1bcd1aaaed9de898e9ec6a436019ecc2420dd0016e712fbb61c5508" +checksum = "ad964f312c59dcfcac840acd8c555de8403e295d39edf96f5240048b5fcaa314" dependencies = [ "futures", "futures-timer", @@ -5416,92 +6267,80 @@ dependencies = [ "libc", "libp2p-core", "libp2p-identity", - "log", - "socket2 0.5.8", + "socket2 0.5.10", "tokio", + "tracing", ] [[package]] name = "libp2p-tls" -version = "0.2.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8218d1d5482b122ccae396bbf38abdcb283ecc96fa54760e1dfd251f0546ac61" +checksum = "47b23dddc2b9c355f73c1e36eb0c3ae86f7dc964a3715f0731cfad352db4d847" dependencies = [ "futures", "futures-rustls", "libp2p-core", "libp2p-identity", "rcgen", - "ring 0.16.20", - "rustls 0.21.11", + "ring 0.17.8", + "rustls", "rustls-webpki 0.101.7", - "thiserror", - "x509-parser 0.15.1", + "thiserror 1.0.69", + "x509-parser 0.16.0", "yasna", ] [[package]] name = "libp2p-upnp" -version = "0.1.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82775a47b34f10f787ad3e2a22e2c1541e6ebef4fe9f28f3ac553921554c94c1" +checksum = "01bf2d1b772bd3abca049214a3304615e6a36fa6ffc742bdd1ba774486200b8f" dependencies = [ "futures", "futures-timer", "igd-next", "libp2p-core", "libp2p-swarm", - "log", "tokio", + "tracing", "void", ] -[[package]] -name = "libp2p-wasm-ext" -version = "0.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e5d8e3a9e07da0ef5b55a9f26c009c8fb3c725d492d8bb4b431715786eea79c" -dependencies = [ - "futures", - "js-sys", - "libp2p-core", - "send_wrapper", - "wasm-bindgen", - "wasm-bindgen-futures", -] - [[package]] name = "libp2p-websocket" -version = "0.42.2" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "004ee9c4a4631435169aee6aad2f62e3984dc031c43b6d29731e8e82a016c538" +checksum = "888b2ff2e5d8dcef97283daab35ad1043d18952b65e05279eecbe02af4c6e347" dependencies = [ "either", "futures", "futures-rustls", "libp2p-core", "libp2p-identity", - "log", "parking_lot 0.12.3", "pin-project-lite", "rw-stream-sink", "soketto 0.8.1", - "thiserror", + "thiserror 1.0.69", + "tracing", "url", "webpki-roots 0.25.4", ] [[package]] name = "libp2p-yamux" -version = "0.44.1" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eedcb62824c4300efb9cfd4e2a6edaf3ca097b9e68b36dabe45a44469fd6a85" +checksum = "788b61c80789dba9760d8c669a5bedb642c8267555c803fabd8396e4ca5c5882" dependencies = [ + "either", "futures", "libp2p-core", - "log", - "thiserror", - "yamux", + "thiserror 1.0.69", + "tracing", + "yamux 0.12.1", + "yamux 0.13.8", ] [[package]] @@ -5510,7 +6349,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.10.0", "libc", ] @@ -5531,18 +6370,18 @@ dependencies = [ [[package]] name = "libsecp256k1" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +checksum = "e79019718125edc905a079a70cfa5f3820bc76139fc91d6f9abc27ea2a887139" dependencies = [ "arrayref", - "base64 0.13.1", + "base64 0.22.1", "digest 0.9.0", "hmac-drbg", "libsecp256k1-core", "libsecp256k1-gen-ecmult", "libsecp256k1-gen-genmult", - "rand", + "rand 0.8.5", "serde", "sha2 0.9.9", "typenum", @@ -5639,6 +6478,12 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + [[package]] name = "lioness" version = "0.1.2" @@ -5651,57 +6496,55 @@ dependencies = [ "keystream", ] +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + [[package]] name = "litep2p" -version = "0.6.2" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f46c51c205264b834ceed95c8b195026e700494bc3991aaba3b4ea9e20626d9" +checksum = "14fb10e63363204b89d91e1292df83322fd9de5d7fa76c3d5c78ddc2f8f3efa9" dependencies = [ "async-trait", - "bs58 0.4.0", + "bs58", "bytes", - "cid 0.10.1", + "cid 0.11.1", "ed25519-dalek", "futures", "futures-timer", - "hex-literal", - "indexmap 2.2.6", + "hickory-resolver 0.25.2", + "indexmap 2.12.0", "libc", - "mockall 0.12.1", + "mockall", "multiaddr 0.17.1", "multihash 0.17.0", "network-interface", - "nohash-hasher", "parking_lot 0.12.3", "pin-project", - "prost 0.12.6", - "prost-build 0.11.9", - "quinn 0.9.4", - "rand", - "rcgen", - "ring 0.16.20", - "rustls 0.20.9", + "prost 0.13.5", + "prost-build", + "rand 0.8.5", "serde", "sha2 0.10.8", "simple-dns", "smallvec", "snow", - "socket2 0.5.8", - "static_assertions", - "str0m", - "thiserror", + "socket2 0.5.10", + "thiserror 2.0.17", "tokio", "tokio-stream", "tokio-tungstenite", "tokio-util", "tracing", - "trust-dns-resolver", - "uint", + "uint 0.10.0", "unsigned-varint 0.8.0", "url", - "webpki", "x25519-dalek", - "x509-parser 0.16.0", + "x509-parser 0.17.0", + "yamux 0.13.8", "yasna", "zeroize", ] @@ -5718,9 +6561,22 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "loom" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] [[package]] name = "lru" @@ -5746,6 +6602,12 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "lz4" version = "1.24.0" @@ -5838,12 +6700,6 @@ dependencies = [ "regex-automata 0.1.10", ] -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - [[package]] name = "matrixmultiply" version = "0.3.8" @@ -5913,21 +6769,10 @@ checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" dependencies = [ "byteorder", "keccak", - "rand_core", + "rand_core 0.6.4", "zeroize", ] -[[package]] -name = "mick-jaeger" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69672161530e8aeca1d1400fbf3f1a1747ff60ea604265a4e906c2442df20532" -dependencies = [ - "futures", - "rand", - "thrift", -] - [[package]] name = "minimal-lexical" version = "0.2.1" @@ -5945,13 +6790,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.11" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -5971,18 +6816,18 @@ dependencies = [ "lioness", "log", "parking_lot 0.12.3", - "rand", - "rand_chacha", + "rand 0.8.5", + "rand_chacha 0.3.1", "rand_distr", "subtle 2.5.0", - "thiserror", + "thiserror 1.0.69", "zeroize", ] [[package]] name = "mmr-gadget" -version = "40.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "45.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "futures", "log", @@ -6000,8 +6845,8 @@ dependencies = [ [[package]] name = "mmr-rpc" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -6015,58 +6860,55 @@ dependencies = [ [[package]] name = "mockall" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c84490118f2ee2d74570d114f3d0493cbf02790df303d2707606c3e14e07c96" -dependencies = [ - "cfg-if", - "downcast", - "fragile", - "lazy_static", - "mockall_derive 0.11.4", - "predicates 2.1.5", - "predicates-tree", -] - -[[package]] -name = "mockall" -version = "0.12.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43766c2b5203b10de348ffe19f7e54564b64f3d6018ff7648d1e2d6d3a0f0a48" +checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2" dependencies = [ "cfg-if", "downcast", "fragile", - "lazy_static", - "mockall_derive 0.12.1", - "predicates 3.1.2", + "mockall_derive", + "predicates", "predicates-tree", ] [[package]] name = "mockall_derive" -version = "0.11.4" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ce75669015c4f47b289fd4d4f56e894e4c96003ffdf3ac51313126f94c6cbb" +checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898" dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.90", ] [[package]] -name = "mockall_derive" -version = "0.12.1" +name = "moka" +version = "0.12.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cbce79ec385a1d4f54baa90a76401eb15d9cab93685f62e7e9f942aa00ae2" +checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926" dependencies = [ - "cfg-if", - "proc-macro2", - "quote", - "syn 2.0.90", + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "loom", + "parking_lot 0.12.3", + "portable-atomic", + "rustc_version 0.4.0", + "smallvec", + "tagptr", + "thiserror 1.0.69", + "uuid", ] +[[package]] +name = "multi-stash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685a9ac4b61f4e728e1d2c6a7844609c16527aeb5e6c865915c08e619c16410f" + [[package]] name = "multiaddr" version = "0.17.1" @@ -6133,23 +6975,6 @@ dependencies = [ "unsigned-varint 0.7.2", ] -[[package]] -name = "multihash" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfd8a792c1694c6da4f68db0a9d707c72bd260994da179e6030a5dcee00bb815" -dependencies = [ - "blake2b_simd", - "blake2s_simd", - "blake3", - "core2", - "digest 0.10.7", - "multihash-derive", - "sha2 0.10.8", - "sha3", - "unsigned-varint 0.7.2", -] - [[package]] name = "multihash" version = "0.19.1" @@ -6227,7 +7052,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bddcd3bf5144b6392de80e04c347cd7fab2508f6df16a85fc496ecd5cec39bc" dependencies = [ - "rand", + "rand 0.8.5", ] [[package]] @@ -6271,7 +7096,7 @@ dependencies = [ "anyhow", "byteorder", "paste", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -6285,7 +7110,7 @@ dependencies = [ "log", "netlink-packet-core", "netlink-sys", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -6304,13 +7129,13 @@ dependencies = [ [[package]] name = "network-interface" -version = "1.1.4" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a43439bf756eed340bdf8feba761e2d50c7d47175d87545cd5cbe4a137c4d1" +checksum = "07709a6d4eba90ab10ec170a0530b3aafc81cb8a2d380e4423ae41fc55fe5745" dependencies = [ "cc", "libc", - "thiserror", + "thiserror 2.0.17", "winapi", ] @@ -6327,13 +7152,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.10.0", "cfg-if", - "cfg_aliases", + "cfg_aliases 0.2.1", "libc", ] @@ -6383,12 +7208,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" -[[package]] -name = "normalize-line-endings" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -6425,6 +7244,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "num-format" version = "0.4.4" @@ -6458,9 +7288,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -6476,27 +7306,6 @@ dependencies = [ "libc", ] -[[package]] -name = "num_enum" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 2.0.90", -] - [[package]] name = "object" version = "0.30.4" @@ -6519,12 +7328,12 @@ dependencies = [ ] [[package]] -name = "oid-registry" -version = "0.6.1" +name = "object" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ - "asn1-rs 0.5.2", + "memchr", ] [[package]] @@ -6536,11 +7345,24 @@ dependencies = [ "asn1-rs 0.6.2", ] +[[package]] +name = "oid-registry" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" +dependencies = [ + "asn1-rs 0.7.1", +] + [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +dependencies = [ + "critical-section", + "portable-atomic", +] [[package]] name = "opaque-debug" @@ -6554,59 +7376,11 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" -[[package]] -name = "openssl" -version = "0.10.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - [[package]] name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-src" -version = "300.3.1+3.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7259953d42a81bf137fbbd73bd30a8e1914d6dce43c2b90ed575783a22608b91" -dependencies = [ - "cc", -] - -[[package]] -name = "openssl-sys" -version = "0.9.103" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" -dependencies = [ - "cc", - "libc", - "openssl-src", - "pkg-config", - "vcpkg", -] +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "option-ext" @@ -6616,9 +7390,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchestra" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f6bbacc8c189a3f2e45e0fd0436e5d97f194db888e721bdbc3973e7dbed4c2" +checksum = "19051f0b0512402f5d52d6776999f55996f01887396278aeeccbbdfbc83eef2d" dependencies = [ "async-trait", "dyn-clonable", @@ -6627,18 +7401,18 @@ dependencies = [ "orchestra-proc-macro", "pin-project", "prioritized-metered-channel", - "thiserror", + "thiserror 1.0.69", "tracing", ] [[package]] name = "orchestra-proc-macro" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7b1d40dd8f367db3c65bec8d3dd47d4a604ee8874480738f93191bddab4e0e0" +checksum = "43dfaf083aef571385fccfdc3a2f8ede8d0a1863160455d4f2b014d8f7d04a3f" dependencies = [ "expander", - "indexmap 2.2.6", + "indexmap 2.12.0", "itertools 0.11.0", "petgraph", "proc-macro-crate 3.1.0", @@ -6647,19 +7421,10 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "ordered-float" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3305af35278dd29f46fcdd139e0b1fbfae2153f0e5928b39b035542dd31e37b7" -dependencies = [ - "num-traits", -] - [[package]] name = "orml-benchmarking" -version = "1.0.0" -source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2409#60b88b84a6abbf8e12a884bf1c3774ff2db1f880" +version = "1.4.0" +source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2503#ab8a16c034cfba502d4aa32be93436e4908d793c" dependencies = [ "frame-benchmarking", "frame-support", @@ -6679,8 +7444,8 @@ dependencies = [ [[package]] name = "orml-tokens" -version = "1.0.0" -source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2409#60b88b84a6abbf8e12a884bf1c3774ff2db1f880" +version = "1.4.0" +source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2503#ab8a16c034cfba502d4aa32be93436e4908d793c" dependencies = [ "frame-support", "frame-system", @@ -6696,8 +7461,8 @@ dependencies = [ [[package]] name = "orml-traits" -version = "1.0.0" -source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2409#60b88b84a6abbf8e12a884bf1c3774ff2db1f880" +version = "1.4.0" +source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2503#ab8a16c034cfba502d4aa32be93436e4908d793c" dependencies = [ "frame-support", "impl-trait-for-tuples", @@ -6716,8 +7481,8 @@ dependencies = [ [[package]] name = "orml-unknown-tokens" -version = "1.0.0" -source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2409#60b88b84a6abbf8e12a884bf1c3774ff2db1f880" +version = "1.4.0" +source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2503#ab8a16c034cfba502d4aa32be93436e4908d793c" dependencies = [ "frame-support", "frame-system", @@ -6731,8 +7496,8 @@ dependencies = [ [[package]] name = "orml-utilities" -version = "1.0.0" -source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2409#60b88b84a6abbf8e12a884bf1c3774ff2db1f880" +version = "1.4.0" +source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2503#ab8a16c034cfba502d4aa32be93436e4908d793c" dependencies = [ "frame-support", "parity-scale-codec", @@ -6746,8 +7511,8 @@ dependencies = [ [[package]] name = "orml-vesting" -version = "1.0.0" -source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2409#60b88b84a6abbf8e12a884bf1c3774ff2db1f880" +version = "1.4.0" +source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2503#ab8a16c034cfba502d4aa32be93436e4908d793c" dependencies = [ "frame-support", "frame-system", @@ -6761,8 +7526,8 @@ dependencies = [ [[package]] name = "orml-xcm" -version = "1.0.0" -source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2409#60b88b84a6abbf8e12a884bf1c3774ff2db1f880" +version = "1.4.0" +source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2503#ab8a16c034cfba502d4aa32be93436e4908d793c" dependencies = [ "frame-support", "frame-system", @@ -6775,8 +7540,8 @@ dependencies = [ [[package]] name = "orml-xcm-support" -version = "1.0.0" -source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2409#60b88b84a6abbf8e12a884bf1c3774ff2db1f880" +version = "1.4.0" +source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2503#ab8a16c034cfba502d4aa32be93436e4908d793c" dependencies = [ "frame-support", "orml-traits", @@ -6789,8 +7554,8 @@ dependencies = [ [[package]] name = "orml-xtokens" -version = "1.0.0" -source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2409#60b88b84a6abbf8e12a884bf1c3774ff2db1f880" +version = "1.4.0" +source = "git+https://github.com/galacticcouncil/open-runtime-module-library?branch=polkadot-stable2503#ab8a16c034cfba502d4aa32be93436e4908d793c" dependencies = [ "frame-support", "frame-system", @@ -6816,8 +7581,8 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "pallet-asset-conversion" -version = "20.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "22.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6834,8 +7599,8 @@ dependencies = [ [[package]] name = "pallet-asset-rate" -version = "17.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "19.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6848,7 +7613,7 @@ dependencies = [ [[package]] name = "pallet-asset-registry" -version = "2.3.6" +version = "2.4.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -6857,7 +7622,7 @@ dependencies = [ "log", "orml-traits", "parity-scale-codec", - "primitive-types", + "primitive-types 0.13.1", "scale-info", "serde", "sp-api", @@ -6871,34 +7636,10 @@ dependencies = [ "test-utils", ] -[[package]] -name = "pallet-asset-registry" -version = "3.3.0" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "hydradx-traits", - "log", - "orml-traits", - "parity-scale-codec", - "primitive-types", - "scale-info", - "serde", - "sp-api", - "sp-arithmetic", - "sp-core", - "sp-runtime", - "sp-std", - "staging-xcm", - "substrate-wasm-builder", -] - [[package]] name = "pallet-asset-tx-payment" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6914,8 +7655,8 @@ dependencies = [ [[package]] name = "pallet-assets" -version = "40.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "42.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6930,8 +7671,8 @@ dependencies = [ [[package]] name = "pallet-aura" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-support", "frame-system", @@ -6946,8 +7687,8 @@ dependencies = [ [[package]] name = "pallet-authority-discovery" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-support", "frame-system", @@ -6961,8 +7702,8 @@ dependencies = [ [[package]] name = "pallet-authorship" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-support", "frame-system", @@ -6974,8 +7715,8 @@ dependencies = [ [[package]] name = "pallet-babe" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6997,8 +7738,8 @@ dependencies = [ [[package]] name = "pallet-bags-list" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "aquamarine", "docify", @@ -7018,8 +7759,8 @@ dependencies = [ [[package]] name = "pallet-balances" -version = "39.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "41.1.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "docify", "frame-benchmarking", @@ -7028,13 +7769,14 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", + "sp-core", "sp-runtime", ] [[package]] name = "pallet-beefy" -version = "39.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "41.1.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-support", "frame-system", @@ -7052,8 +7794,8 @@ dependencies = [ [[package]] name = "pallet-beefy-mmr" -version = "39.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "41.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "array-bytes", "binary-merkle-tree", @@ -7072,35 +7814,13 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-state-machine", -] - -[[package]] -name = "pallet-bonds" -version = "2.2.4" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "hydradx-traits", - "log", - "orml-traits", - "pallet-timestamp", - "parity-scale-codec", - "primitive-types", - "primitives 6.1.0", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", + "sp-state-machine", ] [[package]] name = "pallet-bounties" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7116,15 +7836,16 @@ dependencies = [ [[package]] name = "pallet-broadcast" -version = "1.0.0" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "1.4.0" +source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2503-11-snek#59ae6bfb45c4e37c38c95eead4c9f29e26bc478b" dependencies = [ "frame-support", + "frame-support-procedural", "frame-system", "hydradx-traits", "log", "parity-scale-codec", - "primitives 6.1.0", + "primitives 6.1.2", "scale-info", "serde", "sp-api", @@ -7136,8 +7857,8 @@ dependencies = [ [[package]] name = "pallet-broker" -version = "0.17.2" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.19.2" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bitvec", "frame-benchmarking", @@ -7154,8 +7875,8 @@ dependencies = [ [[package]] name = "pallet-child-bounties" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7170,26 +7891,10 @@ dependencies = [ "sp-runtime", ] -[[package]] -name = "pallet-circuit-breaker" -version = "1.1.28" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" -dependencies = [ - "frame-support", - "frame-system", - "hydradx-traits", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-collator-rewards" -version = "1.0.9" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "1.1.0" +source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2503-11-snek#59ae6bfb45c4e37c38c95eead4c9f29e26bc478b" dependencies = [ "frame-support", "frame-system", @@ -7207,8 +7912,8 @@ dependencies = [ [[package]] name = "pallet-collator-selection" -version = "19.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "21.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7218,7 +7923,7 @@ dependencies = [ "pallet-balances", "pallet-session", "parity-scale-codec", - "rand", + "rand 0.8.5", "scale-info", "sp-runtime", "sp-staking", @@ -7226,9 +7931,10 @@ dependencies = [ [[package]] name = "pallet-collective" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ + "docify", "frame-benchmarking", "frame-support", "frame-system", @@ -7242,8 +7948,8 @@ dependencies = [ [[package]] name = "pallet-conviction-voting" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "assert_matches", "frame-benchmarking", @@ -7258,8 +7964,8 @@ dependencies = [ [[package]] name = "pallet-currencies" -version = "3.0.0" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "3.2.0" +source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2503-11-snek#59ae6bfb45c4e37c38c95eead4c9f29e26bc478b" dependencies = [ "frame-support", "frame-system", @@ -7267,6 +7973,7 @@ dependencies = [ "orml-traits", "orml-utilities", "parity-scale-codec", + "primitives 6.1.2", "scale-info", "serde", "sp-core", @@ -7277,8 +7984,8 @@ dependencies = [ [[package]] name = "pallet-delegated-staking" -version = "5.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "7.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-support", "frame-system", @@ -7292,8 +7999,8 @@ dependencies = [ [[package]] name = "pallet-democracy" -version = "4.3.2" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "4.3.4" +source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2503-11-snek#59ae6bfb45c4e37c38c95eead4c9f29e26bc478b" dependencies = [ "frame-benchmarking", "frame-support", @@ -7310,8 +8017,8 @@ dependencies = [ [[package]] name = "pallet-democracy" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7327,8 +8034,8 @@ dependencies = [ [[package]] name = "pallet-duster" -version = "3.2.7" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "3.3.1" +source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2503-11-snek#59ae6bfb45c4e37c38c95eead4c9f29e26bc478b" dependencies = [ "frame-benchmarking", "frame-support", @@ -7338,32 +8045,15 @@ dependencies = [ "orml-traits", "parity-scale-codec", "scale-info", - "serde", "sp-runtime", "sp-std", "substrate-wasm-builder", ] -[[package]] -name = "pallet-dynamic-fees" -version = "1.0.6" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" -dependencies = [ - "frame-support", - "frame-system", - "hydra-dx-math", - "orml-traits", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-election-provider-multi-phase" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.2.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -7372,20 +8062,20 @@ dependencies = [ "log", "pallet-election-provider-support-benchmarking", "parity-scale-codec", - "rand", + "rand 0.8.5", "scale-info", "sp-arithmetic", "sp-core", "sp-io", "sp-npos-elections", "sp-runtime", - "strum 0.26.2", + "strum 0.26.3", ] [[package]] name = "pallet-election-provider-support-benchmarking" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -7397,8 +8087,8 @@ dependencies = [ [[package]] name = "pallet-elections-phragmen" -version = "39.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "41.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7415,52 +8105,33 @@ dependencies = [ [[package]] name = "pallet-ema-oracle" -version = "1.3.4" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "1.4.0" dependencies = [ + "basilisk-math", + "basilisk-traits", "frame-benchmarking", "frame-support", "frame-system", "hydra-dx-math", - "hydradx-traits", "log", "parity-scale-codec", + "pretty_assertions", + "proptest", + "rug", "scale-info", "serde", "sp-arithmetic", "sp-core", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "pallet-evm" -version = "6.0.0-dev" -source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-stable2409#48028bbad21d66b2b9d467a5343a8707e00c8b6c" -dependencies = [ - "cumulus-primitives-storage-weight-reclaim", - "environmental", - "evm", - "fp-account", - "fp-evm", - "frame-benchmarking", - "frame-support", - "frame-system", - "hash-db", - "hex-literal", - "impl-trait-for-tuples", - "log", - "parity-scale-codec", - "scale-info", - "sp-core", "sp-io", "sp-runtime", + "sp-std", + "test-utils", ] [[package]] name = "pallet-fast-unstake" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "docify", "frame-benchmarking", @@ -7477,8 +8148,8 @@ dependencies = [ [[package]] name = "pallet-grandpa" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7499,8 +8170,8 @@ dependencies = [ [[package]] name = "pallet-identity" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "enumflags2", "frame-benchmarking", @@ -7515,8 +8186,8 @@ dependencies = [ [[package]] name = "pallet-im-online" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.1.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7534,8 +8205,8 @@ dependencies = [ [[package]] name = "pallet-indices" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7544,15 +8215,14 @@ dependencies = [ "scale-info", "sp-core", "sp-io", - "sp-keyring", "sp-runtime", ] [[package]] name = "pallet-lbp" -version = "4.10.0" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "4.11.0" dependencies = [ + "basilisk-traits", "frame-benchmarking", "frame-support", "frame-system", @@ -7562,19 +8232,23 @@ dependencies = [ "orml-traits", "pallet-broadcast", "parity-scale-codec", - "primitive-types", + "primitive-types 0.13.1", + "proptest", + "rug", "scale-info", "serde", "sp-core", + "sp-io", "sp-runtime", "sp-std", "substrate-wasm-builder", + "test-utils", ] [[package]] name = "pallet-liquidity-mining" -version = "4.4.5" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "4.4.8" +source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2503-11-snek#59ae6bfb45c4e37c38c95eead4c9f29e26bc478b" dependencies = [ "frame-support", "frame-system", @@ -7590,7 +8264,7 @@ dependencies = [ [[package]] name = "pallet-marketplace" -version = "5.0.20" +version = "5.1.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -7600,7 +8274,7 @@ dependencies = [ "pallet-uniques", "parity-scale-codec", "pretty_assertions", - "primitives 6.6.5", + "primitives 6.7.0", "scale-info", "serde", "sp-arithmetic", @@ -7612,8 +8286,8 @@ dependencies = [ [[package]] name = "pallet-membership" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7628,8 +8302,8 @@ dependencies = [ [[package]] name = "pallet-message-queue" -version = "41.0.2" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "43.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "environmental", "frame-benchmarking", @@ -7646,41 +8320,69 @@ dependencies = [ ] [[package]] -name = "pallet-mmr" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +name = "pallet-meta-tx" +version = "0.2.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ + "docify", "frame-benchmarking", "frame-support", "frame-system", - "log", "parity-scale-codec", "scale-info", + "serde", "sp-core", "sp-io", - "sp-mmr-primitives", "sp-runtime", + "sp-std", ] [[package]] -name = "pallet-multisig" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +name = "pallet-migrations" +version = "10.1.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ + "docify", "frame-benchmarking", "frame-support", "frame-system", + "impl-trait-for-tuples", "log", "parity-scale-codec", + "polkadot-sdk-frame", "scale-info", + "sp-core", "sp-io", "sp-runtime", ] +[[package]] +name = "pallet-mmr" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" +dependencies = [ + "log", + "parity-scale-codec", + "polkadot-sdk-frame", + "scale-info", + "sp-mmr-primitives", +] + +[[package]] +name = "pallet-multisig" +version = "40.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" +dependencies = [ + "log", + "parity-scale-codec", + "polkadot-sdk-frame", + "scale-info", +] + [[package]] name = "pallet-nft" -version = "7.1.5" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "7.1.6" +source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2503-11-snek#59ae6bfb45c4e37c38c95eead4c9f29e26bc478b" dependencies = [ "frame-benchmarking", "frame-support", @@ -7698,23 +8400,18 @@ dependencies = [ [[package]] name = "pallet-nis" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", "parity-scale-codec", + "polkadot-sdk-frame", "scale-info", - "sp-arithmetic", - "sp-core", - "sp-runtime", ] [[package]] name = "pallet-nomination-pools" -version = "35.0.2" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "38.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-support", "frame-system", @@ -7731,8 +8428,8 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-benchmarking" -version = "36.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "38.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -7741,7 +8438,7 @@ dependencies = [ "pallet-bags-list", "pallet-delegated-staking", "pallet-nomination-pools", - "pallet-staking 38.0.0", + "pallet-staking 40.1.1", "parity-scale-codec", "scale-info", "sp-runtime", @@ -7751,8 +8448,8 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-runtime-api" -version = "33.0.2" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "36.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "pallet-nomination-pools", "parity-scale-codec", @@ -7761,13 +8458,12 @@ dependencies = [ [[package]] name = "pallet-offences" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-support", "frame-system", "log", - "pallet-balances", "parity-scale-codec", "scale-info", "serde", @@ -7777,8 +8473,8 @@ dependencies = [ [[package]] name = "pallet-offences-benchmarking" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -7791,7 +8487,7 @@ dependencies = [ "pallet-im-online", "pallet-offences", "pallet-session", - "pallet-staking 38.0.0", + "pallet-staking 40.1.1", "parity-scale-codec", "scale-info", "sp-runtime", @@ -7799,93 +8495,70 @@ dependencies = [ ] [[package]] -name = "pallet-omnipool" -version = "4.5.0" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +name = "pallet-parameters" +version = "0.11.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "bitflags 1.3.2", + "docify", "frame-benchmarking", "frame-support", "frame-system", - "hydra-dx-math", - "hydradx-traits", - "impl-trait-for-tuples", - "log", - "orml-traits", - "pallet-balances", - "pallet-broadcast", "parity-scale-codec", - "primitive-types", + "paste", "scale-info", + "serde", "sp-core", - "sp-io", "sp-runtime", - "sp-std", ] [[package]] -name = "pallet-omnipool-liquidity-mining" -version = "2.6.1" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +name = "pallet-preimage" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", - "hydra-dx-math", - "hydradx-traits", "log", - "orml-traits", - "pallet-balances", - "pallet-ema-oracle", - "pallet-liquidity-mining", - "pallet-omnipool", - "pallet-stableswap", "parity-scale-codec", - "primitive-types", - "primitives 6.1.0", "scale-info", "sp-core", "sp-io", "sp-runtime", - "sp-std", ] [[package]] -name = "pallet-parameters" -version = "0.9.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +name = "pallet-proxy" +version = "40.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "docify", - "frame-benchmarking", - "frame-support", - "frame-system", "parity-scale-codec", - "paste", + "polkadot-sdk-frame", "scale-info", - "serde", - "sp-core", - "sp-runtime", ] [[package]] -name = "pallet-preimage" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +name = "pallet-ranked-collective" +version = "40.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "impl-trait-for-tuples", "log", "parity-scale-codec", "scale-info", + "sp-arithmetic", "sp-core", "sp-io", "sp-runtime", ] [[package]] -name = "pallet-proxy" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +name = "pallet-recovery" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7897,92 +8570,126 @@ dependencies = [ ] [[package]] -name = "pallet-ranked-collective" -version = "38.2.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +name = "pallet-referenda" +version = "40.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ + "assert_matches", "frame-benchmarking", "frame-support", "frame-system", - "impl-trait-for-tuples", "log", "parity-scale-codec", "scale-info", + "serde", "sp-arithmetic", - "sp-core", "sp-io", "sp-runtime", ] [[package]] -name = "pallet-recovery" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +name = "pallet-relaychain-info" +version = "0.3.6" +source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2503-11-snek#59ae6bfb45c4e37c38c95eead4c9f29e26bc478b" dependencies = [ - "frame-benchmarking", + "cumulus-pallet-parachain-system", + "cumulus-primitives-core", "frame-support", "frame-system", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", + "sp-api", + "sp-std", ] [[package]] -name = "pallet-referenda" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +name = "pallet-revive" +version = "0.6.2" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "assert_matches", + "alloy-core", + "derive_more 0.99.17", + "environmental", + "ethabi-decode", + "ethereum-types", "frame-benchmarking", "frame-support", "frame-system", + "hex-literal", + "humantime-serde", + "impl-trait-for-tuples", "log", + "num-bigint", + "num-integer", + "num-traits", + "pallet-revive-fixtures", + "pallet-revive-proc-macro", + "pallet-revive-uapi", + "pallet-transaction-payment", "parity-scale-codec", + "paste", + "polkavm 0.21.0", + "polkavm-common 0.21.0", + "rand 0.8.5", + "rand_pcg", + "ripemd", + "rlp 0.6.1", "scale-info", "serde", + "sp-api", "sp-arithmetic", + "sp-consensus-aura", + "sp-consensus-babe", + "sp-consensus-slots", + "sp-core", "sp-io", "sp-runtime", + "staging-xcm", + "staging-xcm-builder", + "substrate-bn", + "subxt-signer", ] [[package]] -name = "pallet-referrals" -version = "1.2.8" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +name = "pallet-revive-fixtures" +version = "0.3.2" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "frame-support", - "frame-system", - "hex-literal", - "hydra-dx-math", - "hydradx-traits", - "orml-traits", - "parity-scale-codec", - "scale-info", + "anyhow", + "cargo_metadata", + "pallet-revive-uapi", + "polkavm-linker 0.21.0", "sp-core", - "sp-runtime", - "sp-std", + "sp-io", + "toml 0.8.12", ] [[package]] -name = "pallet-relaychain-info" -version = "0.3.5" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +name = "pallet-revive-proc-macro" +version = "0.3.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "cumulus-pallet-parachain-system", - "cumulus-primitives-core", - "frame-support", - "frame-system", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "pallet-revive-uapi" +version = "0.4.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" +dependencies = [ + "bitflags 1.3.2", + "pallet-revive-proc-macro", "parity-scale-codec", + "polkavm-derive 0.21.0", "scale-info", - "sp-api", - "sp-std", ] [[package]] name = "pallet-root-testing" -version = "14.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "16.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-support", "frame-system", @@ -7995,29 +8702,37 @@ dependencies = [ [[package]] name = "pallet-route-executor" -version = "2.7.0" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "2.8.0" dependencies = [ + "basilisk-adapters", + "basilisk-math", + "basilisk-traits", + "frame-benchmarking", "frame-support", "frame-system", "hydra-dx-math", "hydradx-traits", + "orml-tokens", "orml-traits", "pallet-balances", "pallet-broadcast", + "pallet-currencies", "parity-scale-codec", - "primitives 6.1.0", + "pretty_assertions", + "primitives 6.7.0", "scale-info", "serde", "sp-core", + "sp-io", "sp-runtime", "sp-std", + "test-utils", ] [[package]] name = "pallet-scheduler" -version = "39.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "41.2.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "docify", "frame-benchmarking", @@ -8033,8 +8748,8 @@ dependencies = [ [[package]] name = "pallet-session" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-support", "frame-system", @@ -8054,62 +8769,41 @@ dependencies = [ [[package]] name = "pallet-session-benchmarking" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "pallet-session", - "pallet-staking 38.0.0", + "pallet-staking 40.1.1", "parity-scale-codec", - "rand", + "rand 0.8.5", "sp-runtime", "sp-session", ] [[package]] name = "pallet-society" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "log", "parity-scale-codec", - "rand_chacha", + "rand_chacha 0.3.1", "scale-info", "sp-arithmetic", "sp-io", "sp-runtime", ] -[[package]] -name = "pallet-stableswap" -version = "4.2.0" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" -dependencies = [ - "bitflags 1.3.2", - "frame-support", - "frame-system", - "hydra-dx-math", - "hydradx-traits", - "orml-traits", - "pallet-broadcast", - "parity-scale-codec", - "scale-info", - "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-staking" -version = "4.1.0" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "4.1.5" +source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2503-11-snek#59ae6bfb45c4e37c38c95eead4c9f29e26bc478b" dependencies = [ "frame-benchmarking", "frame-support", @@ -8118,7 +8812,7 @@ dependencies = [ "log", "orml-traits", "pallet-conviction-voting", - "pallet-democracy 4.3.2", + "pallet-democracy 4.3.4", "pallet-referenda", "parity-scale-codec", "scale-info", @@ -8131,8 +8825,8 @@ dependencies = [ [[package]] name = "pallet-staking" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.1.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -8142,7 +8836,7 @@ dependencies = [ "pallet-authorship", "pallet-session", "parity-scale-codec", - "rand_chacha", + "rand_chacha 0.3.1", "scale-info", "serde", "sp-application-crypto", @@ -8153,8 +8847,8 @@ dependencies = [ [[package]] name = "pallet-staking-reward-fn" -version = "22.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "22.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "log", "sp-arithmetic", @@ -8162,8 +8856,8 @@ dependencies = [ [[package]] name = "pallet-staking-runtime-api" -version = "24.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "26.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "sp-api", @@ -8172,8 +8866,8 @@ dependencies = [ [[package]] name = "pallet-state-trie-migration" -version = "40.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "45.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -8188,8 +8882,8 @@ dependencies = [ [[package]] name = "pallet-sudo" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "docify", "frame-benchmarking", @@ -8203,8 +8897,8 @@ dependencies = [ [[package]] name = "pallet-timestamp" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "docify", "frame-benchmarking", @@ -8222,8 +8916,8 @@ dependencies = [ [[package]] name = "pallet-tips" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -8240,31 +8934,36 @@ dependencies = [ [[package]] name = "pallet-transaction-multi-payment" -version = "10.1.4" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "11.1.0" dependencies = [ + "basilisk-math", + "basilisk-traits", "frame-support", "frame-system", "hydra-dx-math", "hydradx-traits", + "orml-tokens", "orml-traits", - "pallet-evm", + "pallet-balances", + "pallet-currencies", "pallet-transaction-payment", "pallet-utility", "pallet-xyk", "parity-scale-codec", - "primitives 6.1.0", + "primitives 6.7.0", "scale-info", "sp-api", "sp-core", + "sp-io", "sp-runtime", "sp-std", + "test-utils", ] [[package]] name = "pallet-transaction-pause" -version = "1.1.0" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "1.1.1" +source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2503-11-snek#59ae6bfb45c4e37c38c95eead4c9f29e26bc478b" dependencies = [ "frame-benchmarking", "frame-support", @@ -8278,9 +8977,10 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" -version = "38.0.2" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "parity-scale-codec", @@ -8293,8 +8993,8 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" -version = "41.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "43.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "jsonrpsee", "pallet-transaction-payment-rpc-runtime-api", @@ -8309,8 +9009,8 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -8321,14 +9021,15 @@ dependencies = [ [[package]] name = "pallet-treasury" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "docify", "frame-benchmarking", "frame-support", "frame-system", "impl-trait-for-tuples", + "log", "pallet-balances", "parity-scale-codec", "scale-info", @@ -8339,8 +9040,8 @@ dependencies = [ [[package]] name = "pallet-uniques" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -8353,8 +9054,8 @@ dependencies = [ [[package]] name = "pallet-utility" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", @@ -8368,44 +9069,58 @@ dependencies = [ ] [[package]] -name = "pallet-vesting" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +name = "pallet-verify-signature" +version = "0.3.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log", "parity-scale-codec", "scale-info", + "sp-core", + "sp-io", "sp-runtime", + "sp-weights", ] [[package]] -name = "pallet-whitelist" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +name = "pallet-vesting" +version = "40.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "log", "parity-scale-codec", "scale-info", - "sp-api", "sp-runtime", ] +[[package]] +name = "pallet-whitelist" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" +dependencies = [ + "parity-scale-codec", + "polkadot-sdk-frame", + "scale-info", +] + [[package]] name = "pallet-xcm" -version = "17.0.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "19.2.2" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bounded-collections", "frame-benchmarking", "frame-support", "frame-system", - "log", + "hex-literal", "pallet-balances", + "pallet-revive", + "pallet-timestamp", "parity-scale-codec", "scale-info", "serde", @@ -8421,13 +9136,12 @@ dependencies = [ [[package]] name = "pallet-xcm-benchmarks" -version = "17.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "20.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log", "parity-scale-codec", "scale-info", "sp-io", @@ -8439,9 +9153,10 @@ dependencies = [ [[package]] name = "pallet-xyk" -version = "6.7.0" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "6.8.0" dependencies = [ + "basilisk-math", + "basilisk-traits", "frame-benchmarking", "frame-support", "frame-system", @@ -8450,12 +9165,16 @@ dependencies = [ "log", "orml-tokens", "orml-traits", + "pallet-asset-registry", "pallet-broadcast", "parity-scale-codec", - "primitive-types", + "primitive-types 0.13.1", + "proptest", "scale-info", "serde", + "sp-api", "sp-core", + "sp-io", "sp-runtime", "sp-std", "substrate-wasm-builder", @@ -8463,7 +9182,7 @@ dependencies = [ [[package]] name = "pallet-xyk-liquidity-mining" -version = "1.1.13" +version = "1.2.0" dependencies = [ "frame-support", "frame-system", @@ -8478,7 +9197,7 @@ dependencies = [ "pallet-xyk", "parity-scale-codec", "pretty_assertions", - "primitives 6.6.5", + "primitives 6.7.0", "scale-info", "sp-arithmetic", "sp-core", @@ -8489,7 +9208,7 @@ dependencies = [ [[package]] name = "pallet-xyk-liquidity-mining-benchmarking" -version = "1.0.19" +version = "1.1.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -8497,7 +9216,7 @@ dependencies = [ "hydradx-traits", "orml-tokens", "orml-traits", - "pallet-asset-registry 2.3.6", + "pallet-asset-registry", "pallet-balances", "pallet-broadcast", "pallet-duster", @@ -8507,7 +9226,7 @@ dependencies = [ "pallet-xyk", "pallet-xyk-liquidity-mining", "parity-scale-codec", - "primitives 6.6.5", + "primitives 6.7.0", "scale-info", "sp-arithmetic", "sp-core", @@ -8518,8 +9237,8 @@ dependencies = [ [[package]] name = "parachains-common" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "21.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "cumulus-primitives-core", "cumulus-primitives-utility", @@ -8543,7 +9262,6 @@ dependencies = [ "staging-parachain-info", "staging-xcm", "staging-xcm-executor", - "substrate-wasm-builder", ] [[package]] @@ -8553,8 +9271,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" dependencies = [ "bitcoin_hashes 0.13.0", - "rand", - "rand_core", + "rand 0.8.5", + "rand_core 0.6.4", "serde", "unicode-normalization", ] @@ -8574,37 +9292,39 @@ dependencies = [ "lz4", "memmap2 0.5.10", "parking_lot 0.12.3", - "rand", - "siphasher", + "rand 0.8.5", + "siphasher 0.3.11", "snap", "winapi", ] [[package]] name = "parity-scale-codec" -version = "3.6.12" +version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" dependencies = [ "arrayvec 0.7.4", "bitvec", "byte-slice-cast", "bytes", + "const_format", "impl-trait-for-tuples", "parity-scale-codec-derive", + "rustversion", "serde", ] [[package]] name = "parity-scale-codec-derive" -version = "3.6.12" +version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.90", ] [[package]] @@ -8680,7 +9400,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" dependencies = [ "base64ct", - "rand_core", + "rand_core 0.6.4", "subtle 2.5.0", ] @@ -8697,6 +9417,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest 0.10.7", + "hmac 0.12.1", "password-hash", ] @@ -8708,11 +9429,12 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "pem" -version = "1.1.1" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ - "base64 0.13.1", + "base64 0.22.1", + "serde_core", ] [[package]] @@ -8728,7 +9450,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" dependencies = [ "memchr", - "thiserror", + "thiserror 1.0.69", "ucd-trie", ] @@ -8773,23 +9495,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.2.6", + "indexmap 2.12.0", ] [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", @@ -8843,46 +9565,42 @@ checksum = "989d43012e2ca1c4a02507c67282691a0a3207f9dc67cec596b43fe925b3d325" [[package]] name = "polkadot-approval-distribution" -version = "18.2.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "bitvec", "futures", "futures-timer", "itertools 0.11.0", - "polkadot-node-jaeger", "polkadot-node-metrics", "polkadot-node-network-protocol", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand", + "rand 0.8.5", "tracing-gum", ] [[package]] name = "polkadot-availability-bitfield-distribution" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "always-assert", "futures", "futures-timer", "polkadot-node-network-protocol", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand", + "rand 0.8.5", "tracing-gum", ] [[package]] name = "polkadot-availability-distribution" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "derive_more 0.99.17", "fatality", "futures", "parity-scale-codec", @@ -8892,19 +9610,19 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand", + "rand 0.8.5", "sc-network", "schnellru", "sp-core", "sp-keystore", - "thiserror", + "thiserror 1.0.69", "tracing-gum", ] [[package]] name = "polkadot-availability-recovery" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "fatality", @@ -8916,19 +9634,19 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand", + "rand 0.8.5", "sc-network", "schnellru", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing-gum", ] [[package]] name = "polkadot-ckb-merkle-mountain-range" -version = "0.7.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b44320e5f7ce2c18227537a3032ae5b2c476a7e8eddba45333e1011fc31b92" +checksum = "221c71b432b38e494a0fdedb5f720e4cb974edf03a0af09e5b2238dbac7e6947" dependencies = [ "cfg-if", "itertools 0.10.5", @@ -8936,10 +9654,9 @@ dependencies = [ [[package]] name = "polkadot-cli" -version = "19.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "24.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "cfg-if", "clap", "frame-benchmarking-cli", "futures", @@ -8948,24 +9665,21 @@ dependencies = [ "polkadot-node-primitives", "polkadot-service", "sc-cli", - "sc-executor", "sc-service", "sc-storage-monitor", "sc-sysinfo", "sc-tracing", "sp-core", - "sp-io", "sp-keyring", - "sp-maybe-compressed-blob", "sp-runtime", "substrate-build-script-utils", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "polkadot-collator-protocol" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bitvec", "fatality", @@ -8980,15 +9694,15 @@ dependencies = [ "sp-core", "sp-keystore", "sp-runtime", - "thiserror", + "thiserror 1.0.69", "tokio-util", "tracing-gum", ] [[package]] name = "polkadot-core-primitives" -version = "15.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "17.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "scale-info", @@ -8998,33 +9712,30 @@ dependencies = [ [[package]] name = "polkadot-dispute-distribution" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "derive_more 0.99.17", "fatality", "futures", "futures-timer", - "indexmap 2.2.6", + "indexmap 2.12.0", "parity-scale-codec", - "polkadot-erasure-coding", "polkadot-node-network-protocol", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", "sc-network", - "schnellru", "sp-application-crypto", "sp-keystore", - "thiserror", + "thiserror 1.0.69", "tracing-gum", ] [[package]] name = "polkadot-erasure-coding" -version = "16.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "19.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "polkadot-node-primitives", @@ -9032,13 +9743,13 @@ dependencies = [ "reed-solomon-novelpoly", "sp-core", "sp-trie", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "polkadot-gossip-support" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "futures", "futures-timer", @@ -9046,21 +9757,20 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand", - "rand_chacha", + "rand 0.8.5", + "rand_chacha 0.3.1", "sc-network", - "sc-network-common", "sp-application-crypto", "sp-core", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", "sp-keystore", "tracing-gum", ] [[package]] name = "polkadot-network-bridge" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "always-assert", "async-trait", @@ -9076,14 +9786,14 @@ dependencies = [ "polkadot-primitives", "sc-network", "sp-consensus", - "thiserror", + "thiserror 1.0.69", "tracing-gum", ] [[package]] name = "polkadot-node-collation-generation" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "futures", "parity-scale-codec", @@ -9092,34 +9802,33 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", + "schnellru", "sp-core", - "sp-maybe-compressed-blob", - "thiserror", + "thiserror 1.0.69", "tracing-gum", ] [[package]] name = "polkadot-node-core-approval-voting" -version = "18.2.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ + "async-trait", "bitvec", "derive_more 0.99.17", "futures", "futures-timer", "itertools 0.11.0", - "kvdb", "merlin", "parity-scale-codec", - "polkadot-node-jaeger", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-overseer", "polkadot-primitives", - "rand", - "rand_chacha", - "rand_core", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_core 0.6.4", "sc-keystore", "schnellru", "schnorrkel 0.11.4", @@ -9127,36 +9836,57 @@ dependencies = [ "sp-consensus", "sp-consensus-slots", "sp-runtime", - "thiserror", + "thiserror 1.0.69", + "tracing-gum", +] + +[[package]] +name = "polkadot-node-core-approval-voting-parallel" +version = "0.6.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" +dependencies = [ + "async-trait", + "futures", + "itertools 0.11.0", + "polkadot-approval-distribution", + "polkadot-node-core-approval-voting", + "polkadot-node-metrics", + "polkadot-node-network-protocol", + "polkadot-node-primitives", + "polkadot-node-subsystem", + "polkadot-node-subsystem-util", + "polkadot-overseer", + "polkadot-primitives", + "rand 0.8.5", + "rand_core 0.6.4", + "sc-keystore", + "sp-consensus", "tracing-gum", ] [[package]] name = "polkadot-node-core-av-store" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bitvec", "futures", "futures-timer", - "kvdb", "parity-scale-codec", "polkadot-erasure-coding", - "polkadot-node-jaeger", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-util", - "polkadot-overseer", "polkadot-primitives", "sp-consensus", - "thiserror", + "thiserror 1.0.69", "tracing-gum", ] [[package]] name = "polkadot-node-core-backing" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bitvec", "fatality", @@ -9165,33 +9895,34 @@ dependencies = [ "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-util", + "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-statement-table", "schnellru", "sp-keystore", - "thiserror", + "thiserror 1.0.69", "tracing-gum", ] [[package]] name = "polkadot-node-core-bitfield-signing" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "futures", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", "sp-keystore", - "thiserror", + "thiserror 1.0.69", "tracing-gum", "wasm-timer", ] [[package]] name = "polkadot-node-core-candidate-validation" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "futures", @@ -9212,8 +9943,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-api" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "futures", "polkadot-node-metrics", @@ -9226,29 +9957,27 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-selection" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "futures", "futures-timer", - "kvdb", "parity-scale-codec", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "thiserror", + "thiserror 1.0.69", "tracing-gum", ] [[package]] name = "polkadot-node-core-dispute-coordinator" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "fatality", "futures", - "kvdb", "parity-scale-codec", "polkadot-node-primitives", "polkadot-node-subsystem", @@ -9256,14 +9985,14 @@ dependencies = [ "polkadot-primitives", "sc-keystore", "schnellru", - "thiserror", + "thiserror 1.0.69", "tracing-gum", ] [[package]] name = "polkadot-node-core-parachains-inherent" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "futures", @@ -9273,28 +10002,28 @@ dependencies = [ "polkadot-primitives", "sp-blockchain", "sp-inherents", - "thiserror", + "thiserror 1.0.69", "tracing-gum", ] [[package]] name = "polkadot-node-core-prospective-parachains" -version = "17.0.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "22.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "fatality", "futures", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "thiserror", + "thiserror 1.0.69", "tracing-gum", ] [[package]] name = "polkadot-node-core-provisioner" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bitvec", "fatality", @@ -9304,66 +10033,61 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "schnellru", - "thiserror", + "thiserror 1.0.69", "tracing-gum", ] [[package]] name = "polkadot-node-core-pvf" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "always-assert", "array-bytes", - "blake3", - "cfg-if", "futures", "futures-timer", "parity-scale-codec", "pin-project", - "polkadot-core-primitives", "polkadot-node-core-pvf-common", "polkadot-node-metrics", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-parachain-primitives", "polkadot-primitives", - "rand", + "rand 0.8.5", + "sc-tracing", "slotmap", "sp-core", + "strum 0.26.3", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing-gum", ] [[package]] name = "polkadot-node-core-pvf-checker" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "futures", - "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-util", - "polkadot-overseer", "polkadot-primitives", "sp-keystore", - "thiserror", "tracing-gum", ] [[package]] name = "polkadot-node-core-pvf-common" -version = "16.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "19.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "cpu-time", "futures", "landlock", "libc", - "nix 0.28.0", + "nix 0.29.0", "parity-scale-codec", "polkadot-parachain-primitives", "polkadot-primitives", @@ -9372,18 +10096,18 @@ dependencies = [ "sc-executor-wasmtime", "seccompiler", "sp-core", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", "sp-externalities", "sp-io", "sp-tracing", - "thiserror", + "thiserror 1.0.69", "tracing-gum", ] [[package]] name = "polkadot-node-core-runtime-api" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "futures", "polkadot-node-metrics", @@ -9395,34 +10119,14 @@ dependencies = [ "tracing-gum", ] -[[package]] -name = "polkadot-node-jaeger" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" -dependencies = [ - "lazy_static", - "log", - "mick-jaeger", - "parity-scale-codec", - "parking_lot 0.12.3", - "polkadot-node-primitives", - "polkadot-primitives", - "sc-network", - "sc-network-types", - "sp-core", - "thiserror", - "tokio", -] - [[package]] name = "polkadot-node-metrics" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "bs58 0.5.1", + "bs58", "futures", "futures-timer", - "log", "parity-scale-codec", "polkadot-primitives", "prioritized-metered-channel", @@ -9430,13 +10134,12 @@ dependencies = [ "sc-service", "sc-tracing", "substrate-prometheus-endpoint", - "tracing-gum", ] [[package]] name = "polkadot-node-network-protocol" -version = "18.2.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-channel 1.9.0", "async-trait", @@ -9446,23 +10149,22 @@ dependencies = [ "futures", "hex", "parity-scale-codec", - "polkadot-node-jaeger", "polkadot-node-primitives", "polkadot-primitives", - "rand", + "rand 0.8.5", "sc-authority-discovery", "sc-network", "sc-network-types", "sp-runtime", - "strum 0.26.2", - "thiserror", + "strum 0.26.3", + "thiserror 1.0.69", "tracing-gum", ] [[package]] name = "polkadot-node-primitives" -version = "16.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "19.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bitvec", "bounded-vec", @@ -9477,36 +10179,31 @@ dependencies = [ "sp-application-crypto", "sp-consensus-babe", "sp-consensus-slots", - "sp-core", "sp-keystore", "sp-maybe-compressed-blob", - "sp-runtime", - "thiserror", + "thiserror 1.0.69", "zstd 0.12.4", ] [[package]] name = "polkadot-node-subsystem" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "polkadot-node-jaeger", "polkadot-node-subsystem-types", "polkadot-overseer", ] [[package]] name = "polkadot-node-subsystem-types" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", - "bitvec", "derive_more 0.99.17", "fatality", "futures", "orchestra", - "polkadot-node-jaeger", "polkadot-node-network-protocol", "polkadot-node-primitives", "polkadot-primitives", @@ -9522,27 +10219,22 @@ dependencies = [ "sp-consensus-babe", "sp-runtime", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "polkadot-node-subsystem-util" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "async-trait", - "derive_more 0.99.17", "fatality", "futures", - "futures-channel", "itertools 0.11.0", "kvdb", "parity-db", "parity-scale-codec", "parking_lot 0.12.3", - "pin-project", "polkadot-erasure-coding", - "polkadot-node-jaeger", "polkadot-node-metrics", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -9551,33 +10243,32 @@ dependencies = [ "polkadot-overseer", "polkadot-primitives", "prioritized-metered-channel", - "rand", + "rand 0.8.5", "sc-client-api", + "sc-keystore", "schnellru", "sp-application-crypto", "sp-core", "sp-keystore", - "thiserror", + "thiserror 1.0.69", "tracing-gum", ] [[package]] name = "polkadot-overseer" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "futures", "futures-timer", "orchestra", - "parking_lot 0.12.3", "polkadot-node-metrics", "polkadot-node-network-protocol", "polkadot-node-primitives", "polkadot-node-subsystem-types", "polkadot-primitives", "sc-client-api", - "sp-api", "sp-core", "tikv-jemalloc-ctl", "tracing-gum", @@ -9585,8 +10276,8 @@ dependencies = [ [[package]] name = "polkadot-parachain-primitives" -version = "14.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "16.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bounded-collections", "derive_more 0.99.17", @@ -9601,8 +10292,8 @@ dependencies = [ [[package]] name = "polkadot-primitives" -version = "16.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "18.2.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bitvec", "hex-literal", @@ -9623,12 +10314,14 @@ dependencies = [ "sp-keystore", "sp-runtime", "sp-staking", + "sp-std", + "thiserror 1.0.69", ] [[package]] name = "polkadot-rpc" -version = "19.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "24.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "jsonrpsee", "mmr-rpc", @@ -9640,11 +10333,9 @@ dependencies = [ "sc-consensus-babe-rpc", "sc-consensus-beefy", "sc-consensus-beefy-rpc", - "sc-consensus-epochs", "sc-consensus-grandpa", "sc-consensus-grandpa-rpc", "sc-rpc", - "sc-rpc-spec-v2", "sc-sync-state-rpc", "sc-transaction-pool-api", "sp-api", @@ -9662,8 +10353,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-common" -version = "17.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "19.1.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bitvec", "frame-benchmarking", @@ -9682,7 +10373,7 @@ dependencies = [ "pallet-fast-unstake", "pallet-identity", "pallet-session", - "pallet-staking 38.0.0", + "pallet-staking 40.1.1", "pallet-staking-reward-fn", "pallet-timestamp", "pallet-transaction-payment", @@ -9694,12 +10385,12 @@ dependencies = [ "rustc-hex", "scale-info", "serde", - "serde_derive", "slot-range-helper", "sp-api", "sp-core", "sp-inherents", "sp-io", + "sp-keyring", "sp-npos-elections", "sp-runtime", "sp-session", @@ -9712,10 +10403,10 @@ dependencies = [ [[package]] name = "polkadot-runtime-metrics" -version = "17.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "20.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "bs58 0.5.1", + "bs58", "frame-benchmarking", "parity-scale-codec", "polkadot-primitives", @@ -9724,12 +10415,11 @@ dependencies = [ [[package]] name = "polkadot-runtime-parachains" -version = "17.0.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "19.2.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bitflags 1.3.2", "bitvec", - "derive_more 0.99.17", "frame-benchmarking", "frame-support", "frame-system", @@ -9743,38 +10433,81 @@ dependencies = [ "pallet-message-queue", "pallet-mmr", "pallet-session", - "pallet-staking 38.0.0", + "pallet-staking 40.1.1", "pallet-timestamp", - "pallet-vesting", "parity-scale-codec", "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-metrics", - "rand", - "rand_chacha", + "rand 0.8.5", + "rand_chacha 0.3.1", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-arithmetic", + "sp-core", + "sp-inherents", + "sp-io", + "sp-keystore", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std", + "staging-xcm", + "staging-xcm-executor", + "static_assertions", +] + +[[package]] +name = "polkadot-sdk" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb819108697967452fa6d8d96ab4c0d48cbaa423b3156499dcb24f1cf95d6775" +dependencies = [ + "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "polkadot-sdk-frame" +version = "0.9.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "log", + "parity-scale-codec", "scale-info", "serde", "sp-api", - "sp-application-crypto", "sp-arithmetic", + "sp-block-builder", + "sp-consensus-aura", + "sp-consensus-grandpa", "sp-core", + "sp-genesis-builder", "sp-inherents", "sp-io", - "sp-keystore", + "sp-keyring", + "sp-offchain", "sp-runtime", "sp-session", - "sp-staking", - "sp-std", - "staging-xcm", - "staging-xcm-executor", - "static_assertions", + "sp-storage", + "sp-transaction-pool", + "sp-version", ] [[package]] name = "polkadot-service" -version = "19.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "24.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "frame-benchmarking", @@ -9803,6 +10536,7 @@ dependencies = [ "polkadot-network-bridge", "polkadot-node-collation-generation", "polkadot-node-core-approval-voting", + "polkadot-node-core-approval-voting-parallel", "polkadot-node-core-av-store", "polkadot-node-core-backing", "polkadot-node-core-bitfield-signing", @@ -9872,7 +10606,7 @@ dependencies = [ "sp-weights", "staging-xcm", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", "tracing-gum", "westend-runtime", "xcm-runtime-apis", @@ -9880,15 +10614,15 @@ dependencies = [ [[package]] name = "polkadot-statement-distribution" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "arrayvec 0.7.4", "bitvec", "fatality", "futures", "futures-timer", - "indexmap 2.2.6", + "indexmap 2.12.0", "parity-scale-codec", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -9897,68 +10631,122 @@ dependencies = [ "polkadot-primitives", "sp-keystore", "sp-staking", - "thiserror", + "thiserror 1.0.69", "tracing-gum", ] [[package]] name = "polkadot-statement-table" -version = "16.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "19.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "polkadot-primitives", - "sp-core", "tracing-gum", ] [[package]] name = "polkavm" -version = "0.9.3" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd044ab1d3b11567ab6b98ca71259a992b4034220d5972988a0e96518e5d343d" +dependencies = [ + "libc", + "log", + "polkavm-assembler 0.18.0", + "polkavm-common 0.18.0", + "polkavm-linux-raw 0.18.0", +] + +[[package]] +name = "polkavm" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a3693e5efdb2bf74e449cd25fd777a28bd7ed87e41f5d5da75eb31b4de48b94" +checksum = "cfd34e2f74206fff33482ae1718e275f11365ef8c4de7f0e69217f8845303867" dependencies = [ "libc", "log", - "polkavm-assembler", - "polkavm-common", - "polkavm-linux-raw", + "polkavm-assembler 0.21.0", + "polkavm-common 0.21.0", + "polkavm-linux-raw 0.21.0", ] [[package]] name = "polkavm-assembler" -version = "0.9.0" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaad38dc420bfed79e6f731471c973ce5ff5e47ab403e63cf40358fef8a6368f" +dependencies = [ + "log", +] + +[[package]] +name = "polkavm-assembler" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa96d6d868243acc12de813dd48e756cbadcc8e13964c70d272753266deadc1" +checksum = "f512bc80cb10439391a7c13a9eb2d37cf66b7305e7df0a06d662eff4f5b07625" dependencies = [ "log", ] [[package]] name = "polkavm-common" -version = "0.9.0" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ff33982a807d8567645d4784b9b5d7ab87bcb494f534a57cadd9012688e102" +dependencies = [ + "log", + "polkavm-assembler 0.18.0", +] + +[[package]] +name = "polkavm-common" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9428a5cfcc85c5d7b9fc4b6a18c4b802d0173d768182a51cc7751640f08b92" +checksum = "5c16b809cfd398f861261c045a8745e6c78b71ea7e0d3ef6f7cc553eb27bc17e" dependencies = [ + "blake3", "log", + "polkavm-assembler 0.21.0", ] [[package]] name = "polkavm-derive" -version = "0.9.1" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8c4bea6f3e11cd89bb18bcdddac10bd9a24015399bd1c485ad68a985a19606" +checksum = "c2eb703f3b6404c13228402e98a5eae063fd16b8f58afe334073ec105ee4117e" dependencies = [ - "polkavm-derive-impl-macro", + "polkavm-derive-impl-macro 0.18.0", +] + +[[package]] +name = "polkavm-derive" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47239245f87329541932c0d7fec750a66a75b13aa87dfe4fbfd637bab86ad387" +dependencies = [ + "polkavm-derive-impl-macro 0.21.0", ] [[package]] name = "polkavm-derive-impl" -version = "0.9.0" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f2116a92e6e96220a398930f4c8a6cda1264206f3e2034fc9982bfd93f261f7" +dependencies = [ + "polkavm-common 0.18.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "polkavm-derive-impl" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" +checksum = "24fd6c6215450c3e57511df5c38a82eb4bde208de15ee15046ac33852f3c3eaa" dependencies = [ - "polkavm-common", + "polkavm-common 0.21.0", "proc-macro2", "quote", "syn 2.0.90", @@ -9966,34 +10754,67 @@ dependencies = [ [[package]] name = "polkavm-derive-impl-macro" -version = "0.9.0" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c16669ddc7433e34c1007d31080b80901e3e8e523cb9d4b441c3910cf9294b" +dependencies = [ + "polkavm-derive-impl 0.18.1", + "syn 2.0.90", +] + +[[package]] +name = "polkavm-derive-impl-macro" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" +checksum = "36837f6b7edfd6f4498f8d25d81da16cf03bd6992c3e56f3d477dfc90f4fefca" dependencies = [ - "polkavm-derive-impl", + "polkavm-derive-impl 0.21.0", "syn 2.0.90", ] [[package]] name = "polkavm-linker" -version = "0.9.2" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7be503e60cf56c0eb785f90aaba4b583b36bff00e93997d93fef97f9553c39" +checksum = "e9bfe793b094d9ea5c99b7c43ba46e277b0f8f48f4bbfdbabf8d3ebf701a4bd3" dependencies = [ - "gimli 0.28.1", - "hashbrown 0.14.3", + "dirs", + "gimli 0.31.1", + "hashbrown 0.14.5", "log", - "object 0.32.2", - "polkavm-common", + "object 0.36.7", + "polkavm-common 0.18.0", + "regalloc2 0.9.3", + "rustc-demangle", +] + +[[package]] +name = "polkavm-linker" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23bc764986c4a63f9ab9890c3f4eb9b4c13b6ff80d79685bd48ade147234aab4" +dependencies = [ + "dirs", + "gimli 0.31.1", + "hashbrown 0.14.5", + "log", + "object 0.36.7", + "polkavm-common 0.21.0", "regalloc2 0.9.3", "rustc-demangle", ] [[package]] name = "polkavm-linux-raw" -version = "0.9.0" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23eff02c070c70f31878a3d915e88a914ecf3e153741e2fb572dde28cce20fde" + +[[package]] +name = "polkavm-linux-raw" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26e85d3456948e650dff0cfc85603915847faf893ed1e66b020bb82ef4557120" +checksum = "be6cd1d48c5e7814d287a3e12a339386a5dfa2f3ac72f932335f4cf56467f1b3" [[package]] name = "polling" @@ -10051,9 +10872,18 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "potential_utf" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] [[package]] name = "powerfmt" @@ -10067,20 +10897,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "predicates" -version = "2.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" -dependencies = [ - "difflib", - "float-cmp", - "itertools 0.10.5", - "normalize-line-endings", - "predicates-core", - "regex", -] - [[package]] name = "predicates" version = "3.1.2" @@ -10127,16 +10943,6 @@ dependencies = [ "yansi", ] -[[package]] -name = "prettyplease" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28f53e8b192565862cf99343194579a022eb9c7dd3a8d03134734803c7b3125" -dependencies = [ - "proc-macro2", - "syn 1.0.109", -] - [[package]] name = "prettyplease" version = "0.2.19" @@ -10154,17 +10960,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", - "impl-codec", + "impl-codec 0.6.0", + "uint 0.9.5", +] + +[[package]] +name = "primitive-types" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15600a7d856470b7d278b3fe0e311fe28c2526348549f8ef2ff7db3299c87f5" +dependencies = [ + "fixed-hash", + "impl-codec 0.7.1", + "impl-num-traits", "impl-rlp", "impl-serde", "scale-info", - "uint", + "uint 0.10.0", ] [[package]] name = "primitives" -version = "6.1.0" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "6.1.2" +source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2503-11-snek#59ae6bfb45c4e37c38c95eead4c9f29e26bc478b" dependencies = [ "frame-support", "hex-literal", @@ -10179,12 +10997,12 @@ dependencies = [ [[package]] name = "primitives" -version = "6.6.5" +version = "6.7.0" dependencies = [ "frame-support", "parity-scale-codec", "polkadot-primitives", - "primitive-types", + "primitive-types 0.13.1", "scale-info", "serde", "sp-core", @@ -10207,7 +11025,7 @@ dependencies = [ "futures", "futures-timer", "nanorand", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -10255,11 +11073,22 @@ dependencies = [ ] [[package]] -name = "proc-macro-warning" -version = "0.4.2" +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" dependencies = [ + "proc-macro-error-attr2", "proc-macro2", "quote", "syn 2.0.90", @@ -10278,9 +11107,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] @@ -10296,14 +11125,14 @@ dependencies = [ "lazy_static", "memchr", "parking_lot 0.12.3", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "prometheus-client" -version = "0.21.2" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c99afa9a01501019ac3a14d71d9f94050346f55ca471ce90c799a15c58f61e2" +checksum = "504ee9ff529add891127c4827eb481bd69dc0ebc72e9a682e187db4caa60c3ca" dependencies = [ "dtoa", "itoa", @@ -10323,13 +11152,23 @@ dependencies = [ ] [[package]] -name = "prost" -version = "0.11.9" +name = "proptest" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" dependencies = [ - "bytes", - "prost-derive 0.11.9", + "bit-set", + "bit-vec", + "bitflags 2.10.0", + "lazy_static", + "num-traits", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_xorshift", + "regex-syntax 0.8.8", + "rusty-fork", + "tempfile", + "unarray", ] [[package]] @@ -10343,43 +11182,30 @@ dependencies = [ ] [[package]] -name = "prost-build" -version = "0.11.9" +name = "prost" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" dependencies = [ "bytes", - "heck 0.4.1", - "itertools 0.10.5", - "lazy_static", - "log", - "multimap", - "petgraph", - "prettyplease 0.1.11", - "prost 0.11.9", - "prost-types 0.11.9", - "regex", - "syn 1.0.109", - "tempfile", - "which", + "prost-derive 0.13.5", ] [[package]] name = "prost-build" -version = "0.12.6" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "bytes", "heck 0.5.0", - "itertools 0.12.1", + "itertools 0.13.0", "log", "multimap", "once_cell", "petgraph", - "prettyplease 0.2.19", - "prost 0.12.6", - "prost-types 0.12.6", + "prettyplease", + "prost 0.13.5", + "prost-types", "regex", "syn 2.0.90", "tempfile", @@ -10387,25 +11213,25 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.12.1", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.90", ] [[package]] name = "prost-derive" -version = "0.12.6" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.13.0", "proc-macro2", "quote", "syn 2.0.90", @@ -10413,20 +11239,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" -dependencies = [ - "prost 0.11.9", -] - -[[package]] -name = "prost-types" -version = "0.12.6" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" dependencies = [ - "prost 0.12.6", + "prost 0.13.5", ] [[package]] @@ -10470,122 +11287,87 @@ dependencies = [ [[package]] name = "quick-protobuf-codec" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ededb1cd78531627244d51dd0c7139fbe736c7d57af0092a76f0ffb2f56e98" +checksum = "15a0580ab32b169745d7a39db2ba969226ca16738931be152a3209b409de2474" dependencies = [ - "asynchronous-codec", + "asynchronous-codec 0.7.0", "bytes", "quick-protobuf", - "thiserror", - "unsigned-varint 0.7.2", -] - -[[package]] -name = "quinn" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e8b432585672228923edbbf64b8b12c14e1112f62e88737655b4a083dbcd78e" -dependencies = [ - "bytes", - "pin-project-lite", - "quinn-proto 0.9.6", - "quinn-udp 0.3.2", - "rustc-hash 1.1.0", - "rustls 0.20.9", - "thiserror", - "tokio", - "tracing", - "webpki", + "thiserror 1.0.69", + "unsigned-varint 0.8.0", ] [[package]] name = "quinn" -version = "0.10.2" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cc2c5017e4b43d5995dcea317bc46c1e09404c0a9664d2908f7f02dfe943d75" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ "bytes", + "cfg_aliases 0.2.1", "futures-io", "pin-project-lite", - "quinn-proto 0.10.6", - "quinn-udp 0.4.1", - "rustc-hash 1.1.0", - "rustls 0.21.11", - "thiserror", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.0", + "rustls", + "socket2 0.6.1", + "thiserror 2.0.17", "tokio", "tracing", + "web-time", ] [[package]] name = "quinn-proto" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" -dependencies = [ - "bytes", - "rand", - "ring 0.16.20", - "rustc-hash 1.1.0", - "rustls 0.20.9", - "slab", - "thiserror", - "tinyvec", - "tracing", - "webpki", -] - -[[package]] -name = "quinn-proto" -version = "0.10.6" +version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "141bf7dfde2fbc246bfd3fe12f2455aa24b0fbd9af535d8c86c7bd1381ff2b1a" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ "bytes", - "rand", - "ring 0.16.20", - "rustc-hash 1.1.0", - "rustls 0.21.11", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring 0.17.8", + "rustc-hash 2.1.0", + "rustls", + "rustls-pki-types", "slab", - "thiserror", + "thiserror 2.0.17", "tinyvec", "tracing", + "web-time", ] [[package]] name = "quinn-udp" -version = "0.3.2" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "641538578b21f5e5c8ea733b736895576d0fe329bb883b937db6f4d163dbaaf4" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" dependencies = [ + "cfg_aliases 0.2.1", "libc", - "quinn-proto 0.9.6", - "socket2 0.4.10", + "once_cell", + "socket2 0.6.1", "tracing", - "windows-sys 0.42.0", + "windows-sys 0.60.2", ] [[package]] -name = "quinn-udp" -version = "0.4.1" +name = "quote" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "055b4e778e8feb9f93c4e439f71dc2156ef13360b432b799e179a8c4cdf0b1d7" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ - "bytes", - "libc", - "socket2 0.5.8", - "tracing", - "windows-sys 0.48.0", + "proc-macro2", ] [[package]] -name = "quote" -version = "1.0.37" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" -dependencies = [ - "proc-macro2", -] +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "radium" @@ -10595,13 +11377,24 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", + "serde", +] + +[[package]] +name = "rand" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ - "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -10611,7 +11404,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -10620,7 +11423,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.14", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.4", ] [[package]] @@ -10630,7 +11442,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", ] [[package]] @@ -10639,7 +11451,16 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" dependencies = [ - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core 0.6.4", ] [[package]] @@ -10648,7 +11469,7 @@ version = "11.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb9ee317cfe3fbd54b36a511efc1edd42e216903c9cd575e686dd68a2ba90d8d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.10.0", ] [[package]] @@ -10679,9 +11500,9 @@ dependencies = [ [[package]] name = "rcgen" -version = "0.10.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" +checksum = "52c4f3084aa3bc7dfbba4eff4fab2a54db4324965d8872ab933565e6fbd83bc6" dependencies = [ "pem", "ring 0.16.20", @@ -10713,9 +11534,9 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ - "getrandom", + "getrandom 0.2.14", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -10727,7 +11548,7 @@ dependencies = [ "derive_more 0.99.17", "fs-err", "static_init", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -10777,14 +11598,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", + "regex-automata 0.4.13", + "regex-syntax 0.8.8", ] [[package]] @@ -10798,13 +11619,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.3", + "regex-syntax 0.8.8", ] [[package]] @@ -10815,9 +11636,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "resolv-conf" @@ -10862,13 +11683,22 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.14", "libc", "spin 0.9.8", "untrusted 0.9.0", "windows-sys 0.52.0", ] +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "rlp" version = "0.5.2" @@ -10876,19 +11706,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ "bytes", - "rlp-derive", "rustc-hex", ] [[package]] -name = "rlp-derive" -version = "0.1.0" +name = "rlp" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +checksum = "fa24e92bb2a83198bb76d661a71df9f7076b8c420b8696e4d3d97d50d94479e3" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "bytes", + "rustc-hex", ] [[package]] @@ -10903,8 +11731,8 @@ dependencies = [ [[package]] name = "rococo-runtime" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "binary-merkle-tree", "bitvec", @@ -10927,15 +11755,14 @@ dependencies = [ "pallet-beefy-mmr", "pallet-bounties", "pallet-child-bounties", - "pallet-collective", "pallet-conviction-voting", - "pallet-democracy 38.0.0", + "pallet-democracy 40.1.0", "pallet-elections-phragmen", "pallet-grandpa", "pallet-identity", "pallet-indices", - "pallet-membership", "pallet-message-queue", + "pallet-migrations", "pallet-mmr", "pallet-multisig", "pallet-nis", @@ -10950,7 +11777,7 @@ dependencies = [ "pallet-scheduler", "pallet-session", "pallet-society", - "pallet-staking 38.0.0", + "pallet-staking 40.1.1", "pallet-state-trie-migration", "pallet-sudo", "pallet-timestamp", @@ -10973,7 +11800,6 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "smallvec", "sp-api", "sp-arithmetic", "sp-authority-discovery", @@ -10985,6 +11811,7 @@ dependencies = [ "sp-genesis-builder", "sp-inherents", "sp-io", + "sp-keyring", "sp-mmr-primitives", "sp-offchain", "sp-runtime", @@ -10996,15 +11823,14 @@ dependencies = [ "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", - "static_assertions", "substrate-wasm-builder", "xcm-runtime-apis", ] [[package]] name = "rococo-runtime-constants" -version = "17.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "20.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-support", "polkadot-primitives", @@ -11045,7 +11871,7 @@ dependencies = [ "netlink-packet-route", "netlink-proto", "nix 0.24.3", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -11059,11 +11885,57 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rug" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "203180f444c95eac53586ed04793ecf6454c5d28f9eca8eead815fc19e136c47" +dependencies = [ + "az", + "gmp-mpfr-sys", + "libc", + "num-integer", + "num-traits", +] + +[[package]] +name = "ruint" +version = "1.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5ef8fb1dd8de3870cb8400d51b4c2023854bbafd5431a3ac7e7317243e22d2f" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp 0.3.1", + "fastrlp 0.4.0", + "num-bigint", + "num-integer", + "num-traits", + "parity-scale-codec", + "primitive-types 0.12.2", + "proptest", + "rand 0.8.5", + "rlp 0.5.2", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + [[package]] name = "runtime-integration-tests" -version = "1.0.8" +version = "1.1.0" dependencies = [ "basilisk-runtime", + "basilisk-traits", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -11089,7 +11961,7 @@ dependencies = [ "orml-xcm", "orml-xcm-support", "orml-xtokens", - "pallet-asset-registry 2.3.6", + "pallet-asset-registry", "pallet-aura", "pallet-authorship", "pallet-balances", @@ -11120,7 +11992,7 @@ dependencies = [ "polkadot-runtime-parachains", "polkadot-service", "pretty_assertions", - "primitives 6.6.5", + "primitives 6.7.0", "rococo-runtime", "sc-consensus-grandpa", "sp-api", @@ -11175,6 +12047,15 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + [[package]] name = "rustc_version" version = "0.4.0" @@ -11227,7 +12108,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys 0.4.13", @@ -11235,26 +12116,16 @@ dependencies = [ ] [[package]] -name = "rustls" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" -dependencies = [ - "ring 0.16.20", - "sct", - "webpki", -] - -[[package]] -name = "rustls" -version = "0.21.11" +name = "rustix" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "log", - "ring 0.17.8", - "rustls-webpki 0.101.7", - "sct", + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", ] [[package]] @@ -11274,36 +12145,27 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.6.3" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba" dependencies = [ "openssl-probe", - "rustls-pemfile 1.0.4", + "rustls-pemfile", + "rustls-pki-types", "schannel", - "security-framework", + "security-framework 2.10.0", ] [[package]] name = "rustls-native-certs" -version = "0.7.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba" +checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" dependencies = [ "openssl-probe", - "rustls-pemfile 2.1.3", "rustls-pki-types", "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", + "security-framework 3.5.1", ] [[package]] @@ -11321,6 +12183,9 @@ name = "rustls-pki-types" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" +dependencies = [ + "web-time", +] [[package]] name = "rustls-platform-verifier" @@ -11328,16 +12193,16 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afbb878bdfdf63a336a5e63561b1835e7a8c91524f51621db870169eac84b490" dependencies = [ - "core-foundation", + "core-foundation 0.9.4", "core-foundation-sys", "jni", "log", "once_cell", - "rustls 0.23.20", + "rustls", "rustls-native-certs 0.7.1", "rustls-platform-verifier-android", "rustls-webpki 0.102.8", - "security-framework", + "security-framework 2.10.0", "security-framework-sys", "webpki-roots 0.26.7", "winapi", @@ -11376,6 +12241,18 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +[[package]] +name = "rusty-fork" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + [[package]] name = "ruzstd" version = "0.4.0" @@ -11387,6 +12264,16 @@ dependencies = [ "twox-hash", ] +[[package]] +name = "ruzstd" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5174a470eeb535a721ae9fdd6e291c2411a906b96592182d05217591d5c5cf7b" +dependencies = [ + "byteorder", + "derive_more 0.99.17", +] + [[package]] name = "rw-stream-sink" version = "0.4.0" @@ -11413,6 +12300,15 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher 0.4.4", +] + [[package]] name = "same-file" version = "1.0.6" @@ -11424,32 +12320,30 @@ dependencies = [ [[package]] name = "sc-allocator" -version = "29.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "31.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "log", "sp-core", "sp-wasm-interface", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-authority-discovery" -version = "0.45.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.50.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "futures", "futures-timer", "ip_network", - "libp2p", "linked_hash_set", "log", - "multihash 0.19.1", "parity-scale-codec", "prost 0.12.6", - "prost-build 0.12.6", - "rand", + "prost-build", + "rand 0.8.5", "sc-client-api", "sc-network", "sc-network-types", @@ -11460,16 +12354,15 @@ dependencies = [ "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-basic-authorship" -version = "0.45.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.49.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "futures", - "futures-timer", "log", "parity-scale-codec", "sc-block-builder", @@ -11487,8 +12380,8 @@ dependencies = [ [[package]] name = "sc-block-builder" -version = "0.42.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.44.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "sp-api", @@ -11502,12 +12395,11 @@ dependencies = [ [[package]] name = "sc-chain-spec" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "43.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "array-bytes", "docify", - "log", "memmap2 0.9.4", "parity-scale-codec", "sc-chain-spec-derive", @@ -11519,7 +12411,7 @@ dependencies = [ "serde_json", "sp-blockchain", "sp-core", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", "sp-genesis-builder", "sp-io", "sp-runtime", @@ -11530,7 +12422,7 @@ dependencies = [ [[package]] name = "sc-chain-spec-derive" version = "12.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", @@ -11540,8 +12432,8 @@ dependencies = [ [[package]] name = "sc-cli" -version = "0.47.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.52.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "array-bytes", "chrono", @@ -11554,7 +12446,7 @@ dependencies = [ "names", "parity-bip39", "parity-scale-codec", - "rand", + "rand 0.8.5", "regex", "rpassword", "sc-client-api", @@ -11565,6 +12457,7 @@ dependencies = [ "sc-service", "sc-telemetry", "sc-tracing", + "sc-transaction-pool", "sc-utils", "serde", "serde_json", @@ -11575,14 +12468,14 @@ dependencies = [ "sp-panic-handler", "sp-runtime", "sp-version", - "thiserror", + "thiserror 1.0.69", "tokio", ] [[package]] name = "sc-client-api" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "fnv", "futures", @@ -11600,7 +12493,6 @@ dependencies = [ "sp-externalities", "sp-runtime", "sp-state-machine", - "sp-statement-store", "sp-storage", "sp-trie", "substrate-prometheus-endpoint", @@ -11608,8 +12500,8 @@ dependencies = [ [[package]] name = "sc-client-db" -version = "0.44.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.46.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "hash-db", "kvdb", @@ -11634,32 +12526,31 @@ dependencies = [ [[package]] name = "sc-consensus" -version = "0.44.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.49.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "futures", "log", - "mockall 0.11.4", + "mockall", "parking_lot 0.12.3", "sc-client-api", "sc-network-types", "sc-utils", "serde", - "sp-api", "sp-blockchain", "sp-consensus", "sp-core", "sp-runtime", "sp-state-machine", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-consensus-aura" -version = "0.45.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.50.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "futures", @@ -11682,13 +12573,13 @@ dependencies = [ "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-consensus-babe" -version = "0.45.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.50.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "fork-tree", @@ -11713,18 +12604,18 @@ dependencies = [ "sp-consensus-babe", "sp-consensus-slots", "sp-core", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", "sp-inherents", "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-consensus-babe-rpc" -version = "0.45.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.50.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "futures", "jsonrpsee", @@ -11740,18 +12631,17 @@ dependencies = [ "sp-core", "sp-keystore", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-consensus-beefy" -version = "24.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "29.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "array-bytes", "async-channel 1.9.0", "async-trait", - "fnv", "futures", "log", "parity-scale-codec", @@ -11770,19 +12660,18 @@ dependencies = [ "sp-consensus", "sp-consensus-beefy", "sp-core", - "sp-crypto-hashing", "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", "tokio", "wasm-timer", ] [[package]] name = "sc-consensus-beefy-rpc" -version = "24.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "29.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "futures", "jsonrpsee", @@ -11796,13 +12685,13 @@ dependencies = [ "sp-consensus-beefy", "sp-core", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-consensus-epochs" -version = "0.44.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.49.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "fork-tree", "parity-scale-codec", @@ -11814,8 +12703,8 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa" -version = "0.30.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.35.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "ahash", "array-bytes", @@ -11828,7 +12717,7 @@ dependencies = [ "log", "parity-scale-codec", "parking_lot 0.12.3", - "rand", + "rand 0.8.5", "sc-block-builder", "sc-chain-spec", "sc-client-api", @@ -11849,17 +12738,17 @@ dependencies = [ "sp-consensus", "sp-consensus-grandpa", "sp-core", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-consensus-grandpa-rpc" -version = "0.30.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.35.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "finality-grandpa", "futures", @@ -11873,13 +12762,13 @@ dependencies = [ "sp-blockchain", "sp-core", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-consensus-slots" -version = "0.44.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.49.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "futures", @@ -11901,8 +12790,8 @@ dependencies = [ [[package]] name = "sc-executor" -version = "0.40.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.42.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", @@ -11924,36 +12813,34 @@ dependencies = [ [[package]] name = "sc-executor-common" -version = "0.35.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.38.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "polkavm", + "polkavm 0.18.0", "sc-allocator", "sp-maybe-compressed-blob", "sp-wasm-interface", - "thiserror", + "thiserror 1.0.69", "wasm-instrument", ] [[package]] name = "sc-executor-polkavm" -version = "0.32.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.35.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "log", - "polkavm", + "polkavm 0.18.0", "sc-executor-common", "sp-wasm-interface", ] [[package]] name = "sc-executor-wasmtime" -version = "0.35.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.38.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "anyhow", - "cfg-if", - "libc", "log", "parking_lot 0.12.3", "rustix 0.36.17", @@ -11966,8 +12853,8 @@ dependencies = [ [[package]] name = "sc-informant" -version = "0.44.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.49.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "console", "futures", @@ -11975,7 +12862,6 @@ dependencies = [ "log", "sc-client-api", "sc-network", - "sc-network-common", "sc-network-sync", "sp-blockchain", "sp-runtime", @@ -11983,8 +12869,8 @@ dependencies = [ [[package]] name = "sc-keystore" -version = "33.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "35.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "array-bytes", "parking_lot 0.12.3", @@ -11992,13 +12878,13 @@ dependencies = [ "sp-application-crypto", "sp-core", "sp-keystore", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-mixnet" -version = "0.15.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.20.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "array-bytes", "arrayvec 0.7.4", @@ -12008,7 +12894,6 @@ dependencies = [ "futures-timer", "log", "mixnet", - "multiaddr 0.18.2", "parity-scale-codec", "parking_lot 0.12.3", "sc-client-api", @@ -12021,18 +12906,18 @@ dependencies = [ "sp-keystore", "sp-mixnet", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-network" -version = "0.45.3" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.50.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "array-bytes", "async-channel 1.9.0", "async-trait", - "asynchronous-codec", + "asynchronous-codec 0.6.2", "bytes", "cid 0.9.0", "either", @@ -12044,15 +12929,14 @@ dependencies = [ "linked_hash_set", "litep2p", "log", - "mockall 0.11.4", - "once_cell", + "mockall", "parity-scale-codec", "parking_lot 0.12.3", "partial_sort", "pin-project", "prost 0.12.6", - "prost-build 0.12.6", - "rand", + "prost-build", + "rand 0.8.5", "sc-client-api", "sc-network-common", "sc-network-types", @@ -12066,7 +12950,7 @@ dependencies = [ "sp-core", "sp-runtime", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "unsigned-varint 0.7.2", @@ -12077,26 +12961,18 @@ dependencies = [ [[package]] name = "sc-network-common" -version = "0.44.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.48.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "async-trait", "bitflags 1.3.2", - "futures", - "libp2p-identity", "parity-scale-codec", - "prost-build 0.12.6", - "sc-consensus", - "sc-network-types", - "sp-consensus", - "sp-consensus-grandpa", "sp-runtime", ] [[package]] name = "sc-network-gossip" -version = "0.45.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.50.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "ahash", "futures", @@ -12114,8 +12990,8 @@ dependencies = [ [[package]] name = "sc-network-light" -version = "0.44.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.49.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "array-bytes", "async-channel 1.9.0", @@ -12123,33 +12999,31 @@ dependencies = [ "log", "parity-scale-codec", "prost 0.12.6", - "prost-build 0.12.6", + "prost-build", "sc-client-api", "sc-network", "sc-network-types", "sp-blockchain", "sp-core", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-network-sync" -version = "0.44.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.49.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "array-bytes", "async-channel 1.9.0", "async-trait", "fork-tree", "futures", - "futures-timer", - "libp2p", "log", - "mockall 0.11.4", + "mockall", "parity-scale-codec", "prost 0.12.6", - "prost-build 0.12.6", + "prost-build", "sc-client-api", "sc-consensus", "sc-network", @@ -12165,15 +13039,15 @@ dependencies = [ "sp-core", "sp-runtime", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", ] [[package]] name = "sc-network-transactions" -version = "0.44.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.49.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "array-bytes", "futures", @@ -12191,42 +13065,44 @@ dependencies = [ [[package]] name = "sc-network-types" -version = "0.12.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.16.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "bs58 0.5.1", + "bs58", + "bytes", "ed25519-dalek", "libp2p-identity", + "libp2p-kad", "litep2p", "log", "multiaddr 0.18.2", "multihash 0.19.1", - "rand", - "thiserror", + "rand 0.8.5", + "thiserror 1.0.69", "zeroize", ] [[package]] name = "sc-offchain" -version = "40.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "45.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "array-bytes", "bytes", "fnv", "futures", "futures-timer", - "hyper 0.14.31", + "http-body-util", + "hyper 1.5.1", "hyper-rustls", - "log", + "hyper-util", "num_cpus", "once_cell", "parity-scale-codec", "parking_lot 0.12.3", - "rand", + "rand 0.8.5", + "rustls", "sc-client-api", "sc-network", - "sc-network-common", "sc-network-types", "sc-transaction-pool-api", "sc-utils", @@ -12242,8 +13118,8 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" -version = "0.18.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.20.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -12251,8 +13127,8 @@ dependencies = [ [[package]] name = "sc-rpc" -version = "40.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "45.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "futures", "jsonrpsee", @@ -12283,8 +13159,8 @@ dependencies = [ [[package]] name = "sc-rpc-api" -version = "0.44.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.49.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -12298,13 +13174,13 @@ dependencies = [ "sp-rpc", "sp-runtime", "sp-version", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-rpc-server" -version = "17.1.2" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "22.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "dyn-clone", "forwarded-header-value", @@ -12327,23 +13203,23 @@ dependencies = [ [[package]] name = "sc-rpc-spec-v2" -version = "0.45.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.50.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "array-bytes", "futures", "futures-util", "hex", + "itertools 0.11.0", "jsonrpsee", "log", "parity-scale-codec", "parking_lot 0.12.3", - "rand", + "rand 0.8.5", "sc-chain-spec", "sc-client-api", "sc-rpc", "sc-transaction-pool-api", - "sc-utils", "schnellru", "serde", "sp-api", @@ -12352,15 +13228,31 @@ dependencies = [ "sp-rpc", "sp-runtime", "sp-version", - "thiserror", + "substrate-prometheus-endpoint", + "thiserror 1.0.69", "tokio", "tokio-stream", ] +[[package]] +name = "sc-runtime-utilities" +version = "0.2.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" +dependencies = [ + "parity-scale-codec", + "sc-executor", + "sc-executor-common", + "sp-core", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", + "sp-state-machine", + "sp-wasm-interface", + "thiserror 1.0.69", +] + [[package]] name = "sc-service" -version = "0.46.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.51.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "directories", @@ -12372,7 +13264,7 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", "pin-project", - "rand", + "rand 0.8.5", "sc-chain-spec", "sc-client-api", "sc-client-db", @@ -12415,7 +13307,7 @@ dependencies = [ "static_init", "substrate-prometheus-endpoint", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "tracing-futures", @@ -12423,8 +13315,8 @@ dependencies = [ [[package]] name = "sc-state-db" -version = "0.36.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.38.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "log", "parity-scale-codec", @@ -12434,21 +13326,21 @@ dependencies = [ [[package]] name = "sc-storage-monitor" -version = "0.22.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.24.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "clap", "fs4", "log", "sp-core", - "thiserror", + "thiserror 1.0.69", "tokio", ] [[package]] name = "sc-sync-state-rpc" -version = "0.45.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.50.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -12461,34 +13353,33 @@ dependencies = [ "serde_json", "sp-blockchain", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-sysinfo" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "42.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "derive_more 0.99.17", "futures", "libc", "log", - "rand", + "rand 0.8.5", "rand_pcg", "regex", "sc-telemetry", "serde", "serde_json", "sp-core", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", "sp-io", - "sp-std", ] [[package]] name = "sc-telemetry" -version = "25.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "28.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "chrono", "futures", @@ -12496,24 +13387,22 @@ dependencies = [ "log", "parking_lot 0.12.3", "pin-project", - "rand", - "sc-network", + "rand 0.8.5", "sc-utils", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "wasm-timer", ] [[package]] name = "sc-tracing" -version = "37.0.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "chrono", "console", "is-terminal", - "lazy_static", "libc", "log", "parity-scale-codec", @@ -12528,7 +13417,7 @@ dependencies = [ "sp-rpc", "sp-runtime", "sp-tracing", - "thiserror", + "thiserror 1.0.69", "tracing", "tracing-log", "tracing-subscriber", @@ -12536,8 +13425,8 @@ dependencies = [ [[package]] name = "sc-tracing-proc-macro" -version = "11.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "11.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", @@ -12547,12 +13436,14 @@ dependencies = [ [[package]] name = "sc-transaction-pool" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "futures", "futures-timer", + "indexmap 2.12.0", + "itertools 0.11.0", "linked-hash-map", "log", "parity-scale-codec", @@ -12564,45 +13455,115 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-core", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", "sp-runtime", "sp-tracing", "sp-transaction-pool", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", + "tokio", + "tokio-stream", + "tracing", ] [[package]] name = "sc-transaction-pool-api" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "futures", + "indexmap 2.12.0", "log", "parity-scale-codec", "serde", "sp-blockchain", "sp-core", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-utils" -version = "17.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "18.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-channel 1.9.0", "futures", "futures-timer", - "lazy_static", "log", "parking_lot 0.12.3", "prometheus", "sp-arithmetic", ] +[[package]] +name = "scale-bits" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57b1e7f6b65ed1f04e79a85a57d755ad56d76fdf1e9bddcc9ae14f71fcdcf54" +dependencies = [ + "parity-scale-codec", + "scale-info", + "scale-type-resolver", + "serde", +] + +[[package]] +name = "scale-decode" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ae9cc099ae85ff28820210732b00f019546f36f33225f509fe25d5816864a0" +dependencies = [ + "derive_more 1.0.0", + "parity-scale-codec", + "primitive-types 0.13.1", + "scale-bits", + "scale-decode-derive", + "scale-type-resolver", + "smallvec", +] + +[[package]] +name = "scale-decode-derive" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ed9401effa946b493f9f84dc03714cca98119b230497df6f3df6b84a2b03648" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "scale-encode" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f9271284d05d0749c40771c46180ce89905fd95aa72a2a2fddb4b7c0aa424db" +dependencies = [ + "derive_more 1.0.0", + "parity-scale-codec", + "primitive-types 0.13.1", + "scale-bits", + "scale-encode-derive", + "scale-type-resolver", + "smallvec", +] + +[[package]] +name = "scale-encode-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "102fbc6236de6c53906c0b262f12c7aa69c2bdc604862c12728f5f4d370bc137" +dependencies = [ + "darling", + "proc-macro-crate 3.1.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "scale-info" version = "2.11.6" @@ -12629,6 +13590,49 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "scale-type-resolver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0cded6518aa0bd6c1be2b88ac81bf7044992f0f154bfbabd5ad34f43512abcb" +dependencies = [ + "scale-info", + "smallvec", +] + +[[package]] +name = "scale-typegen" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc4c70c7fea2eef1740f0081d3fe385d8bee1eef11e9272d3bec7dc8e5438e0" +dependencies = [ + "proc-macro2", + "quote", + "scale-info", + "syn 2.0.90", + "thiserror 1.0.69", +] + +[[package]] +name = "scale-value" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e0ef2a0ee1e02a69ada37feb87ea1616ce9808aca072befe2d3131bf28576e" +dependencies = [ + "base58", + "blake2 0.10.6", + "derive_more 1.0.0", + "either", + "parity-scale-codec", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-type-resolver", + "serde", + "yap", +] + [[package]] name = "schannel" version = "0.1.23" @@ -12659,7 +13663,7 @@ dependencies = [ "arrayvec 0.7.4", "curve25519-dalek-ng", "merlin", - "rand_core", + "rand_core 0.6.4", "sha2 0.9.9", "subtle-ng", "zeroize", @@ -12677,13 +13681,19 @@ dependencies = [ "curve25519-dalek", "getrandom_or_panic", "merlin", - "rand_core", + "rand_core 0.6.4", "serde_bytes", "sha2 0.10.8", "subtle 2.5.0", "zeroize", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -12697,28 +13707,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" [[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", -] - -[[package]] -name = "sctp-proto" -version = "0.2.2" +name = "scrypt" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6220f78bb44c15f326b0596113305f6101097a18755d53727a575c97e09fb24" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" dependencies = [ - "bytes", - "crc", - "fxhash", - "log", - "rand", - "slab", - "thiserror", + "password-hash", + "pbkdf2", + "salsa20", + "sha2 0.10.8", ] [[package]] @@ -12745,13 +13742,42 @@ dependencies = [ "libc", ] +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "secp256k1-sys 0.8.2", +] + [[package]] name = "secp256k1" version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ - "secp256k1-sys", + "secp256k1-sys 0.9.2", +] + +[[package]] +name = "secp256k1" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" +dependencies = [ + "bitcoin_hashes 0.14.0", + "rand 0.8.5", + "secp256k1-sys 0.10.1", +] + +[[package]] +name = "secp256k1-sys" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4473013577ec77b4ee3668179ef1186df3146e2cf2d927bd200974c6fe60fd99" +dependencies = [ + "cc", ] [[package]] @@ -12763,6 +13789,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -12772,6 +13807,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secrecy" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a" +dependencies = [ + "zeroize", +] + [[package]] name = "security-framework" version = "2.10.0" @@ -12779,18 +13823,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "core-foundation-sys", "libc", "num-bigint", "security-framework-sys", ] +[[package]] +name = "security-framework" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.10.1", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + [[package]] name = "security-framework-sys" -version = "2.10.0" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -12802,7 +13859,16 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" dependencies = [ - "semver-parser", + "semver-parser 0.7.0", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser 0.10.3", ] [[package]] @@ -12821,17 +13887,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] -name = "send_wrapper" -version = "0.6.0" +name = "semver-parser" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] [[package]] name = "serde" -version = "1.0.216" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] @@ -12844,11 +13914,20 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + [[package]] name = "serde_derive" -version = "1.0.216" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -12899,18 +13978,6 @@ dependencies = [ "opaque-debug 0.3.1", ] -[[package]] -name = "sha-1" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", - "sha1-asm", -] - [[package]] name = "sha1" version = "0.10.6" @@ -12922,15 +13989,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "sha1-asm" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "286acebaf8b67c1130aedffad26f594eff0c1292389158135327d2e23aed582b" -dependencies = [ - "cc", -] - [[package]] name = "sha2" version = "0.9.9" @@ -12965,6 +14023,16 @@ dependencies = [ "keccak", ] +[[package]] +name = "sha3-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +dependencies = [ + "cc", + "cfg-if", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -12996,7 +14064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -13014,11 +14082,11 @@ dependencies = [ [[package]] name = "simple-dns" -version = "0.5.7" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae9a3fcdadafb6d97f4c0e007e4247b114ee0f119f650c3cbf3a8b3a1479694" +checksum = "dee851d0e5e7af3721faea1843e8015e820a234f81fda3dea9247e15bac9a86a" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.10.0", ] [[package]] @@ -13033,6 +14101,12 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "slab" version = "0.4.9" @@ -13050,8 +14124,8 @@ checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "slot-range-helper" -version = "15.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "17.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "enumn", "parity-scale-codec", @@ -13070,9 +14144,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "smol" @@ -13082,15 +14156,32 @@ checksum = "13f2b548cd8447f8de0fdf1c592929f70f4fc7039a05e47404b0d096ec6987a1" dependencies = [ "async-channel 1.9.0", "async-executor", - "async-fs", + "async-fs 1.6.0", "async-io 1.13.0", "async-lock 2.8.0", - "async-net", - "async-process", + "async-net 1.8.0", + "async-process 1.8.1", "blocking", "futures-lite 1.13.0", ] +[[package]] +name = "smol" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33bd3e260892199c3ccfc487c88b2da2265080acb316cd920da72fdfd7c599f" +dependencies = [ + "async-channel 2.5.0", + "async-executor", + "async-fs 2.2.0", + "async-io 2.3.2", + "async-lock 3.3.0", + "async-net 2.0.0", + "async-process 2.5.0", + "blocking", + "futures-lite 2.3.0", +] + [[package]] name = "smoldot" version = "0.11.0" @@ -13100,26 +14191,80 @@ dependencies = [ "arrayvec 0.7.4", "async-lock 2.8.0", "atomic-take", - "base64 0.21.7", + "base64 0.21.7", + "bip39", + "blake2-rfc", + "bs58", + "chacha20", + "crossbeam-queue", + "derive_more 0.99.17", + "ed25519-zebra", + "either", + "event-listener 2.5.3", + "fnv", + "futures-lite 1.13.0", + "futures-util", + "hashbrown 0.14.5", + "hex", + "hmac 0.12.1", + "itertools 0.11.0", + "libsecp256k1", + "merlin", + "no-std-net", + "nom", + "num-bigint", + "num-rational", + "num-traits", + "pbkdf2", + "pin-project", + "poly1305", + "rand 0.8.5", + "rand_chacha 0.3.1", + "ruzstd 0.4.0", + "schnorrkel 0.10.2", + "serde", + "serde_json", + "sha2 0.10.8", + "sha3", + "siphasher 0.3.11", + "slab", + "smallvec", + "soketto 0.7.1", + "twox-hash", + "wasmi 0.31.2", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "smoldot" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "966e72d77a3b2171bb7461d0cb91f43670c63558c62d7cf42809cae6c8b6b818" +dependencies = [ + "arrayvec 0.7.4", + "async-lock 3.3.0", + "atomic-take", + "base64 0.22.1", "bip39", "blake2-rfc", - "bs58 0.5.1", + "bs58", "chacha20", "crossbeam-queue", "derive_more 0.99.17", "ed25519-zebra", "either", - "event-listener 2.5.3", + "event-listener 5.3.0", "fnv", - "futures-lite 1.13.0", + "futures-lite 2.3.0", "futures-util", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", "hmac 0.12.1", - "itertools 0.11.0", + "itertools 0.13.0", + "libm", "libsecp256k1", "merlin", - "no-std-net", "nom", "num-bigint", "num-rational", @@ -13127,20 +14272,20 @@ dependencies = [ "pbkdf2", "pin-project", "poly1305", - "rand", - "rand_chacha", - "ruzstd", - "schnorrkel 0.10.2", + "rand 0.8.5", + "rand_chacha 0.3.1", + "ruzstd 0.6.0", + "schnorrkel 0.11.4", "serde", "serde_json", "sha2 0.10.8", "sha3", - "siphasher", + "siphasher 1.0.1", "slab", "smallvec", - "soketto 0.7.1", + "soketto 0.8.1", "twox-hash", - "wasmi", + "wasmi 0.32.3", "x25519-dalek", "zeroize", ] @@ -13162,7 +14307,7 @@ dependencies = [ "futures-channel", "futures-lite 1.13.0", "futures-util", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", "itertools 0.11.0", "log", @@ -13170,14 +14315,50 @@ dependencies = [ "no-std-net", "parking_lot 0.12.3", "pin-project", - "rand", - "rand_chacha", + "rand 0.8.5", + "rand_chacha 0.3.1", + "serde", + "serde_json", + "siphasher 0.3.11", + "slab", + "smol 1.3.0", + "smoldot 0.11.0", + "zeroize", +] + +[[package]] +name = "smoldot-light" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a33b06891f687909632ce6a4e3fd7677b24df930365af3d0bcb078310129f3f" +dependencies = [ + "async-channel 2.5.0", + "async-lock 3.3.0", + "base64 0.22.1", + "blake2-rfc", + "bs58", + "derive_more 0.99.17", + "either", + "event-listener 5.3.0", + "fnv", + "futures-channel", + "futures-lite 2.3.0", + "futures-util", + "hashbrown 0.14.5", + "hex", + "itertools 0.13.0", + "log", + "lru 0.12.5", + "parking_lot 0.12.3", + "pin-project", + "rand 0.8.5", + "rand_chacha 0.3.1", "serde", "serde_json", - "siphasher", + "siphasher 1.0.1", "slab", - "smol", - "smoldot", + "smol 2.0.2", + "smoldot 0.18.0", "zeroize", ] @@ -13197,9 +14378,9 @@ dependencies = [ "blake2 0.10.6", "chacha20poly1305", "curve25519-dalek", - "rand_core", + "rand_core 0.6.4", "ring 0.17.8", - "rustc_version", + "rustc_version 0.4.0", "sha2 0.10.8", "subtle 2.5.0", ] @@ -13216,14 +14397,24 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + [[package]] name = "soketto" version = "0.7.1" @@ -13235,8 +14426,8 @@ dependencies = [ "futures", "httparse", "log", - "rand", - "sha-1 0.9.8", + "rand 0.8.5", + "sha-1", ] [[package]] @@ -13251,14 +14442,14 @@ dependencies = [ "http 1.2.0", "httparse", "log", - "rand", + "rand 0.8.5", "sha1", ] [[package]] name = "sp-api" -version = "34.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "36.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "docify", "hash-db", @@ -13274,13 +14465,13 @@ dependencies = [ "sp-state-machine", "sp-trie", "sp-version", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sp-api-proc-macro" -version = "20.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "22.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "Inflector", "blake2 0.10.6", @@ -13293,8 +14484,8 @@ dependencies = [ [[package]] name = "sp-application-crypto" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "scale-info", @@ -13305,8 +14496,8 @@ dependencies = [ [[package]] name = "sp-arithmetic" -version = "26.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "26.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "docify", "integer-sqrt", @@ -13319,8 +14510,8 @@ dependencies = [ [[package]] name = "sp-authority-discovery" -version = "34.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "36.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "scale-info", @@ -13331,8 +14522,8 @@ dependencies = [ [[package]] name = "sp-block-builder" -version = "34.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "36.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "sp-api", "sp-inherents", @@ -13341,42 +14532,43 @@ dependencies = [ [[package]] name = "sp-blockchain" -version = "37.0.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "futures", "parity-scale-codec", "parking_lot 0.12.3", "schnellru", + "serde", + "serde_json", "sp-api", "sp-consensus", "sp-core", "sp-database", "sp-runtime", "sp-state-machine", - "thiserror", + "thiserror 1.0.69", "tracing", ] [[package]] name = "sp-consensus" -version = "0.40.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.42.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "futures", "log", - "sp-core", "sp-inherents", "sp-runtime", "sp-state-machine", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sp-consensus-aura" -version = "0.40.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.42.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "parity-scale-codec", @@ -13391,8 +14583,8 @@ dependencies = [ [[package]] name = "sp-consensus-babe" -version = "0.40.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.42.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "parity-scale-codec", @@ -13409,29 +14601,28 @@ dependencies = [ [[package]] name = "sp-consensus-beefy" -version = "22.1.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "24.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "lazy_static", "parity-scale-codec", "scale-info", "serde", "sp-api", "sp-application-crypto", "sp-core", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", "sp-io", "sp-keystore", "sp-mmr-primitives", "sp-runtime", "sp-weights", - "strum 0.26.2", + "strum 0.26.3", ] [[package]] name = "sp-consensus-grandpa" -version = "21.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "finality-grandpa", "log", @@ -13447,8 +14638,8 @@ dependencies = [ [[package]] name = "sp-consensus-slots" -version = "0.40.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.42.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "scale-info", @@ -13458,14 +14649,15 @@ dependencies = [ [[package]] name = "sp-core" -version = "34.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "36.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ + "ark-vrf", "array-bytes", "bitflags 1.3.2", "blake2 0.10.6", "bounded-collections", - "bs58 0.5.1", + "bs58", "dyn-clonable", "ed25519-zebra", "futures", @@ -13481,14 +14673,14 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", "paste", - "primitive-types", - "rand", + "primitive-types 0.13.1", + "rand 0.8.5", "scale-info", "schnorrkel 0.11.4", - "secp256k1", - "secrecy", + "secp256k1 0.28.2", + "secrecy 0.8.0", "serde", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", "sp-debug-derive", "sp-externalities", "sp-runtime-interface", @@ -13496,7 +14688,7 @@ dependencies = [ "sp-storage", "ss58-registry", "substrate-bip39", - "thiserror", + "thiserror 1.0.69", "tracing", "w3f-bls", "zeroize", @@ -13505,7 +14697,21 @@ dependencies = [ [[package]] name = "sp-crypto-hashing" version = "0.1.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9927a7f81334ed5b8a98a4a978c81324d12bd9713ec76b5c68fd410174c5eb" +dependencies = [ + "blake2b_simd", + "byteorder", + "digest 0.10.7", + "sha2 0.10.8", + "sha3", + "twox-hash", +] + +[[package]] +name = "sp-crypto-hashing" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "blake2b_simd", "byteorder", @@ -13518,17 +14724,17 @@ dependencies = [ [[package]] name = "sp-crypto-hashing-proc-macro" version = "0.1.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "quote", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", "syn 2.0.90", ] [[package]] name = "sp-database" version = "10.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "kvdb", "parking_lot 0.12.3", @@ -13537,7 +14743,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "proc-macro2", "quote", @@ -13546,8 +14752,8 @@ dependencies = [ [[package]] name = "sp-externalities" -version = "0.29.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.30.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "environmental", "parity-scale-codec", @@ -13556,8 +14762,8 @@ dependencies = [ [[package]] name = "sp-genesis-builder" -version = "0.15.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.17.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "scale-info", @@ -13568,21 +14774,21 @@ dependencies = [ [[package]] name = "sp-inherents" -version = "34.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "36.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "impl-trait-for-tuples", "parity-scale-codec", "scale-info", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sp-io" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "40.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bytes", "docify", @@ -13590,11 +14796,11 @@ dependencies = [ "libsecp256k1", "log", "parity-scale-codec", - "polkavm-derive", + "polkavm-derive 0.18.0", "rustversion", - "secp256k1", + "secp256k1 0.28.2", "sp-core", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", "sp-externalities", "sp-keystore", "sp-runtime-interface", @@ -13607,18 +14813,18 @@ dependencies = [ [[package]] name = "sp-keyring" -version = "39.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "41.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "sp-core", "sp-runtime", - "strum 0.26.2", + "strum 0.26.3", ] [[package]] name = "sp-keystore" -version = "0.40.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.42.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", @@ -13629,26 +14835,26 @@ dependencies = [ [[package]] name = "sp-maybe-compressed-blob" version = "11.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "thiserror", + "thiserror 1.0.69", "zstd 0.12.4", ] [[package]] name = "sp-metadata-ir" -version = "0.7.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.10.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ - "frame-metadata", + "frame-metadata 20.0.0", "parity-scale-codec", "scale-info", ] [[package]] name = "sp-mixnet" -version = "0.12.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.14.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "scale-info", @@ -13658,8 +14864,8 @@ dependencies = [ [[package]] name = "sp-mmr-primitives" -version = "34.1.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "36.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "log", "parity-scale-codec", @@ -13670,13 +14876,13 @@ dependencies = [ "sp-core", "sp-debug-derive", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sp-npos-elections" -version = "34.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "36.2.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "scale-info", @@ -13688,8 +14894,8 @@ dependencies = [ [[package]] name = "sp-offchain" -version = "34.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "36.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "sp-api", "sp-core", @@ -13698,18 +14904,17 @@ dependencies = [ [[package]] name = "sp-panic-handler" -version = "13.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "13.0.2" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "backtrace", - "lazy_static", "regex", ] [[package]] name = "sp-rpc" -version = "32.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "34.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "rustc-hash 1.1.0", "serde", @@ -13718,9 +14923,10 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "39.0.5" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "41.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ + "binary-merkle-tree", "docify", "either", "hash256-std-hasher", @@ -13729,7 +14935,7 @@ dependencies = [ "num-traits", "parity-scale-codec", "paste", - "rand", + "rand 0.8.5", "scale-info", "serde", "simple-mermaid", @@ -13738,20 +14944,22 @@ dependencies = [ "sp-core", "sp-io", "sp-std", + "sp-trie", "sp-weights", "tracing", + "tuplex", ] [[package]] name = "sp-runtime-interface" -version = "28.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "29.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", - "polkavm-derive", - "primitive-types", + "polkavm-derive 0.18.0", + "primitive-types 0.13.1", "sp-externalities", "sp-runtime-interface-proc-macro", "sp-std", @@ -13764,7 +14972,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "Inflector", "expander", @@ -13776,8 +14984,8 @@ dependencies = [ [[package]] name = "sp-session" -version = "36.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "38.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "scale-info", @@ -13790,8 +14998,8 @@ dependencies = [ [[package]] name = "sp-staking" -version = "36.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "38.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -13803,57 +15011,57 @@ dependencies = [ [[package]] name = "sp-state-machine" -version = "0.43.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.45.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "hash-db", "log", "parity-scale-codec", "parking_lot 0.12.3", - "rand", + "rand 0.8.5", "smallvec", "sp-core", "sp-externalities", "sp-panic-handler", "sp-trie", - "thiserror", + "thiserror 1.0.69", "tracing", - "trie-db", + "trie-db 0.30.0", ] [[package]] name = "sp-statement-store" -version = "18.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "20.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "aes-gcm", "curve25519-dalek", "ed25519-dalek", "hkdf", "parity-scale-codec", - "rand", + "rand 0.8.5", "scale-info", "sha2 0.10.8", "sp-api", "sp-application-crypto", "sp-core", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", "sp-externalities", "sp-runtime", "sp-runtime-interface", - "thiserror", + "thiserror 1.0.69", "x25519-dalek", ] [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" [[package]] name = "sp-storage" -version = "21.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "22.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "impl-serde", "parity-scale-codec", @@ -13864,20 +15072,20 @@ dependencies = [ [[package]] name = "sp-timestamp" -version = "34.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "36.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "parity-scale-codec", "sp-inherents", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sp-tracing" -version = "17.0.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "17.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", "tracing", @@ -13887,8 +15095,8 @@ dependencies = [ [[package]] name = "sp-transaction-pool" -version = "34.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "36.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "sp-api", "sp-runtime", @@ -13896,8 +15104,8 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" -version = "34.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "36.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "async-trait", "parity-scale-codec", @@ -13910,31 +15118,30 @@ dependencies = [ [[package]] name = "sp-trie" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "ahash", "hash-db", - "lazy_static", "memory-db", "nohash-hasher", "parity-scale-codec", "parking_lot 0.12.3", - "rand", + "rand 0.8.5", "scale-info", "schnellru", "sp-core", "sp-externalities", - "thiserror", + "thiserror 1.0.69", "tracing", - "trie-db", + "trie-db 0.30.0", "trie-root", ] [[package]] name = "sp-version" -version = "37.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "39.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "impl-serde", "parity-scale-codec", @@ -13945,15 +15152,16 @@ dependencies = [ "sp-runtime", "sp-std", "sp-version-proc-macro", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sp-version-proc-macro" -version = "14.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "15.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "parity-scale-codec", + "proc-macro-warning", "proc-macro2", "quote", "syn 2.0.90", @@ -13962,7 +15170,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "21.0.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -13973,8 +15181,8 @@ dependencies = [ [[package]] name = "sp-weights" -version = "31.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "31.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "bounded-collections", "parity-scale-codec", @@ -14039,8 +15247,8 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "staging-parachain-info" -version = "0.17.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.20.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -14052,13 +15260,15 @@ dependencies = [ [[package]] name = "staging-xcm" -version = "14.2.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "16.2.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "array-bytes", "bounded-collections", - "derivative", + "derive-where", "environmental", + "frame-support", + "hex-literal", "impl-trait-for-tuples", "log", "parity-scale-codec", @@ -14071,30 +15281,32 @@ dependencies = [ [[package]] name = "staging-xcm-builder" -version = "17.0.3" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "20.1.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ + "environmental", "frame-support", "frame-system", "impl-trait-for-tuples", - "log", "pallet-asset-conversion", "pallet-transaction-payment", "parity-scale-codec", "polkadot-parachain-primitives", "scale-info", "sp-arithmetic", + "sp-core", "sp-io", "sp-runtime", "sp-weights", "staging-xcm", "staging-xcm-executor", + "tracing", ] [[package]] name = "staging-xcm-executor" -version = "17.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "19.1.3" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "environmental", "frame-benchmarking", @@ -14124,7 +15336,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a2a1c578e98c1c16fc3b8ec1328f7659a500737d7a0c6d625e73e830ff9c1f6" dependencies = [ "bitflags 1.3.2", - "cfg_aliases", + "cfg_aliases 0.1.1", "libc", "parking_lot 0.11.2", "parking_lot_core 0.8.6", @@ -14138,7 +15350,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70a2595fc3aa78f2d0e45dd425b22282dd863273761cc77780914b2cf3003acf" dependencies = [ - "cfg_aliases", + "cfg_aliases 0.1.1", "memchr", "proc-macro2", "quote", @@ -14146,23 +15358,13 @@ dependencies = [ ] [[package]] -name = "str0m" -version = "0.5.1" +name = "string-interner" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6706347e49b13373f7ddfafad47df7583ed52083d6fc8a594eb2c80497ef959d" +checksum = "1c6a0d765f5807e98a091107bae0a56ea3799f66a5de47b2c84c94a39c09974e" dependencies = [ - "combine", - "crc", - "fastrand 2.0.2", - "hmac 0.12.1", - "once_cell", - "openssl", - "openssl-sys", - "sctp-proto", - "serde", - "sha-1 0.10.1", - "thiserror", - "tracing", + "cfg-if", + "hashbrown 0.14.5", ] [[package]] @@ -14179,11 +15381,11 @@ checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ - "strum_macros 0.26.2", + "strum_macros 0.26.4", ] [[package]] @@ -14201,11 +15403,11 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", @@ -14215,7 +15417,7 @@ dependencies = [ [[package]] name = "substrate-bip39" version = "0.6.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "hmac 0.12.1", "pbkdf2", @@ -14224,15 +15426,28 @@ dependencies = [ "zeroize", ] +[[package]] +name = "substrate-bn" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" +dependencies = [ + "byteorder", + "crunchy", + "lazy_static", + "rand 0.8.5", + "rustc-hex", +] + [[package]] name = "substrate-build-script-utils" version = "11.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" [[package]] name = "substrate-frame-rpc-system" -version = "39.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "44.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "docify", "frame-system-rpc-runtime-api", @@ -14251,22 +15466,22 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" -version = "0.17.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.17.3" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "http-body-util", "hyper 1.5.1", "hyper-util", "log", "prometheus", - "thiserror", + "thiserror 1.0.69", "tokio", ] [[package]] name = "substrate-state-trie-migration-rpc" -version = "38.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "43.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -14277,13 +15492,13 @@ dependencies = [ "sp-runtime", "sp-state-machine", "sp-trie", - "trie-db", + "trie-db 0.30.0", ] [[package]] name = "substrate-wasm-builder" -version = "24.0.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "26.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "build-helper", "cargo_metadata", @@ -14291,9 +15506,10 @@ dependencies = [ "filetime", "jobserver", "parity-wasm", - "polkavm-linker", + "polkavm-linker 0.18.0", + "shlex", "sp-maybe-compressed-blob", - "strum 0.26.2", + "strum 0.26.3", "tempfile", "toml 0.8.12", "walkdir", @@ -14318,6 +15534,175 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" +[[package]] +name = "subxt" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c17d7ec2359d33133b63c97e28c8b7cd3f0a5bc6ce567ae3aef9d9e85be3433" +dependencies = [ + "async-trait", + "derive-where", + "either", + "frame-metadata 17.0.0", + "futures", + "hex", + "impl-serde", + "jsonrpsee", + "parity-scale-codec", + "polkadot-sdk", + "primitive-types 0.13.1", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-value", + "serde", + "serde_json", + "subxt-core", + "subxt-lightclient", + "subxt-macro", + "subxt-metadata", + "thiserror 1.0.69", + "tokio", + "tokio-util", + "tracing", + "url", + "web-time", +] + +[[package]] +name = "subxt-codegen" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6550ef451c77db6e3bc7c56fb6fe1dca9398a2c8fc774b127f6a396a769b9c5b" +dependencies = [ + "heck 0.5.0", + "parity-scale-codec", + "proc-macro2", + "quote", + "scale-info", + "scale-typegen", + "subxt-metadata", + "syn 2.0.90", + "thiserror 1.0.69", +] + +[[package]] +name = "subxt-core" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7a1bc6c9c1724971636a66e3225a7253cdb35bb6efb81524a6c71c04f08c59" +dependencies = [ + "base58", + "blake2 0.10.6", + "derive-where", + "frame-decode", + "frame-metadata 17.0.0", + "hashbrown 0.14.5", + "hex", + "impl-serde", + "keccak-hash", + "parity-scale-codec", + "polkadot-sdk", + "primitive-types 0.13.1", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-value", + "serde", + "serde_json", + "subxt-metadata", + "tracing", +] + +[[package]] +name = "subxt-lightclient" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ebc9131da4d0ba1f7814495b8cc79698798ccd52cacd7bcefe451e415bd945" +dependencies = [ + "futures", + "futures-util", + "serde", + "serde_json", + "smoldot-light 0.16.2", + "thiserror 1.0.69", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "subxt-macro" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7819c5e09aae0319981ee853869f2fcd1fac4db8babd0d004c17161297aadc05" +dependencies = [ + "darling", + "parity-scale-codec", + "proc-macro-error2", + "quote", + "scale-typegen", + "subxt-codegen", + "subxt-utils-fetchmetadata", + "syn 2.0.90", +] + +[[package]] +name = "subxt-metadata" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aacd4e7484fef58deaa2dcb32d94753a864b208a668c0dd0c28be1d8abeeadb2" +dependencies = [ + "frame-decode", + "frame-metadata 17.0.0", + "hashbrown 0.14.5", + "parity-scale-codec", + "polkadot-sdk", + "scale-info", +] + +[[package]] +name = "subxt-signer" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d680352d04665b1e4eb6f9d2a54b800c4d8e1b20478e69be1b7d975b08d9fc34" +dependencies = [ + "base64 0.22.1", + "bip32", + "bip39", + "cfg-if", + "crypto_secretbox", + "hex", + "hmac 0.12.1", + "keccak-hash", + "parity-scale-codec", + "pbkdf2", + "polkadot-sdk", + "regex", + "schnorrkel 0.11.4", + "scrypt", + "secp256k1 0.30.0", + "secrecy 0.10.3", + "serde", + "serde_json", + "sha2 0.10.8", + "subxt-core", + "zeroize", +] + +[[package]] +name = "subxt-utils-fetchmetadata" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3c53bc3eeaacc143a2f29ace4082edd2edaccab37b69ad20befba9fb00fdb3d" +dependencies = [ + "hex", + "parity-scale-codec", + "thiserror 1.0.69", +] + [[package]] name = "syn" version = "1.0.109" @@ -14337,7 +15722,19 @@ checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", - "unicode-ident", + "unicode-ident", +] + +[[package]] +name = "syn-solidity" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab4e6eed052a117409a1a744c8bda9c3ea6934597cf7419f791cb7d590871c4c" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.90", ] [[package]] @@ -14370,7 +15767,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys", ] @@ -14384,6 +15781,12 @@ dependencies = [ "libc", ] +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "tap" version = "1.0.1" @@ -14468,8 +15871,8 @@ dependencies = [ [[package]] name = "test-utils" -version = "1.1.2" -source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2409-patch22#7a11f3e2cd9a2dac1c1eca6ee7b5eba5d17e72a3" +version = "1.1.3" +source = "git+https://github.com/galacticcouncil/hydration-node?branch=polkadot-stable2503-11-snek#59ae6bfb45c4e37c38c95eead4c9f29e26bc478b" dependencies = [ "frame-system", "pretty_assertions", @@ -14481,7 +15884,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl 2.0.17", ] [[package]] @@ -14515,6 +15927,17 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "thousands" version = "0.2.0" @@ -14540,19 +15963,6 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "thrift" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b82ca8f46f95b3ce96081fe3dd89160fdea970c254bb72925255d1b62aae692e" -dependencies = [ - "byteorder", - "integer-encoding", - "log", - "ordered-float", - "threadpool", -] - [[package]] name = "tikv-jemalloc-ctl" version = "0.5.4" @@ -14614,6 +16024,16 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -14631,59 +16051,47 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.8", + "socket2 0.6.1", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", "syn 2.0.90", ] -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.11", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls 0.23.20", + "rustls", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -14693,24 +16101,25 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.20.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" dependencies = [ "futures-util", "log", - "rustls 0.21.11", - "rustls-native-certs 0.6.3", + "rustls", + "rustls-native-certs 0.8.2", + "rustls-pki-types", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls", "tungstenite", ] [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", @@ -14756,7 +16165,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.12.0", "toml_datetime", "winnow 0.5.40", ] @@ -14767,7 +16176,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.12.0", "toml_datetime", "winnow 0.5.40", ] @@ -14778,7 +16187,7 @@ version = "0.22.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.12.0", "serde", "serde_spanned", "toml_datetime", @@ -14806,7 +16215,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.10.0", "bytes", "http 1.2.0", "http-body 1.0.1", @@ -14873,8 +16282,8 @@ dependencies = [ [[package]] name = "tracing-gum" -version = "16.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "19.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "coarsetime", "polkadot-primitives", @@ -14885,7 +16294,7 @@ dependencies = [ [[package]] name = "tracing-gum-proc-macro" version = "5.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "expander", "proc-macro-crate 3.1.0", @@ -14938,84 +16347,24 @@ dependencies = [ ] [[package]] -name = "trie-root" -version = "0.18.0" +name = "trie-db" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +checksum = "6c0670ab45a6b7002c7df369fee950a27cf29ae0474343fd3a15aa15f691e7a6" dependencies = [ "hash-db", -] - -[[package]] -name = "trust-dns-proto" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26" -dependencies = [ - "async-trait", - "cfg-if", - "data-encoding", - "enum-as-inner 0.5.1", - "futures-channel", - "futures-io", - "futures-util", - "idna 0.2.3", - "ipnet", - "lazy_static", - "rand", - "smallvec", - "socket2 0.4.10", - "thiserror", - "tinyvec", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "trust-dns-proto" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3119112651c157f4488931a01e586aa459736e9d6046d3bd9105ffb69352d374" -dependencies = [ - "async-trait", - "cfg-if", - "data-encoding", - "enum-as-inner 0.6.0", - "futures-channel", - "futures-io", - "futures-util", - "idna 0.4.0", - "ipnet", - "once_cell", - "rand", + "log", + "rustc-hex", "smallvec", - "thiserror", - "tinyvec", - "tokio", - "tracing", - "url", ] [[package]] -name = "trust-dns-resolver" -version = "0.23.2" +name = "trie-root" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a3e6c3aff1718b3c73e395d1f35202ba2ffa847c6a62eea0db8fb4cfe30be6" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" dependencies = [ - "cfg-if", - "futures-util", - "ipconfig", - "lru-cache", - "once_cell", - "parking_lot 0.12.3", - "rand", - "resolv-conf", - "smallvec", - "thiserror", - "tokio", - "tracing", - "trust-dns-proto 0.23.2", + "hash-db", ] [[package]] @@ -15032,24 +16381,30 @@ checksum = "f4f195fd851901624eee5a58c4bb2b4f06399148fcd0ed336e6f1cb60a9881df" [[package]] name = "tungstenite" -version = "0.20.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" dependencies = [ - "byteorder", "bytes", "data-encoding", - "http 0.2.12", + "http 1.2.0", "httparse", "log", - "rand", - "rustls 0.21.11", + "rand 0.9.2", + "rustls", + "rustls-pki-types", "sha1", - "thiserror", + "thiserror 2.0.17", "url", "utf-8", ] +[[package]] +name = "tuplex" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "676ac81d5454c4dcf37955d34fa8626ede3490f744b86ca14a7b90168d2a08aa" + [[package]] name = "twox-hash" version = "1.6.3" @@ -15058,7 +16413,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", "digest 0.10.7", - "rand", + "rand 0.8.5", "static_assertions", ] @@ -15087,10 +16442,22 @@ dependencies = [ ] [[package]] -name = "unicode-bidi" -version = "0.3.15" +name = "uint" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unarray" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" @@ -15107,12 +16474,24 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + [[package]] name = "unicode-width" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + [[package]] name = "unicode-xid" version = "0.2.4" @@ -15135,7 +16514,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" dependencies = [ - "asynchronous-codec", + "asynchronous-codec 0.6.2", "bytes", "futures-io", "futures-util", @@ -15165,12 +16544,12 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna", "percent-encoding", ] @@ -15180,12 +16559,29 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "uuid" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +dependencies = [ + "getrandom 0.3.4", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "valuable" version = "0.1.0" @@ -15217,23 +16613,78 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7335e4c132c28cc43caef6adb339789e599e39adbe78da0c4d547fad48cbc331" dependencies = [ "ark-bls12-377", - "ark-bls12-381", - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-serialize-derive", + "ark-bls12-381 0.4.0", + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-serialize-derive 0.4.2", "arrayref", "constcat", "digest 0.10.7", - "rand", - "rand_chacha", - "rand_core", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_core 0.6.4", "sha2 0.10.8", "sha3", - "thiserror", + "thiserror 1.0.69", "zeroize", ] +[[package]] +name = "w3f-pcs" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbe7a8d5c914b69392ab3b267f679a2e546fe29afaddce47981772ac71bd02e1" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-poly 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "merlin", +] + +[[package]] +name = "w3f-plonk-common" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aca389e494fe08c5c108b512e2328309036ee1c0bc7bdfdb743fef54d448c8c" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-poly 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "getrandom_or_panic", + "rand_core 0.6.4", + "w3f-pcs", +] + +[[package]] +name = "w3f-ring-proof" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a639379402ad51504575dbd258740383291ac8147d3b15859bdf1ea48c677de" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-poly 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "ark-transcript", + "w3f-pcs", + "w3f-plonk-common", +] + +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + [[package]] name = "waker-fn" version = "1.1.1" @@ -15265,6 +16716,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasix" version = "0.12.21" @@ -15276,26 +16736,14 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" -dependencies = [ - "bumpalo", - "log", "once_cell", - "proc-macro2", - "quote", - "syn 2.0.90", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] @@ -15313,9 +16761,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -15323,22 +16771,25 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn 2.0.90", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +dependencies = [ + "unicode-ident", +] [[package]] name = "wasm-instrument" @@ -15360,7 +16811,7 @@ dependencies = [ "strum 0.24.1", "strum_macros 0.24.3", "tempfile", - "thiserror", + "thiserror 1.0.69", "wasm-opt-cxx-sys", "wasm-opt-sys", ] @@ -15413,7 +16864,24 @@ dependencies = [ "smallvec", "spin 0.9.8", "wasmi_arena", - "wasmi_core", + "wasmi_core 0.13.0", + "wasmparser-nostd", +] + +[[package]] +name = "wasmi" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50386c99b9c32bd2ed71a55b6dd4040af2580530fae8bdb9a6576571a80d0cca" +dependencies = [ + "arrayvec 0.7.4", + "multi-stash", + "num-derive", + "num-traits", + "smallvec", + "spin 0.9.8", + "wasmi_collections", + "wasmi_core 0.32.3", "wasmparser-nostd", ] @@ -15423,6 +16891,17 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073" +[[package]] +name = "wasmi_collections" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c128c039340ffd50d4195c3f8ce31aac357f06804cfc494c8b9508d4b30dca4" +dependencies = [ + "ahash", + "hashbrown 0.14.5", + "string-interner", +] + [[package]] name = "wasmi_core" version = "0.13.0" @@ -15435,6 +16914,18 @@ dependencies = [ "paste", ] +[[package]] +name = "wasmi_core" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23b3a7f6c8c3ceeec6b83531ee61f0013c56e51cbf2b14b0f213548b23a4b41" +dependencies = [ + "downcast-rs", + "libm", + "num-traits", + "paste", +] + [[package]] name = "wasmparser" version = "0.102.0" @@ -15527,7 +17018,7 @@ dependencies = [ "log", "object 0.30.4", "target-lexicon", - "thiserror", + "thiserror 1.0.69", "wasmparser", "wasmtime-cranelift-shared", "wasmtime-environ", @@ -15562,7 +17053,7 @@ dependencies = [ "object 0.30.4", "serde", "target-lexicon", - "thiserror", + "thiserror 1.0.69", "wasmparser", "wasmtime-types", ] @@ -15629,7 +17120,7 @@ dependencies = [ "memfd", "memoffset", "paste", - "rand", + "rand 0.8.5", "rustix 0.36.17", "wasmtime-asm-macros", "wasmtime-environ", @@ -15645,7 +17136,7 @@ checksum = "a4f6fffd2a1011887d57f07654dd112791e872e3ff4a2e626aee8059ee17f06f" dependencies = [ "cranelift-entity", "serde", - "thiserror", + "thiserror 1.0.69", "wasmparser", ] @@ -15660,13 +17151,13 @@ dependencies = [ ] [[package]] -name = "webpki" -version = "0.22.4" +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "js-sys", + "wasm-bindgen", ] [[package]] @@ -15686,8 +17177,8 @@ dependencies = [ [[package]] name = "westend-runtime" -version = "18.0.1" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "23.0.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "binary-merkle-tree", "bitvec", @@ -15710,10 +17201,8 @@ dependencies = [ "pallet-balances", "pallet-beefy", "pallet-beefy-mmr", - "pallet-collective", "pallet-conviction-voting", "pallet-delegated-staking", - "pallet-democracy 38.0.0", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", @@ -15723,6 +17212,8 @@ dependencies = [ "pallet-indices", "pallet-membership", "pallet-message-queue", + "pallet-meta-tx", + "pallet-migrations", "pallet-mmr", "pallet-multisig", "pallet-nomination-pools", @@ -15740,7 +17231,7 @@ dependencies = [ "pallet-session", "pallet-session-benchmarking", "pallet-society", - "pallet-staking 38.0.0", + "pallet-staking 40.1.1", "pallet-staking-runtime-api", "pallet-state-trie-migration", "pallet-sudo", @@ -15749,6 +17240,7 @@ dependencies = [ "pallet-transaction-payment-rpc-runtime-api", "pallet-treasury", "pallet-utility", + "pallet-verify-signature", "pallet-vesting", "pallet-whitelist", "pallet-xcm", @@ -15762,7 +17254,6 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "smallvec", "sp-api", "sp-application-crypto", "sp-arithmetic", @@ -15775,6 +17266,7 @@ dependencies = [ "sp-genesis-builder", "sp-inherents", "sp-io", + "sp-keyring", "sp-mmr-primitives", "sp-npos-elections", "sp-offchain", @@ -15794,30 +17286,18 @@ dependencies = [ [[package]] name = "westend-runtime-constants" -version = "17.0.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "20.0.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-support", "polkadot-primitives", - "polkadot-runtime-common", - "smallvec", - "sp-core", - "sp-runtime", - "sp-weights", - "staging-xcm", - "staging-xcm-builder", -] - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix 0.38.34", + "polkadot-runtime-common", + "smallvec", + "sp-core", + "sp-runtime", + "sp-weights", + "staging-xcm", + "staging-xcm-builder", ] [[package]] @@ -15873,10 +17353,32 @@ version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" dependencies = [ - "windows-core", + "windows-core 0.51.1", "windows-targets 0.48.5", ] +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", +] + [[package]] name = "windows-core" version = "0.51.1" @@ -15887,18 +17389,89 @@ dependencies = [ ] [[package]] -name = "windows-sys" -version = "0.42.0" +name = "windows-core" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", ] [[package]] @@ -15928,6 +17501,24 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -15967,13 +17558,39 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.5", "windows_aarch64_msvc 0.52.5", "windows_i686_gnu 0.52.5", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.5", "windows_i686_msvc 0.52.5", "windows_x86_64_gnu 0.52.5", "windows_x86_64_gnullvm 0.52.5", "windows_x86_64_msvc 0.52.5", ] +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -15992,6 +17609,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -16010,6 +17633,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -16028,12 +17657,24 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -16052,6 +17693,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -16070,6 +17717,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -16088,6 +17741,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -16106,6 +17765,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + [[package]] name = "winnow" version = "0.5.40" @@ -16124,6 +17789,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" @@ -16134,6 +17808,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + [[package]] name = "wyz" version = "0.5.1" @@ -16150,63 +17836,62 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ "curve25519-dalek", - "rand_core", + "rand_core 0.6.4", "serde", "zeroize", ] [[package]] name = "x509-parser" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7069fba5b66b9193bd2c5d3d4ff12b839118f6bcbef5328efafafb5395cf63da" +checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" dependencies = [ - "asn1-rs 0.5.2", + "asn1-rs 0.6.2", "data-encoding", - "der-parser 8.2.0", + "der-parser 9.0.0", "lazy_static", "nom", - "oid-registry 0.6.1", + "oid-registry 0.7.1", "rusticata-macros", - "thiserror", + "thiserror 1.0.69", "time", ] [[package]] name = "x509-parser" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" +checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460" dependencies = [ - "asn1-rs 0.6.2", + "asn1-rs 0.7.1", "data-encoding", - "der-parser 9.0.0", + "der-parser 10.0.0", "lazy_static", "nom", - "oid-registry 0.7.1", + "oid-registry 0.8.1", "rusticata-macros", - "thiserror", + "thiserror 2.0.17", "time", ] [[package]] name = "xcm-emulator" -version = "0.16.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.19.3" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "array-bytes", "cumulus-pallet-parachain-system", - "cumulus-pallet-xcmp-queue", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-test-relay-sproof-builder", "frame-support", "frame-system", "impl-trait-for-tuples", - "lazy_static", "log", "pallet-balances", "pallet-message-queue", + "pallet-timestamp", "parachains-common", "parity-scale-codec", "paste", @@ -16215,19 +17900,19 @@ dependencies = [ "polkadot-runtime-parachains", "sp-arithmetic", "sp-core", - "sp-crypto-hashing", + "sp-crypto-hashing 0.1.0 (git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch)", "sp-io", "sp-runtime", - "sp-std", "sp-tracing", "staging-xcm", "staging-xcm-executor", + "xcm-simulator", ] [[package]] name = "xcm-procedural" -version = "10.1.0" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "11.0.2" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "Inflector", "proc-macro2", @@ -16237,8 +17922,8 @@ dependencies = [ [[package]] name = "xcm-runtime-apis" -version = "0.4.2" -source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409-patch22#c3fe9c0219ebab4bc7b7c14a0b93da619a6cca28" +version = "0.7.1" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" dependencies = [ "frame-support", "parity-scale-codec", @@ -16249,6 +17934,27 @@ dependencies = [ "staging-xcm-executor", ] +[[package]] +name = "xcm-simulator" +version = "20.1.0" +source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=polkadot-stable2503-11-patch#e5734fcc2dec3e01fa70e27d4562098a4845e55e" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "paste", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "polkadot-primitives", + "polkadot-runtime-parachains", + "scale-info", + "sp-io", + "sp-runtime", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", +] + [[package]] name = "xml-rs" version = "0.8.24" @@ -16275,8 +17981,24 @@ dependencies = [ "nohash-hasher", "parking_lot 0.12.3", "pin-project", - "rand", + "rand 0.8.5", + "static_assertions", +] + +[[package]] +name = "yamux" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deab71f2e20691b4728b349c6cee8fc7223880fa67b6b4f92225ec32225447e5" +dependencies = [ + "futures", + "log", + "nohash-hasher", + "parking_lot 0.12.3", + "pin-project", + "rand 0.9.2", "static_assertions", + "web-time", ] [[package]] @@ -16285,6 +18007,12 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "yap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4524214bc4629eba08d78ceb1d6507070cc0bcbbed23af74e19e6e924a24cf" + [[package]] name = "yasna" version = "0.5.2" @@ -16294,6 +18022,29 @@ dependencies = [ "time", ] +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure 0.13.1", +] + [[package]] name = "zerocopy" version = "0.7.32" @@ -16314,6 +18065,27 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure 0.13.1", +] + [[package]] name = "zeroize" version = "1.8.1" @@ -16334,6 +18106,39 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "zstd" version = "0.11.2+zstd.1.5.2" diff --git a/Cargo.toml b/Cargo.toml index 839e51ab080..2f1720dd3c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,12 +3,19 @@ panic = 'unwind' [workspace] members = [ + 'math', 'node', 'runtime/basilisk', 'pallets/marketplace', 'pallets/asset-registry', + 'pallets/ema-oracle', + 'pallets/lbp', + 'pallets/route-executor', + 'pallets/transaction-multi-payment', + 'pallets/xyk', 'pallets/xyk-liquidity-mining', 'pallets/xyk-liquidity-mining/benchmarking', + 'runtime/adapters', 'integration-tests', ] @@ -18,565 +25,575 @@ resolver = '2' scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } serde = { version = "1.0.209", features = ["derive"], default-features = false } -primitive-types = { version = "0.12.1", default-features = false } +primitive-types = { version = "0.13.1", default-features = false } log = "0.4.20" hex-literal = "0.4.1" pretty_assertions = "1.4.0" static_assertions = "1.1.0" test-case = "3.1.0" +proptest = "1.0.40" +impl-trait-for-tuples = "0.2.2" jsonrpsee = { version = "0.24.3", features = ["server", "macros"] } serde_json = { version = "1.0.117", default-features = false } clap = { version = "4.1.8", features = [ "derive" ] } -futures = "0.3.25" +futures = "0.3.31" trie-db = "0.29.1" lazy_static = "1.4.0" smallvec = "1.9.0" +rug = { version = "1.17.0", features = ["num-traits"] } +num-traits = { default-features = false, version = "0.2.14" } +rand = { version = "0.8.5", default-features = false } +frame-metadata = { version = "16.0.0", default-features = false, features = ["current", "decode"] } + +basilisk-math = { path = "math", default-features = false } +basilisk-adapters = { path = "runtime/adapters", default-features = false } basilisk-runtime = { path = "runtime/basilisk", default-features = false } +primitives = { path = "primitives", default-features = false } +basilisk-traits = { path = "traits", default-features = false } pallet-marketplace = { path = "pallets/marketplace", default-features = false} pallet-asset-registry = { path = "pallets/asset-registry", default-features = false} +pallet-ema-oracle = { path = "pallets/ema-oracle", default-features = false} +pallet-lbp = { path = "pallets/lbp", default-features = false } +pallet-route-executor = { path = "pallets/route-executor", default-features = false } +pallet-transaction-multi-payment = { path = "pallets/transaction-multi-payment", default-features = false } +pallet-xyk = { path = "pallets/xyk", default-features = false } pallet-xyk-liquidity-mining = { path = "pallets/xyk-liquidity-mining", default-features = false} pallet-xyk-liquidity-mining-benchmarking = { path = "pallets/xyk-liquidity-mining/benchmarking", default-features = false} -hydra-dx-math = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -hydradx-traits = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -hydradx-adapters = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -pallet-relaychain-info = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -pallet-transaction-multi-payment = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -pallet-nft = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -pallet-currencies = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -pallet-transaction-pause = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -pallet-route-executor = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -pallet-ema-oracle = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -pallet-duster = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -pallet-collator-rewards = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -test-utils = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -pallet-lbp = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -pallet-xyk = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -pallet-liquidity-mining = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -pallet-broadcast = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -pallet-staking = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -warehouse-liquidity-mining = { package="pallet-liquidity-mining", git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22", default-features = false } -hydra-dx-build-script-utils = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2409-patch22" } +hydra-dx-math = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2503-11-snek", default-features = false } +hydradx-traits = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2503-11-snek", default-features = false } +pallet-relaychain-info = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2503-11-snek", default-features = false } +pallet-nft = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2503-11-snek", default-features = false } +pallet-currencies = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2503-11-snek", default-features = false } +pallet-transaction-pause = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2503-11-snek", default-features = false } +pallet-duster = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2503-11-snek", default-features = false } +pallet-collator-rewards = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2503-11-snek", default-features = false } +test-utils = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2503-11-snek", default-features = false } +pallet-liquidity-mining = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2503-11-snek", default-features = false } +pallet-broadcast = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2503-11-snek", default-features = false } +pallet-staking = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2503-11-snek", default-features = false } +warehouse-liquidity-mining = { package="pallet-liquidity-mining", git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2503-11-snek", default-features = false } +hydra-dx-build-script-utils = { git = "https://github.com/galacticcouncil/hydration-node", branch ="polkadot-stable2503-11-snek" } -frame-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -frame-benchmarking-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -frame-election-provider-support = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -frame-executive = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -frame-support = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -frame-support-procedural = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -frame-support-procedural-tools = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -frame-support-procedural-tools-derive = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -frame-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -frame-system-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -frame-system-rpc-runtime-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -frame-try-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-authority-discovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-authorship = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-babe = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-balances = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-bounties = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-collective = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-conviction-voting = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-democracy = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-election-provider-multi-phase = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-elections-phragmen = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-identity = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-im-online = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-indices = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-membership = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-multisig = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-offences = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-offences-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-proxy = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-recovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-referenda = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-scheduler = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-session = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-session-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-society = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-state-trie-migration = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-sudo = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-tips = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-transaction-payment = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-transaction-payment-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-treasury = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-uniques = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-utility = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-vesting = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-whitelist = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-preimage = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-message-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22", default-features = false } +frame-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +frame-benchmarking-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +frame-election-provider-support = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +frame-executive = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +frame-support = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +frame-support-procedural = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +frame-support-procedural-tools = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +frame-support-procedural-tools-derive = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +frame-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +frame-system-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +frame-system-rpc-runtime-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +frame-try-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-authority-discovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-authorship = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-babe = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-balances = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-bounties = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-collective = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-conviction-voting = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-democracy = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-election-provider-multi-phase = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-elections-phragmen = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-identity = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-im-online = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-indices = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-membership = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-multisig = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-offences = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-offences-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-proxy = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-recovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-referenda = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-scheduler = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-session = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-session-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-society = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-state-trie-migration = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-sudo = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-tips = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-transaction-payment = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-transaction-payment-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-treasury = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-uniques = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-utility = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-vesting = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-whitelist = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-preimage = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-message-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch", default-features = false } -sc-authority-discovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-basic-authorship = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-block-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-chain-spec = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-client-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-client-db = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-consensus = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-consensus-babe = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-consensus-babe-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-consensus-epochs = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-consensus-slots = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-consensus-grandpa = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-executor = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-executor-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-executor-wasmtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-informant = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-keystore = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-network = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-network-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-network-sync = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-network-gossip = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-offchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-rpc-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-rpc-server = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-sync-state-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-telemetry = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-tracing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-transaction-pool = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-transaction-pool-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-utils = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sc-sysinfo = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-application-crypto = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-arithmetic = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-authority-discovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false} -sp-block-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-genesis-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22", default-features = false } -sp-blockchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-consensus = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-consensus-babe = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-consensus-slots = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-consensus-beefy = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-core = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-debug-derive = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-externalities = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-inherents = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-io = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-keyring = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-keystore = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-maybe-compressed-blob = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-npos-elections = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-offchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-runtime-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-runtime-interface-proc-macro = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-session = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-staking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-state-machine = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-std = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-storage = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-tracing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-transaction-pool = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-trie = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-version = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-wasm-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-weights = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-crypto-hashing= { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22", default-features = false} -sp-crypto-ec-utils= { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22", default-features = false} -sp-core-hashing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22", default-features = false} +sc-authority-discovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-basic-authorship = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-block-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-chain-spec = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-client-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-client-db = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-consensus = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-consensus-babe = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-consensus-babe-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-consensus-epochs = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-consensus-slots = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-consensus-grandpa = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-executor = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-executor-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-executor-wasmtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-informant = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-keystore = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-network = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-network-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-network-sync = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-network-gossip = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-offchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-rpc-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-rpc-server = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-sync-state-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-telemetry = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-tracing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-transaction-pool = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-transaction-pool-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-utils = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sc-sysinfo = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-application-crypto = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-arithmetic = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-authority-discovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false} +sp-block-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-genesis-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch", default-features = false } +sp-blockchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-consensus = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-consensus-babe = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-consensus-slots = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-consensus-beefy = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-core = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-debug-derive = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-externalities = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-inherents = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-io = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-keyring = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-keystore = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-maybe-compressed-blob = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-npos-elections = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-offchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-runtime-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-runtime-interface-proc-macro = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-session = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-staking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-state-machine = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-std = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-storage = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-tracing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-transaction-pool = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-trie = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-version = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-wasm-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-weights = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-crypto-hashing= { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch", default-features = false} +sp-crypto-ec-utils= { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch", default-features = false} +sp-core-hashing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch", default-features = false} -substrate-build-script-utils = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -substrate-frame-rpc-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -substrate-prometheus-endpoint = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -substrate-wasm-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -pallet-mmr = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -sp-mmr-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -substrate-state-trie-migration-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22" } +substrate-build-script-utils = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +substrate-frame-rpc-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +substrate-prometheus-endpoint = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +substrate-wasm-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +pallet-mmr = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +sp-mmr-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +substrate-state-trie-migration-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch" } -pallet-xcm = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -polkadot-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -polkadot-core-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -polkadot-node-core-pvf = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -polkadot-node-network-protocol = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -polkadot-node-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -polkadot-node-subsystem = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -polkadot-node-subsystem-util = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -polkadot-overseer = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -polkadot-parachain = { package = "polkadot-parachain-primitives", git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false, features = ["wasm-api"] } -polkadot-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -polkadot-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -polkadot-runtime-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -polkadot-runtime-parachains = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -polkadot-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -polkadot-statement-table = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -rococo-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -rococo-emulated-chain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -westend-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -xcm = { package = "staging-xcm", git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -polkadot-xcm = { package = "staging-xcm", git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -xcm-emulator = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -xcm-runtime-apis = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22", default-features = false } -parachains-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22", default-features = false } +pallet-xcm = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +polkadot-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +polkadot-core-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +polkadot-node-core-pvf = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +polkadot-node-network-protocol = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +polkadot-node-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +polkadot-node-subsystem = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +polkadot-node-subsystem-util = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +polkadot-overseer = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +polkadot-parachain = { package = "polkadot-parachain-primitives", git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false, features = ["wasm-api"] } +polkadot-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +polkadot-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +polkadot-runtime-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +polkadot-runtime-parachains = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +polkadot-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +polkadot-statement-table = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +rococo-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +rococo-emulated-chain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +westend-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +xcm = { package = "staging-xcm", git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +polkadot-xcm = { package = "staging-xcm", git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +xcm-emulator = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +xcm-runtime-apis = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch", default-features = false } +parachains-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch", default-features = false } -pallet-collator-selection = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-client-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-client-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-client-consensus-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-client-consensus-proposer = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-client-network = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-client-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-client-collator = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-pallet-aura-ext = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-pallet-dmp-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-pallet-parachain-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-pallet-xcm = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-pallet-xcmp-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-primitives-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-primitives-core = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-primitives-parachain-inherent = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-primitives-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-primitives-utility = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-test-relay-sproof-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -staging-parachain-info = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-relay-chain-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-relay-chain-minimal-node = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } -cumulus-relay-chain-inprocess-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="stable2409-patch22", default-features = false } +pallet-collator-selection = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-client-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-client-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-client-consensus-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-client-consensus-proposer = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-client-network = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-client-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-client-collator = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-pallet-aura-ext = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-pallet-dmp-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-pallet-parachain-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-pallet-xcm = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-pallet-xcmp-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-primitives-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-primitives-core = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-primitives-parachain-inherent = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-primitives-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-primitives-utility = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-test-relay-sproof-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +staging-parachain-info = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-relay-chain-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-relay-chain-minimal-node = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } +cumulus-relay-chain-inprocess-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch ="polkadot-stable2503-11-patch", default-features = false } # ORML dependencies -orml-benchmarking = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409", default-features = false } -orml-tokens = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409", default-features = false } -orml-traits = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409", default-features = false } -orml-utilities = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409", default-features = false } -orml-vesting = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409", default-features = false } +orml-benchmarking = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503", default-features = false } +orml-tokens = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503", default-features = false } +orml-traits = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503", default-features = false } +orml-utilities = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503", default-features = false } +orml-vesting = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503", default-features = false } # orml XCM support -orml-unknown-tokens = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409", default-features = false } -orml-xcm = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409", default-features = false } -orml-xcm-support = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409", default-features = false } -orml-xtokens = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409", default-features = false } +orml-unknown-tokens = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503", default-features = false } +orml-xcm = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503", default-features = false } +orml-xcm-support = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503", default-features = false } +orml-xtokens = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503", default-features = false } [patch."https://github.com/moonbeam-foundation/open-runtime-module-library"] # ORML dependencies -orml-benchmarking = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409"} -orml-tokens = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409"} -orml-traits = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409"} -orml-utilities = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409"} -orml-vesting = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409"} -orml-unknown-tokens = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409"} -orml-xcm = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409"} -orml-xcm-support = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409"} -orml-xtokens = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2409"} +orml-benchmarking = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503"} +orml-tokens = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503"} +orml-traits = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503"} +orml-utilities = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503"} +orml-vesting = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503"} +orml-unknown-tokens = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503"} +orml-xcm = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503"} +orml-xcm-support = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503"} +orml-xtokens = { git = "https://github.com/galacticcouncil/open-runtime-module-library", branch = "polkadot-stable2503"} [patch."https://github.com/moonbeam-foundation/polkadot-sdk"] -frame-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -frame-benchmarking-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -frame-executive = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -frame-support = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -frame-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -frame-system-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -frame-system-rpc-runtime-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -frame-try-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-arithmetic = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-authority-discovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-block-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-genesis-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-blockchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-consensus = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-consensus-babe = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-core = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-externalities = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-inherents = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-io = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-keystore = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-npos-elections = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-offchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-offchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-runtime-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-runtime-interface-proc-macro = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-wasm-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-panic-handler = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-database = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-session = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-staking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-std = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-storage = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-tracing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-transaction-pool = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-trie = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-version = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-basic-authorship = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-chain-spec = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-client-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-client-db = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-consensus = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-consensus-grandpa = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-executor = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-keystore = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-network = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-network-sync = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-network-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-rpc-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-telemetry = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-tracing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-transaction-pool = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-transaction-pool-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-sysinfo = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-utils = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-state-machine = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-weights = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22"} -sp-crypto-hashing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22"} +frame-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +frame-benchmarking-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +frame-executive = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +frame-support = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +frame-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +frame-system-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +frame-system-rpc-runtime-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +frame-try-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-arithmetic = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-authority-discovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-block-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-genesis-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-blockchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-consensus = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-consensus-babe = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-core = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-externalities = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-inherents = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-io = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-keystore = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-npos-elections = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-offchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-offchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-runtime-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-runtime-interface-proc-macro = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-wasm-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-panic-handler = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-database = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-session = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-staking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-std = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-storage = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-tracing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-transaction-pool = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-trie = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-version = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-basic-authorship = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-chain-spec = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-client-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-client-db = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-consensus = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-consensus-grandpa = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-executor = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-keystore = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-network = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-network-sync = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-network-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-rpc-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-telemetry = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-tracing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-transaction-pool = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-transaction-pool-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-sysinfo = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-utils = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-state-machine = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-weights = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch"} +sp-crypto-hashing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch"} # Substrate Pallets -pallet-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-authorship = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-balances = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-collective = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-conviction-voting = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-elections-phragmen = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-identity = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-multisig = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-preimage = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-proxy = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-referenda = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-scheduler = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-session = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-sudo = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-tips = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-transaction-payment = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-transaction-payment-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-treasury = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-uniques = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-whitelist = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-utility = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-im-online = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-message-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22"} +pallet-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-authorship = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-balances = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-collective = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-conviction-voting = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-elections-phragmen = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-identity = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-multisig = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-preimage = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-proxy = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-referenda = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-scheduler = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-session = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-sudo = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-tips = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-transaction-payment = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-transaction-payment-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-treasury = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-uniques = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-whitelist = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-utility = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-im-online = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-message-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch"} -substrate-build-script-utils = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -substrate-frame-rpc-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -substrate-prometheus-endpoint = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -substrate-wasm-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } +substrate-build-script-utils = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +substrate-frame-rpc-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +substrate-prometheus-endpoint = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +substrate-wasm-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } # Cumulus dependencies -cumulus-client-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-client-collator = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-client-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-client-consensus-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-client-consensus-proposer = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-client-network = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-client-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-pallet-aura-ext = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-pallet-dmp-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-pallet-parachain-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-pallet-xcm = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-pallet-xcmp-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-primitives-core = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-primitives-parachain-inherent = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-primitives-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-primitives-utility = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-relay-chain-inprocess-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-relay-chain-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-relay-chain-minimal-node = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-test-relay-sproof-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-collator-selection = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -staging-parachain-info = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -xcm-emulator = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -parachains-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22"} +cumulus-client-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-client-collator = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-client-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-client-consensus-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-client-consensus-proposer = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-client-network = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-client-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-pallet-aura-ext = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-pallet-dmp-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-pallet-parachain-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-pallet-xcm = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-pallet-xcmp-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-primitives-core = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-primitives-parachain-inherent = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-primitives-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-primitives-utility = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-relay-chain-inprocess-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-relay-chain-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-relay-chain-minimal-node = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-test-relay-sproof-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-collator-selection = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +staging-parachain-info = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +xcm-emulator = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +parachains-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch"} # Polkadot dependencies -pallet-xcm = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-core-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-parachain = { package = "polkadot-parachain-primitives", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22"} -polkadot-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-runtime-parachains = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -xcm = { package = "staging-xcm", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -xcm-runtime-apis = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } +pallet-xcm = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-core-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-parachain = { package = "polkadot-parachain-primitives", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch"} +polkadot-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-runtime-parachains = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +xcm = { package = "staging-xcm", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +xcm-runtime-apis = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } -polkadot-node-core-pvf = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-node-network-protocol = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-node-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-node-subsystem = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-node-subsystem-util = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-overseer = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-runtime-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22"} -polkadot-statement-table = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -rococo-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -westend-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } +polkadot-node-core-pvf = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-node-network-protocol = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-node-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-node-subsystem = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-node-subsystem-util = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-overseer = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-runtime-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch"} +polkadot-statement-table = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +rococo-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +westend-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } -cumulus-client-pov-recovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-pallet-parachain-system-proc-macro = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-relay-chain-rpc-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } +cumulus-client-pov-recovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-pallet-parachain-system-proc-macro = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-relay-chain-rpc-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } [patch."https://github.com/paritytech/polkadot-sdk"] -frame-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -frame-benchmarking-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -frame-executive = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -frame-support = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -frame-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -frame-system-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -frame-system-rpc-runtime-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -frame-try-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -frame-metadata-hash-extension = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-arithmetic = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-authority-discovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-block-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-genesis-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-blockchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-consensus = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-consensus-babe = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-core = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-externalities = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-inherents = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-io = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-keystore = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-npos-elections = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-offchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-offchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-runtime-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-runtime-interface-proc-macro = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-wasm-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-panic-handler = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-database = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-session = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-staking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-std = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-storage = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-tracing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-transaction-pool = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-trie = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-version = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-basic-authorship = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-chain-spec = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-client-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-client-db = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-consensus = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-consensus-grandpa = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-executor = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-keystore = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-network = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-network-sync = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-network-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-rpc-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-telemetry = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-tracing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-transaction-pool = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-transaction-pool-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-sysinfo = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sc-utils = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-state-machine = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -sp-weights = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22"} -sp-crypto-hashing= { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22"} +frame-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +frame-benchmarking-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +frame-executive = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +frame-support = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +frame-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +frame-system-benchmarking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +frame-system-rpc-runtime-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +frame-try-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +frame-metadata-hash-extension = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-arithmetic = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-authority-discovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-block-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-genesis-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-blockchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-consensus = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-consensus-babe = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-core = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-externalities = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-inherents = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-io = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-keystore = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-npos-elections = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-offchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-offchain = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-runtime-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-runtime-interface-proc-macro = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-wasm-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-panic-handler = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-database = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-session = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-staking = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-std = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-storage = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-tracing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-transaction-pool = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-trie = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-version = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-basic-authorship = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-chain-spec = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-client-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-client-db = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-consensus = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-consensus-grandpa = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-executor = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-keystore = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-network = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-network-sync = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-network-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-rpc-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-telemetry = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-tracing = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-transaction-pool = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-transaction-pool-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-sysinfo = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sc-utils = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-state-machine = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +sp-weights = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch"} +sp-crypto-hashing= { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch"} # Substrate Pallets -pallet-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-authorship = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-balances = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-collective = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-elections-phragmen = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-identity = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-multisig = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-preimage = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-proxy = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-scheduler = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-session = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-sudo = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-tips = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-transaction-payment = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-transaction-payment-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-treasury = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-uniques = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-utility = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-im-online = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-message-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22"} -pallet-state-trie-migration = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22"} +pallet-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-authorship = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-balances = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-collective = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-elections-phragmen = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-identity = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-multisig = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-preimage = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-proxy = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-scheduler = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-session = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-sudo = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-tips = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-transaction-payment = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-transaction-payment-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-treasury = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-uniques = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-utility = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-im-online = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-message-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch"} +pallet-state-trie-migration = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch"} -substrate-build-script-utils = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -substrate-frame-rpc-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -substrate-prometheus-endpoint = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -substrate-wasm-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -substrate-state-trie-migration-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } +substrate-build-script-utils = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +substrate-frame-rpc-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +substrate-prometheus-endpoint = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +substrate-wasm-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +substrate-state-trie-migration-rpc = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } # Cumulus dependencies -cumulus-client-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-client-collator = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-client-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-client-consensus-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-client-consensus-proposer = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-client-network = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-client-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-pallet-aura-ext = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-pallet-parachain-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-pallet-xcm = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-pallet-xcmp-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-primitives-core = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-primitives-parachain-inherent = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-primitives-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-primitives-utility = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-relay-chain-inprocess-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-relay-chain-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-relay-chain-minimal-node = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-test-relay-sproof-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -pallet-collator-selection = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -staging-parachain-info = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -xcm-emulator = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -parachains-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22"} +cumulus-client-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-client-collator = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-client-consensus-aura = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-client-consensus-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-client-consensus-proposer = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-client-network = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-client-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-pallet-aura-ext = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-pallet-parachain-system = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-pallet-xcm = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-pallet-xcmp-queue = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-primitives-core = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-primitives-parachain-inherent = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-primitives-timestamp = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-primitives-utility = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-relay-chain-inprocess-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-relay-chain-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-relay-chain-minimal-node = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-test-relay-sproof-builder = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +pallet-collator-selection = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +staging-parachain-info = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +xcm-emulator = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +parachains-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch"} # Polkadot dependencies -pallet-xcm = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-core-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-parachain = { package = "polkadot-parachain-primitives", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22"} -polkadot-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-runtime-parachains = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -xcm = { package = "staging-xcm", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -xcm-runtime-apis = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } +pallet-xcm = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-cli = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-core-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-parachain = { package = "polkadot-parachain-primitives", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch"} +polkadot-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-runtime-parachains = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-service = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +xcm = { package = "staging-xcm", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +xcm-runtime-apis = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } -polkadot-node-core-pvf = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-node-network-protocol = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-node-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-node-subsystem = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-node-subsystem-util = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-overseer = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-runtime-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -polkadot-statement-table = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -rococo-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -westend-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } +polkadot-node-core-pvf = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-node-network-protocol = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-node-primitives = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-node-subsystem = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-node-subsystem-util = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-overseer = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-runtime-common = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +polkadot-statement-table = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +rococo-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +westend-runtime = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } -cumulus-client-pov-recovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-pallet-parachain-system-proc-macro = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } -cumulus-relay-chain-rpc-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "stable2409-patch22" } +cumulus-client-pov-recovery = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-pallet-parachain-system-proc-macro = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } +cumulus-relay-chain-rpc-interface = { git = "https://github.com/galacticcouncil/polkadot-sdk", branch = "polkadot-stable2503-11-patch" } diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 9b6cc7a456a..cd1fc2ef477 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "runtime-integration-tests" -version = "1.0.8" +version = "1.1.0" description = "Integration tests" authors = ["GalacticCouncil"] edition = "2021" @@ -9,6 +9,7 @@ license = "Apache 2.0" repository = "https://github.com/galacticcouncil/Basilisk-node" [dependencies] +basilisk-traits = { workspace = true } # HydraDX dependencies pallet-transaction-multi-payment = { workspace = true } pallet-nft = { workspace = true } @@ -186,4 +187,9 @@ std = [ runtime-benchmarks = [ "basilisk-runtime/runtime-benchmarks", "rococo-runtime/runtime-benchmarks", +] + +try-runtime = [ + "basilisk-runtime/try-runtime", + "rococo-runtime/try-runtime", ] \ No newline at end of file diff --git a/integration-tests/src/exchange_asset.rs b/integration-tests/src/exchange_asset.rs deleted file mode 100644 index 762fa3aa442..00000000000 --- a/integration-tests/src/exchange_asset.rs +++ /dev/null @@ -1,286 +0,0 @@ -#![cfg(test)] - -use crate::kusama_test_net::*; -use basilisk_runtime::RuntimeOrigin; -use basilisk_runtime::XYK; -use frame_support::dispatch::GetDispatchInfo; -use frame_support::{assert_ok, pallet_prelude::*}; -use orml_traits::currency::MultiCurrency; -use polkadot_xcm::{ - opaque::v3::{Junction, Junctions::X2, MultiLocation}, - v4::prelude::*, - VersionedXcm, -}; -use pretty_assertions::assert_eq; -use primitives::constants::chain::CORE_ASSET_ID; -use sp_runtime::FixedU128; -use sp_std::sync::Arc; -use xcm_emulator::TestExt; - -pub const SELL: bool = true; -pub const BUY: bool = false; - -#[test] -fn basilisk_should_swap_assets_when_receiving_from_otherchain_with_sell() { - //Arrange - TestNet::reset(); - - Basilisk::execute_with(|| { - register_kar(); - add_currency_price(KAR, FixedU128::from(1)); - - assert_ok!(basilisk_runtime::Tokens::deposit(KAR, &CHARLIE.into(), 3000 * UNITS)); - create_xyk_pool(KAR, BSX); - }); - - OtherParachain::execute_with(|| { - let sell_amount: Asset = Asset::from((cumulus_primitives_core::Junction::GeneralIndex(0), 5 * UNITS)); - - let min_amount_out = Asset::from(( - cumulus_primitives_core::Junction::GeneralIndex(CORE_ASSET_ID.into()), - 2 * UNITS, - )); - - let xcm = craft_exchange_asset_xcm::<_, basilisk_runtime::RuntimeCall>(sell_amount, min_amount_out, SELL); - //Act - let res = basilisk_runtime::PolkadotXcm::execute( - basilisk_runtime::RuntimeOrigin::signed(ALICE.into()), - Box::new(xcm), - Weight::from_parts(399_600_000_000, 0), - ); - assert_ok!(res); - - //Assert - assert_eq!( - basilisk_runtime::Balances::free_balance(AccountId::from(ALICE)), - ALICE_INITIAL_NATIVE_BALANCE_ON_OTHER_PARACHAIN - 100 * UNITS - ); - - assert!(matches!( - last_other_para_events(2).first(), - Some(basilisk_runtime::RuntimeEvent::XcmpQueue( - cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. } - )) - )); - }); - - let fees = 27_500_000_000_000; - Basilisk::execute_with(|| { - assert_eq!( - basilisk_runtime::Tokens::free_balance(KAR, &AccountId::from(BOB)), - 95000000000000 - fees - ); - let received = BOB_INITIAL_BSX_BALANCE + 2373809523812; - assert_eq!(basilisk_runtime::Balances::free_balance(AccountId::from(BOB)), received); - assert_eq!( - basilisk_runtime::Tokens::free_balance(KAR, &basilisk_runtime::Treasury::account_id()), - fees - ); - }); -} - -#[test] -fn basilisk_should_swap_assets_when_receiving_from_otherchain_with_buy() { - //Arrange - TestNet::reset(); - - Basilisk::execute_with(|| { - register_kar(); - add_currency_price(KAR, FixedU128::from(1)); - - assert_ok!(basilisk_runtime::Tokens::deposit(KAR, &CHARLIE.into(), 3000 * UNITS)); - assert_ok!(basilisk_runtime::Tokens::deposit(BSX, &CHARLIE.into(), 3000 * UNITS)); - assert_ok!(XYK::create_pool( - RuntimeOrigin::signed(CHARLIE.into()), - KAR, - 1000 * UNITS, - BSX, - 500 * UNITS, - )); - }); - - let amount_out = 20 * UNITS; - OtherParachain::execute_with(|| { - let max_amount_in: Asset = Asset::from((cumulus_primitives_core::Junction::GeneralIndex(0), 70 * UNITS)); - let amount_out_asset: Asset = Asset::from(( - cumulus_primitives_core::Junction::GeneralIndex(CORE_ASSET_ID.into()), - amount_out, - )); - - let xcm = craft_exchange_asset_xcm::<_, basilisk_runtime::RuntimeCall>(max_amount_in, amount_out_asset, BUY); - //Act - let res = basilisk_runtime::PolkadotXcm::execute( - basilisk_runtime::RuntimeOrigin::signed(ALICE.into()), - Box::new(xcm), - Weight::from_parts(399_600_000_000, 0), - ); - assert_ok!(res); - - //Assert - assert_eq!( - basilisk_runtime::Balances::free_balance(AccountId::from(ALICE)), - ALICE_INITIAL_NATIVE_BALANCE_ON_OTHER_PARACHAIN - 100 * UNITS - ); - - assert!(matches!( - last_other_para_events(2).first(), - Some(basilisk_runtime::RuntimeEvent::XcmpQueue( - cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. } - )) - )); - }); - - Basilisk::execute_with(|| { - let fees = basilisk_runtime::Tokens::free_balance(KAR, &basilisk_runtime::Treasury::account_id()); - assert!(fees > 0, "Fees are not sent to treasury"); - - assert_eq!( - basilisk_runtime::Balances::free_balance(AccountId::from(BOB)), - BOB_INITIAL_BSX_BALANCE + amount_out - ); - }); -} - -fn register_kar() { - assert_ok!(basilisk_runtime::AssetRegistry::register( - basilisk_runtime::RuntimeOrigin::root(), - b"KAR".to_vec(), - pallet_asset_registry::AssetType::Token, - 1_000_000, - Some(KAR), - None, - Some(basilisk_runtime::AssetLocation(MultiLocation::new( - 1, - X2(Junction::Parachain(OTHER_PARA_ID), Junction::GeneralIndex(0)) - ))), - None - )); -} - -fn add_currency_price(asset_id: u32, price: FixedU128) { - assert_ok!(basilisk_runtime::MultiTransactionPayment::add_currency( - basilisk_runtime::RuntimeOrigin::root(), - asset_id, - price, - )); - - // make sure the price is propagated - basilisk_runtime::MultiTransactionPayment::on_initialize(basilisk_runtime::System::block_number()); -} - -fn craft_exchange_asset_xcm, RC: Decode + GetDispatchInfo>( - give: Asset, - want: M, - is_sell: bool, -) -> VersionedXcm { - use rococo_runtime::xcm_config::BaseXcmWeight; - use xcm_builder::FixedWeightBounds; - use xcm_executor::traits::WeightBounds; - - type Weigher = FixedWeightBounds>; - - let dest = Location::new( - 1, - cumulus_primitives_core::Junctions::X1(Arc::new( - vec![cumulus_primitives_core::Junction::Parachain(BASILISK_PARA_ID)] - .try_into() - .unwrap(), - )), - ); - - let beneficiary = Location::new( - 0, - cumulus_primitives_core::Junctions::X1(Arc::new( - vec![cumulus_primitives_core::Junction::AccountId32 { id: BOB, network: None }] - .try_into() - .unwrap(), - )), - ); - - let assets: Assets = Assets::from(Asset::from(( - cumulus_primitives_core::Junction::GeneralIndex(0), - 100 * UNITS, - ))); - - let max_assets = assets.len() as u32 + 1; - let context = cumulus_primitives_core::Junctions::X2(Arc::new( - vec![ - cumulus_primitives_core::Junction::GlobalConsensus(NetworkId::Polkadot), - cumulus_primitives_core::Junction::Parachain(OTHER_PARA_ID), - ] - .try_into() - .unwrap(), - )); - - let fees = assets - .get(0) - .expect("should have at least 1 asset") - .clone() - .reanchored(&dest, &context) - .expect("should reanchor"); - let give = give.reanchored(&dest, &context).expect("should reanchor give"); - let give: AssetFilter = Definite(give.into()); - let want = want.into(); - let weight_limit = { - let fees = fees.clone(); - let mut remote_message = Xcm(vec![ - ReserveAssetDeposited::(assets.clone()), - ClearOrigin, - BuyExecution { - fees, - weight_limit: Limited(Weight::zero()), - }, - ExchangeAsset { - give: give.clone(), - want: want.clone(), - maximal: is_sell, - }, - DepositAsset { - assets: Wild(AllCounted(max_assets)), - beneficiary: beneficiary.clone(), - }, - ]); - // use local weight for remote message and hope for the best. - let remote_weight = Weigher::weight(&mut remote_message).expect("weighing should not fail"); - Limited(remote_weight) - }; - // executed on remote (on hydra) - let xcm = Xcm(vec![ - BuyExecution { fees, weight_limit }, - ExchangeAsset { - give, - want, - maximal: is_sell, - }, - DepositAsset { - assets: Wild(AllCounted(max_assets)), - beneficiary, - }, - ]); - // executed on local (acala) - let message = Xcm(vec![ - SetFeesMode { jit_withdraw: true }, - TransferReserveAsset { assets, dest, xcm }, - ]); - VersionedXcm::from(message) -} - -pub fn last_other_para_events(n: usize) -> Vec { - frame_system::Pallet::::events() - .into_iter() - .rev() - .take(n) - .rev() - .map(|e| e.event) - .collect() -} - -fn create_xyk_pool(asset_a: u32, asset_b: u32) { - assert_ok!(XYK::create_pool( - RuntimeOrigin::signed(CHARLIE.into()), - asset_a, - 100 * UNITS, - asset_b, - 50 * UNITS, - )); -} diff --git a/integration-tests/src/kusama_test_net.rs b/integration-tests/src/kusama_test_net.rs index c69507a0090..51438985731 100644 --- a/integration-tests/src/kusama_test_net.rs +++ b/integration-tests/src/kusama_test_net.rs @@ -16,7 +16,6 @@ pub const AUSD: AssetId = 1; pub const MOVR: AssetId = 2; pub const KSM: AssetId = 3; pub const NEW_BOOTSTRAPPED_TOKEN: AssetId = 4; -pub const KAR: AssetId = 5; pub const ALICE_INITIAL_BSX_BALANCE: u128 = 1_000 * UNITS; pub const BOB_INITIAL_BSX_BALANCE: u128 = 1000 * UNITS; @@ -59,9 +58,10 @@ use sp_consensus_slots::{Slot, SlotDuration}; use sp_core::{storage::Storage, Encode}; use sp_runtime::{traits::AccountIdConversion, BuildStorage, Digest, DigestItem}; +use polkadot_primitives::runtime_api::runtime_decl_for_parachain_host::ParachainHostV13; use primitives::constants::chain::CORE_ASSET_ID; pub use xcm_emulator::Network; -use xcm_emulator::{decl_test_networks, decl_test_parachains, decl_test_relay_chains}; +use xcm_emulator::{decl_test_networks, decl_test_parachains, decl_test_relay_chains, Parachain}; pub type Basilisk = BasiliskParachain; pub type OtherParachain = OtherPara; @@ -81,7 +81,9 @@ decl_test_relay_chains! { #[api_version(11)] pub struct RococoRelayChain { genesis = rococo::genesis(), - on_init = (), + on_init = { + rococo_runtime::System::set_block_number(1); + }, runtime = rococo_runtime, core = { SovereignAccountOf: rococo_runtime::xcm_config::LocationConverter, @@ -98,7 +100,7 @@ decl_test_parachains! { pub struct BasiliskParachain { genesis = basilisk::genesis(), on_init = { - set_para_slot_info(0); + basilisk_runtime::System::set_block_number(1); }, runtime = basilisk_runtime, core = { @@ -115,7 +117,7 @@ decl_test_parachains! { pub struct OtherPara { genesis = other_parachain::genesis(), on_init = { - set_para_slot_info(0); + basilisk_runtime::System::set_block_number(1); }, runtime = basilisk_runtime, core = { @@ -167,12 +169,13 @@ pub mod rococo { } use polkadot_primitives::{AssignmentId, ValidatorId}; - use polkadot_service::chain_spec::get_account_id_from_seed; use sc_consensus_grandpa::AuthorityId as GrandpaId; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_consensus_babe::AuthorityId as BabeId; use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId; use sp_core::{sr25519, Pair, Public}; + use sp_runtime::traits::AccountIdConversion; + use sp_runtime::AccountId32 as AccountPublic; /// Helper function to generate a crypto pair from seed fn get_from_seed(seed: &str) -> ::Public { @@ -181,6 +184,14 @@ pub mod rococo { .public() } + /// Helper function to generate an account ID from seed. + fn get_account_id_from_seed(seed: &str) -> AccountId + where + AccountPublic: From<::Public>, + { + AccountPublic::from(get_from_seed::(seed)) + } + fn session_keys( babe: BabeId, grandpa: GrandpaId, @@ -252,6 +263,7 @@ pub mod rococo { (AccountId::from(ALICE), 2002 * UNITS), (ParaId::from(BASILISK_PARA_ID).into_account_truncating(), 10 * UNITS), ], + dev_accounts: Default::default(), }, session: rococo_runtime::SessionConfig { keys: initial_authorities() @@ -283,7 +295,7 @@ pub mod rococo { }, xcm_pallet: rococo_runtime::XcmPalletConfig { - safe_xcm_version: Some(3), + safe_xcm_version: Some(5), ..Default::default() }, ..Default::default() @@ -378,6 +390,7 @@ pub mod basilisk { (AccountId::from(DAVE), DAVE_INITIAL_BSX_BALANCE), (vesting_account(), VESTING_ACCOUNT_INITIAL_BSX_BALANCE), ], + dev_accounts: Default::default(), }, collator_selection: basilisk_runtime::CollatorSelectionConfig { invulnerables: invulnerables().iter().cloned().map(|(acc, _)| acc).collect(), @@ -436,7 +449,7 @@ pub mod basilisk { ], }, polkadot_xcm: basilisk_runtime::PolkadotXcmConfig { - safe_xcm_version: Some(3), + safe_xcm_version: Some(5), ..Default::default() }, multi_transaction_payment: basilisk_runtime::MultiTransactionPaymentConfig { @@ -444,9 +457,7 @@ pub mod basilisk { account_currencies: vec![], }, duster: basilisk_runtime::DusterConfig { - account_blacklist: vec![basilisk_runtime::Treasury::account_id()], - reward_account: Some(basilisk_runtime::Treasury::account_id()), - dust_account: Some(basilisk_runtime::Treasury::account_id()), + account_whitelist: vec![basilisk_runtime::Treasury::account_id()], }, ..Default::default() }; @@ -466,6 +477,7 @@ pub mod other_parachain { let genesis_config = basilisk_runtime::RuntimeGenesisConfig { balances: basilisk_runtime::BalancesConfig { balances: vec![(AccountId::from(ALICE), ALICE_INITIAL_NATIVE_BALANCE_ON_OTHER_PARACHAIN)], + dev_accounts: Default::default(), }, collator_selection: basilisk_runtime::CollatorSelectionConfig { invulnerables: basilisk::invulnerables().iter().cloned().map(|(acc, _)| acc).collect(), @@ -505,7 +517,7 @@ pub mod other_parachain { ], }, polkadot_xcm: basilisk_runtime::PolkadotXcmConfig { - safe_xcm_version: Some(3), + safe_xcm_version: Some(5), ..Default::default() }, multi_transaction_payment: basilisk_runtime::MultiTransactionPaymentConfig { @@ -513,9 +525,7 @@ pub mod other_parachain { account_currencies: vec![], }, duster: basilisk_runtime::DusterConfig { - account_blacklist: vec![basilisk_runtime::Treasury::account_id()], - reward_account: Some(basilisk_runtime::Treasury::account_id()), - dust_account: Some(basilisk_runtime::Treasury::account_id()), + account_whitelist: vec![basilisk_runtime::Treasury::account_id()], }, ..Default::default() }; @@ -585,13 +595,11 @@ pub fn initialize_rococo_block(target_block: BlockNumber, target_slot: Slot) { rococo_runtime::Scheduler::on_initialize(target_block); rococo_runtime::Preimage::on_initialize(target_block); rococo_runtime::Babe::on_initialize(target_block); - rococo_runtime::Timestamp::on_initialize(target_block); rococo_runtime::Session::on_initialize(target_block); rococo_runtime::Grandpa::on_initialize(target_block); rococo_runtime::ParachainsOrigin::on_initialize(target_block); rococo_runtime::ParasShared::on_initialize(target_block); rococo_runtime::ParaInclusion::on_initialize(target_block); - // rococo_runtime::ParaInherent::on_initialize(target_block); rococo_runtime::ParaScheduler::on_initialize(target_block); rococo_runtime::Paras::on_initialize(target_block); rococo_runtime::Initializer::on_initialize(target_block); @@ -602,15 +610,28 @@ pub fn initialize_rococo_block(target_block: BlockNumber, target_slot: Slot) { rococo_runtime::XcmPallet::on_initialize(target_block); rococo_runtime::MessageQueue::on_initialize(target_block); rococo_runtime::Beefy::on_initialize(target_block); - assert_ok!(rococo_runtime::Timestamp::set( - rococo_runtime::RuntimeOrigin::none(), - SLOT_DURATION * *target_slot - )); - // rococo_runtime::AllPalletsWithSystem::on_initialize(target_block); } pub fn initialize_basilisk_block(target_block: BlockNumber, target_slot: Slot) { - // Force a new Basilisk block to be created + use frame_support::storage::unhashed; + + // Clear AuraExt storage when starting a new test (block 1) or when resetting + // This prevents "Slot moved backwards" errors from previous test runs + let aura_key = frame_support::storage::storage_prefix(b"AuraExt", b"RelaySlotInfo"); + + if target_block == 1 { + unhashed::kill(&aura_key); + } else if let Some(data) = unhashed::get_raw(&aura_key) { + // Also check if stored slot exists and is greater than what we're about to set + // This indicates storage wasn't properly cleared after previous test + use sp_core::Decode; + if let Ok((stored_slot, _)) = <(Slot, u32)>::decode(&mut &data[..]) { + // If stored slot is greater than or equal to the number we're setting, clear it + if u64::from(stored_slot) >= target_block as u64 { + unhashed::kill(&aura_key); + } + } + } basilisk_runtime::System::set_block_number(target_block); basilisk_runtime::System::initialize( @@ -636,12 +657,8 @@ pub fn initialize_basilisk_block(target_block: BlockNumber, target_slot: Slot) { basilisk_runtime::MessageQueue::on_initialize(target_block); basilisk_runtime::MultiTransactionPayment::on_initialize(target_block); basilisk_runtime::EmaOracle::on_initialize(target_block); - // assert_ok!(basilisk_runtime::Timestamp::set( - // basilisk_runtime::RuntimeOrigin::none(), - // SLOT_DURATION * *target_slot - // )); - // basilisk_runtime::AllPalletsWithSystem::on_initialize(target_block); + // Set validation data AFTER on_initialize hooks set_validation_data(target_block, target_slot); } @@ -649,7 +666,6 @@ pub fn finalize_basilisk_block(target_block: BlockNumber) { use frame_support::traits::OnFinalize; basilisk_runtime::System::on_finalize(target_block); - // basilisk_runtime::Timestamp::on_finalize(target_block); basilisk_runtime::Session::on_finalize(target_block); basilisk_runtime::Aura::on_finalize(target_block); basilisk_runtime::AuraExt::on_finalize(target_block); @@ -672,13 +688,11 @@ pub fn finalize_rococo_block(target_block: BlockNumber) { rococo_runtime::Scheduler::on_finalize(target_block); rococo_runtime::Preimage::on_finalize(target_block); rococo_runtime::Babe::on_finalize(target_block); - rococo_runtime::Timestamp::on_finalize(target_block); rococo_runtime::Session::on_finalize(target_block); rococo_runtime::Grandpa::on_finalize(target_block); rococo_runtime::ParachainsOrigin::on_finalize(target_block); rococo_runtime::ParasShared::on_finalize(target_block); rococo_runtime::ParaInclusion::on_finalize(target_block); - // rococo_runtime::ParaInherent::on_finalize(target_block); rococo_runtime::ParaScheduler::on_finalize(target_block); rococo_runtime::Paras::on_finalize(target_block); rococo_runtime::Initializer::on_finalize(target_block); @@ -689,10 +703,6 @@ pub fn finalize_rococo_block(target_block: BlockNumber) { rococo_runtime::XcmPallet::on_finalize(target_block); rococo_runtime::MessageQueue::on_finalize(target_block); rococo_runtime::Beefy::on_finalize(target_block); - // rococo_runtime::System::finalize(); - - // rococo_runtime::AllPalletsWithSystem::on_finalize(target_block); - // } pub fn go_to_next_block(initialize: bool, finalize: bool) { @@ -719,7 +729,7 @@ pub fn go_to_next_block(initialize: bool, finalize: bool) { } } -pub fn set_validation_data(next_block: u32, slot: Slot) { +pub fn set_validation_data(next_block: u32, _slot: Slot) { use basilisk_runtime::RuntimeOrigin; use frame_support::storage::storage_prefix; use polkadot_primitives::HeadData; @@ -728,7 +738,7 @@ pub fn set_validation_data(next_block: u32, slot: Slot) { let sproof_builder = RelayStateSproofBuilder { para_id: basilisk_runtime::ParachainInfo::parachain_id(), included_para_head: Some(parent_head.clone()), - current_slot: slot, + current_slot: (next_block as u64).into(), ..Default::default() }; @@ -752,17 +762,6 @@ pub fn set_validation_data(next_block: u32, slot: Slot) { sp_io::storage::clear(&storage_prefix(b"ParachainSystem", b"UnincludedSegment")); } -pub fn set_para_slot_info(number: u64) { - // sp_io::storage::clear(&frame_support::storage::storage_prefix( - // b"ParachainSystem", - // b"UnincludedSegment", - // )); - frame_support::storage::unhashed::put( - &frame_support::storage::storage_prefix(b"AuraExt", b"SlotInfo"), - &(Slot::from(number), 0), - ); -} - use xcm_emulator::pallet_message_queue; pub fn assert_xcm_message_processing_failed() { diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index cec3dbd1183..7cbfb151e6a 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -2,7 +2,6 @@ // Disable the integration tests when this feature is enabled. #![cfg(not(feature = "runtime-benchmarks"))] mod call_filter; -mod exchange_asset; mod fees; mod kusama_test_net; mod nft; diff --git a/integration-tests/src/non_native_fee.rs b/integration-tests/src/non_native_fee.rs index e1a8cbaf807..e929022ed29 100644 --- a/integration-tests/src/non_native_fee.rs +++ b/integration-tests/src/non_native_fee.rs @@ -5,12 +5,9 @@ use crate::kusama_test_net::*; use basilisk_runtime::{Balances, Currencies, MultiTransactionPayment, RuntimeOrigin, Tokens}; use frame_support::{ - assert_err, assert_ok, + assert_ok, dispatch::DispatchInfo, - sp_runtime::{ - traits::SignedExtension, - transaction_validity::{InvalidTransaction, TransactionValidityError}, - }, + sp_runtime::transaction_validity::{InvalidTransaction, TransactionValidityError}, weights::Weight, }; use hydradx_traits::AMM; @@ -18,6 +15,7 @@ use orml_traits::currency::MultiCurrency; use pallet_asset_registry::AssetType; use pallet_transaction_multi_payment::Price; use primitives::AssetId; +use sp_runtime::traits::DispatchTransaction; use xcm_emulator::TestExt; #[test] @@ -30,22 +28,18 @@ fn non_native_fee_payment_works_with_configured_price() { ); let info = DispatchInfo { - weight: Weight::from_parts(106_957_000, 0), + call_weight: Weight::from_parts(106_957_000, 0), ..Default::default() }; let len: usize = 10; assert_ok!( - pallet_transaction_payment::ChargeTransactionPayment::::from(0).pre_dispatch( - &AccountId::from(BOB), - &call, - &info, - len, - ) + pallet_transaction_payment::ChargeTransactionPayment::::from(0) + .validate_and_prepare(Some(AccountId::from(BOB)).into(), &call, &info, len, 0,) ); let bob_balance = basilisk_runtime::Tokens::free_balance(AUSD, &AccountId::from(BOB)); - assert_eq!(bob_balance, 999_999_992_137_669); + assert_eq!(bob_balance, 999_999_992_137_710); }); } @@ -60,7 +54,7 @@ fn non_native_fee_payment_works_with_oracle_price_based_on_onchain_route() { currency: NEW_TOKEN, }); let info = DispatchInfo { - weight: Weight::from_parts(106_957_000, 0), + call_weight: Weight::from_parts(106_957_000, 0), ..Default::default() }; let len: usize = 10; @@ -107,13 +101,10 @@ fn non_native_fee_payment_works_with_oracle_price_based_on_onchain_route() { )); // try and fail to pay with the new token - assert_err!( - pallet_transaction_payment::ChargeTransactionPayment::::from(0).pre_dispatch( - &AccountId::from(DAVE), - &call, - &info, - len, - ), + assert_eq!( + pallet_transaction_payment::ChargeTransactionPayment::::from(0) + .validate_and_prepare(Some(AccountId::from(DAVE)).into(), &call, &info, len, 0,) + .unwrap_err(), TransactionValidityError::from(InvalidTransaction::Payment) ); @@ -144,16 +135,12 @@ fn non_native_fee_payment_works_with_oracle_price_based_on_onchain_route() { // pay with the new token assert_ok!( - pallet_transaction_payment::ChargeTransactionPayment::::from(0).pre_dispatch( - &AccountId::from(DAVE), - &call, - &info, - len, - ) + pallet_transaction_payment::ChargeTransactionPayment::::from(0) + .validate_and_prepare(Some(AccountId::from(DAVE)).into(), &call, &info, len, 0,) ); let dave_balance = basilisk_runtime::Tokens::free_balance(NEW_TOKEN, &AccountId::from(DAVE)); - assert_eq!(dave_balance, 990_264_297_166_679); + assert_eq!(dave_balance, 990_264_347_751_724); }); } diff --git a/integration-tests/src/oracle.rs b/integration-tests/src/oracle.rs index 78d536b380d..02397cff068 100644 --- a/integration-tests/src/oracle.rs +++ b/integration-tests/src/oracle.rs @@ -3,8 +3,8 @@ use crate::kusama_test_net::*; use basilisk_runtime::{EmaOracle, RuntimeOrigin, XYKOracleSourceIdentifier, XYK}; +use basilisk_traits::oracle::{AggregatedPriceOracle, OraclePeriod::*}; use frame_support::assert_ok; -use hydradx_traits::{AggregatedPriceOracle, OraclePeriod::*}; use pallet_ema_oracle::OracleError; use xcm_emulator::TestExt; diff --git a/integration-tests/src/router.rs b/integration-tests/src/router.rs index d6cd09f6ee8..8afdc9fbee3 100644 --- a/integration-tests/src/router.rs +++ b/integration-tests/src/router.rs @@ -26,8 +26,8 @@ mod router_different_pools_tests { use basilisk_runtime::Router; use xcm_emulator::TestExt; + use basilisk_traits::router::PoolType; use frame_support::assert_ok; - use hydradx_traits::router::PoolType; use pallet_route_executor::Trade; use super::*; @@ -161,8 +161,8 @@ mod xyk_router_tests { use basilisk_runtime::Router; use xcm_emulator::TestExt; + use basilisk_traits::router::PoolType; use frame_support::{assert_noop, assert_ok}; - use hydradx_traits::router::PoolType; use pallet_route_executor::Trade; use super::*; @@ -804,8 +804,8 @@ mod lbp_router_tests { use basilisk_runtime::Router; use xcm_emulator::TestExt; + use basilisk_traits::router::PoolType; use frame_support::assert_ok; - use hydradx_traits::router::PoolType; use pallet_route_executor::Trade; use crate::router::*; diff --git a/integration-tests/src/transact_call_filter.rs b/integration-tests/src/transact_call_filter.rs index 666e59d4080..f8b166e2c0a 100644 --- a/integration-tests/src/transact_call_filter.rs +++ b/integration-tests/src/transact_call_filter.rs @@ -4,7 +4,7 @@ use crate::kusama_test_net::*; use frame_support::{assert_ok, dispatch::GetDispatchInfo}; use sp_runtime::codec::Encode; -use polkadot_xcm::v4::prelude::*; +use polkadot_xcm::v5::prelude::*; use xcm_emulator::TestExt; @@ -58,7 +58,7 @@ fn allowed_transact_call_should_pass_filter() { weight_limit: Unlimited, }, Transact { - require_weight_at_most: call.get_dispatch_info().weight, + fallback_max_weight: Some(call.get_dispatch_info().call_weight), origin_kind: OriginKind::SovereignAccount, call: basilisk_runtime::RuntimeCall::Currencies(call).encode().into(), }, @@ -149,7 +149,7 @@ fn blocked_transact_calls_should_not_pass_filter() { weight_limit: Unlimited, }, Transact { - require_weight_at_most: Weight::from_parts(10_000_000_000, 0u64), + fallback_max_weight: Some(Weight::from_parts(10_000_000_000, 0u64)), origin_kind: OriginKind::Native, call: basilisk_runtime::RuntimeCall::Treasury(call).encode().into(), }, @@ -225,7 +225,7 @@ fn safe_call_filter_should_respect_runtime_call_filter() { weight_limit: Unlimited, }, Transact { - require_weight_at_most: Weight::from_parts(1_000_000_000, 2653u64), + fallback_max_weight: Some(Weight::from_parts(1_000_000_000, 2653u64)), origin_kind: OriginKind::Native, call: basilisk_runtime::RuntimeCall::Uniques(call).encode().into(), }, diff --git a/launch-configs/zombienet/local.json b/launch-configs/zombienet/local.json index e6888f29856..a784b3d66df 100644 --- a/launch-configs/zombienet/local.json +++ b/launch-configs/zombienet/local.json @@ -50,7 +50,8 @@ "args": [ "--no-hardware-benchmarks", "--force-authoring", - "--database=paritydb" + "--database=paritydb", + "--pool-type=fork-aware" ] }, { @@ -60,7 +61,8 @@ "args": [ "--no-hardware-benchmarks", "--force-authoring", - "--database=paritydb" + "--database=paritydb", + "--pool-type=fork-aware" ] } ] diff --git a/math/Cargo.toml b/math/Cargo.toml new file mode 100644 index 00000000000..0deff4f07d4 --- /dev/null +++ b/math/Cargo.toml @@ -0,0 +1,37 @@ +[package] +authors = ['GalacticCouncil'] +edition = '2021' +homepage = 'https://github.com/galacticcouncil/hydradx-math' +license = 'Apache-2.0' +name = "basilisk-math" +description = "A collection of utilities to make performing liquidity pool calculations more convenient." +repository = 'https://github.com/galacticcouncil/hydradx-math' +version = "8.4.0" + +[dependencies] +primitive-types = { workspace = true } +# Added because of use of the FixedU128, used to implement `Ratio` +codec = { workspace = true, features = ["derive", "max-encoded-len"] } +scale-info = { workspace = true } +sp-arithmetic = { workspace = true } +sp-std = { workspace = true } +serde = { workspace = true } +num-traits = { workspace = true } +rand = { workspace = true, features = ["std_rng"] } + +hydra-dx-math = { workspace = true } + +[dev-dependencies] +proptest = { workspace = true } +rug = { workspace = true } +test-case = { workspace = true } + +[features] +default = ["std"] +std = [ + "codec/std", + "serde/std", + "sp-arithmetic/std", + "sp-std/std" +] +runtime-benchmarks = [] diff --git a/math/README.md b/math/README.md new file mode 100644 index 00000000000..77d521998a2 --- /dev/null +++ b/math/README.md @@ -0,0 +1,20 @@ +# hydraDX-math-helpers + +![example workflow](https://github.com/galacticcouncil/HydraDX-math/actions/workflows/tests.yml/badge.svg) +![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/galacticcouncil/HydraDX-math) + +A collection of utilities to make performing liquidity pool calculations more convenient. + +### Development + +This crate uses the [`rug` crate](https://crates.io/crates) for arbitrary precision math in tests +which depends on GMP under the hood. You will thus need to install the dependencies in order to be +able to run the tests. + +For Debian based systems +```sh +sudo apt install diffutils gcc m4 make +``` +should do the trick. + +See the `rug` docs [here](https://crates.io/crates/rug#using-rug) diff --git a/math/proptest-regressions/ema/invariants.txt b/math/proptest-regressions/ema/invariants.txt new file mode 100644 index 00000000000..16166de0d67 --- /dev/null +++ b/math/proptest-regressions/ema/invariants.txt @@ -0,0 +1,42 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc abec821adc4d6f531f3c98182f19e06d78de958953786d1d96bb3e520dd7c395 # shrinks to period = 2000000000000000000 +cc 77f840c7f76607867c737267a0992a0a0b4b2d7497c1b41f6b8f13f4df276103 # shrinks to smoothing = 9739961688584222, (prev_balance, incoming_balance) = (11056416052049, 18446744073709551615) +cc b1f65eb4e272d2cde1d2741deccb63242ce213831c30bec99656afdaedead601 # shrinks to smoothing = 1, (prev_balance, incoming_balance) = (3583904071919985516, 0) +cc f48b8a58b6e7602312bb7b14a7351d4ecfba57faeeeb69e67c19ba2a875cca98 # shrinks to smoothing = 166666667, iterations = 9 +cc 4f73e8148e172e2f43ab0e4a7195bfd64735280a4752cec13ac5db6d1e26a705 # shrinks to smoothing = 134438341, iterations = 93 +cc 7cdc87109e4394ac830b4a29e4dd781427afe1e4efdf7a6f8070cc79c7b65536 # shrinks to smoothing = 170005061, iterations = 5487 +cc b64dd6dd6ee16de91f517834efc2f9ef6886d1b3b102a97ac63d84fa221e0517 # shrinks to (smoothing, period) = (FixedU128(0.000138888888888888), 14399), (start_balance, incoming_balance) = (538686509725217712287442, 96117734629487432900618706) +cc 78e01143250f0cdb3f0d615ccf3e9a2dd89c5d8915d70b77e1ef782e26ca2ed0 # shrinks to (smoothing, period) = (FixedU128(0.000138888888888888), 14399), (start_balance, incoming_balance) = (6080793798739155567397, 97290591802259957192102914) +cc 2cbff43e667403ae7a143ad1301bdcfff7a4f93c500fc9d52ee71ea715238119 # shrinks to period = 834921, iterations = 26381 +cc eb7b922c3e65ee00cdd95f21f348f27e6c9348a90e7a1e123b9cc7dd40ec9ab8 # shrinks to period = 329568, iterations = 59434 +cc 5e6f637fd3a5e1e8d611c9804561f9a4f354140940ece2ab1fbf4bab230c1cf2 # shrinks to history = [(1431702168725732163623164190, 1), (9270214550274397946945479026, 64137), (1199962558090205922879252692, 111748), (2965905542316536899321670, 3052)], period = 114061 +cc 1d7b229a3a2b04852aa13d4a175f905b00e7d958efc98ec194f99fc7604c23f6 # shrinks to (first, second, third) = ((FixedU128(0.000000000000000000), 1), (FixedU128(10000000000.000000000000000000), 1), (FixedU128(0.000000000100000000), 1708959)), period = 48485 +cc 312b667e7f6bef532a7529f0fae7d7f9b7ee74aabd1451d197f2d86a17b9cc61 # shrinks to history = [(FixedU128(0.000000000000000000), 1), (FixedU128(10000000000.000000000000000000), 5), (FixedU128(0.000000000000005029), 392771)], period = 10914 +cc 1465b3d145191d0883635b7f02767b62b72e224dffcd8949878c63f07bab7a28 # shrinks to (period, history) = (33340, [(Rational128(1.1316), 1), (Rational128(2.1296), 11769)]) +cc f7b1c40bf98d06a8e01b5eb4870dd6bc837d6fedbe137eb42af31556650e6d75 # shrinks to (period, history) = (31053, [(Rational128(7.6470), 1), (Rational128(2.5107), 45024), (Rational128(0.4752), 49558), (Rational128(2.0159), 54224)]) +cc 5deb210a66bd8c5d88293f3c6e989edccc73d6c378a85d165184f42e4ec73754 # shrinks to (period, history) = (19782, [(Rational128(2.7131), 1), (Rational128(0.0343), 2428), (Rational128(2.9196), 6355)]) +cc e0a7d380297142ba6b51cc5e46bb3fd784ecb4fe3701f0f2502364793e46c4c0 # shrinks to (period, history) = (12266, [(Rational128(0.6243), 1), (Rational128(0.2173), 2157), (Rational128(0.1538), 141), (Rational128(0.2201), 4401), (Rational128(0.0369), 4679), (Rational128(1.3423), 3913), (Rational128(1.7269), 5496)]) +cc c6c9c8f0893557d4f17d0371200feee58910af5c426ce745b53271dca9d531d5 # shrinks to (period, history) = (13932, [(Rational128(0.9582), 1), (Rational128(0.4613), 1707), (Rational128(0.7781), 3842), (Rational128(1.0488), 180), (Rational128(1.2507), 6958)]) +cc 7ba2b7931c66eac9f6ed78ca7e3995f0c11d1c20e3a9a112a354b3b8a21c373c # shrinks to (period, history) = (63149, [(Rational128(0.2081), 1), (Rational128(4.1363), 8475), (Rational128(1.7487), 9686)]) +cc 647390ff0e87bc3ee3cb3dc41f9d5c878edb4a71bba39658e3b9d8796a0a0e60 # shrinks to (period, history) = (45601, [(Rational128(0.9444), 1), (Rational128(50.3758), 91), (Rational128(164.4235), 191)]) +cc c719ee1d8bc9e65fdde9772558249a3bad25c130236f9ca8f4ca523fb84eb1c5 # shrinks to smoothing = 0.00004808848280836739600865592690550613, price = (50, 12997644) +cc 1b4bb3a569ab43780bad69b0c397e7a9e827a618acbe87855a2498ba0251ef0a # shrinks to smoothing = 0.000051253139254779355235508174875711137, (n, d) = (50, 217194730) +cc 94e5627a31a334d408ed88bc409bae74da871e797c7cb0c6f2e2e5454cb773fa # shrinks to smoothing = 0.00028960324355632783087170576310454677, (n, d) = (2281576278019707174198467582691, 53153566379044363274733477818057705701) +cc 60c11e7ba33c227d5d10afc4f71f3ed8d9896a5d89129a03769b8a4791a7728e # shrinks to smoothing = 0.000062148472701283365961281501507100463, price = (50, 4236049749) +cc fd2df98065db7033c98571aa1bbe3ec94afa87d35df7b5d739a82b40f017e9a1 # shrinks to (period, iterations) = (10000, 1), (a, b) = (9827851985371652289712, 51132016236500145641), (c, d) = (50, 50) +cc 0a50cab67c5778bcc2ca54c39af26ef471c9eb822a1a06c25d10aea02c14e49e # shrinks to (period, iterations) = (10000, 1), (a, b) = (9225316072973789759273, 13526827768126688671), (c, d) = (50, 50) +cc f8c7e95627493ccd114518dae42b5c2a436d18a74f4e1cc0a8950e0d65d29336 # shrinks to (period, history) = (10000, [(Rational128(0.9299), 1), (Rational128(0.6038), 1), (Rational128(1.6072), 4418)]) +cc f6a22808f811b6f1caea259cbad512d82e737128f2d7ef661ed36cd070f64be5 # shrinks to (period, history) = (10000, [(Rational128(1.1836), 1), (Rational128(0.6469), 1), (Rational128(2.6856), 1), (Rational128(25.4812), 103)]) +cc f1b85917ca97bfba836e70e6cff2964ea03506085d9c2e0330e6dbe4e4d76309 # shrinks to ((a, b), (c, d)) = ((4772455530259671778783, 50), (475016747425314290123, 4650704057820710497266)) +cc af464757bfd7ff5e0137efd7d32fd88335d645c9186741a6726c4dbb66b2a7a7 # shrinks to (a, b) = (50, 8670891272984227710647), (c, d) = (5143818437214807880321, 9804129788684567) +cc fb5a554f4e5dcb088e665129ce430e3956e0f2b2665a0e8024d21ee9b8f64082 # shrinks to ((a, b), (c, d)) = ((334973391018050633, 5083571361808070355956), (332278759414046595, 5377440163690979518641)) +cc 8f2cb7293658b1d04c476d5384e639e706ca5662786b93746d6ae8186094012d # shrinks to smoothing = 0.18517827071738740306214709613857709917, (prev_price, incoming_price) = (Rational128(0.8553), Rational128(22.7081)) +cc 705bd304496a2879c0824170261e6b17049e2a7fb6fd67071c603962816f9b9c # shrinks to smoothing = 1, price = Rational128(3080132493312.0000) +cc 6addb5321fd6be2a2b050a8d3672dfafc1e4f3ac7bfd0e6927ae9211d7f0553c # shrinks to smoothing = 1, price = Rational128(2781519020032.0000), tolerance = 90 +cc 4234577b90ffc72f37dd4687b9cf38d3163d110eafc55cd02dd37dcb37a39f96 # shrinks to smoothing = 1, price = Rational128(54132.0938), tolerance = 96 +cc feec58cf49c8bf04f1b63e27d7b2a4b71430facb451fd65ab7d8c1e289556c8d # shrinks to smoothing = 1, price = Rational128(24900842553344.0000), tolerance = 80 diff --git a/math/src/ema/math.rs b/math/src/ema/math.rs new file mode 100644 index 00000000000..01dab52d599 --- /dev/null +++ b/math/src/ema/math.rs @@ -0,0 +1,291 @@ +use crate::ratio::Ratio; +use hydra_dx_math::fraction; +use hydra_dx_math::support::rational::Rounding; +use hydra_dx_math::to_u128_wrapper; +use hydra_dx_math::transcendental::saturating_powi_high_precision; +use hydra_dx_math::types::{Balance, Fraction}; + +use num_traits::{One, Zero}; +use primitive_types::{U128, U256, U512}; + +/// EmaPrice is a rational number represented by a `u128` for both numerator and denominator. +pub type EmaPrice = Ratio; +pub type EmaVolume = (Balance, Balance, Balance, Balance); +pub type EmaLiquidity = (Balance, Balance); + +/// Calculate the new oracle values by integrating `incoming` values with the `previous` oracle. +/// Uses a weighted average based on the `smoothing` factor. +pub fn calculate_new_by_integrating_incoming( + previous: (EmaPrice, EmaVolume, EmaLiquidity), + incoming: (EmaPrice, EmaVolume, EmaLiquidity), + smoothing: Fraction, +) -> (EmaPrice, EmaVolume, EmaLiquidity) { + let (prev_price, prev_volume, prev_liquidity) = previous; + let (incoming_price, incoming_volume, incoming_liquidity) = incoming; + let new_price = price_weighted_average(prev_price, incoming_price, smoothing); + let new_volume = volume_weighted_average(prev_volume, incoming_volume, smoothing); + let new_liquidity = liquidity_weighted_average(prev_liquidity, incoming_liquidity, smoothing); + (new_price, new_volume, new_liquidity) +} + +/// Calculate the current oracle values from the `outdated` and `update_with` values using the `smoothing` factor with the old values being `iterations` out of date. +/// +/// Note: The volume is always updated with zero values so it is not a parameter. +pub fn update_outdated_to_current( + iterations: u32, + outdated: (EmaPrice, EmaVolume, EmaLiquidity), + update_with: (EmaPrice, EmaLiquidity), + smoothing: Fraction, +) -> (EmaPrice, EmaVolume, EmaLiquidity) { + let (prev_price, prev_volume, prev_liquidity) = outdated; + let (incoming_price, incoming_liquidity) = update_with; + let smoothing = exp_smoothing(smoothing, iterations); + let new_price = price_weighted_average(prev_price, incoming_price, smoothing); + let new_volume = volume_weighted_average(prev_volume, (0, 0, 0, 0), smoothing); + let new_liquidity = liquidity_weighted_average(prev_liquidity, incoming_liquidity, smoothing); + (new_price, new_volume, new_liquidity) +} + +/// Calculate the iterated exponential moving average for the given prices. +/// `iterations` is the number of iterations of the EMA to calculate. +/// `prev` is the previous oracle value, `incoming` is the new value to integrate. +/// `smoothing` is the smoothing factor of the EMA. +pub fn iterated_price_ema(iterations: u32, prev: EmaPrice, incoming: EmaPrice, smoothing: Fraction) -> EmaPrice { + price_weighted_average(prev, incoming, exp_smoothing(smoothing, iterations)) +} + +/// Calculate the iterated exponential moving average for the given balances. +/// `iterations` is the number of iterations of the EMA to calculate. +/// `prev` is the previous oracle value, `incoming` is the new value to integrate. +/// `smoothing` is the smoothing factor of the EMA. +pub fn iterated_balance_ema(iterations: u32, prev: Balance, incoming: Balance, smoothing: Fraction) -> Balance { + balance_weighted_average(prev, incoming, exp_smoothing(smoothing, iterations)) +} + +/// Calculate the iterated exponential moving average for the givenEmaVolumes. +/// `iterations` is the number of iterations of the EMA to calculate. +/// `prev` is the previous oracle value; the incoming value is always zero. +/// `smoothing` is the smoothing factor of the EMA. +pub fn iterated_volume_ema(iterations: u32, prev: EmaVolume, smoothing: Fraction) -> EmaVolume { + volume_weighted_average(prev, (0, 0, 0, 0), exp_smoothing(smoothing, iterations)) +} + +/// Calculate the iterated exponential moving average for the given balances. +/// `iterations` is the number of iterations of the EMA to calculate. +/// `prev` is the previous oracle value, `incoming` is the new value to integrate. +/// `smoothing` is the smoothing factor of the EMA. +pub fn iterated_liquidity_ema( + iterations: u32, + prev: EmaLiquidity, + incoming: EmaLiquidity, + smoothing: Fraction, +) -> EmaLiquidity { + liquidity_weighted_average(prev, incoming, exp_smoothing(smoothing, iterations)) +} + +/// Calculate the smoothing factor for a period from a given combination of original smoothing +/// factor and iterations by exponentiating the complement by the iterations. +/// +/// Example: +/// `exp_smoothing(0.6, 2) = 1 - (1 - 0.6)^2 = 1 - 0.40^2 = 1 - 0.16 = 0.84` +/// +/// ```ignore +/// # use hydra_dx_math::ema::exp_smoothing; +/// # use hydra_dy_math::types::Fraction; +/// assert_eq!(exp_smoothing(Fraction::from_num(0.6), 2), FixedU128::from_num(0.84)); +/// ``` +pub fn exp_smoothing(smoothing: Fraction, iterations: u32) -> Fraction { + debug_assert!(smoothing <= Fraction::one()); + let complement = Fraction::one() - smoothing; + // in order to determine the iterated smoothing factor we exponentiate the complement + let exp_complement: Fraction = saturating_powi_high_precision(complement, iterations); + debug_assert!(exp_complement <= Fraction::one()); + Fraction::one() - exp_complement +} + +/// Calculates smoothing factor alpha for an exponential moving average based on `period`: +/// `alpha = 2 / (period + 1)`. It leads to the "center of mass" of the EMA corresponding to be the +/// "center of mass" of a `period`-length SMA. +/// +/// Possible alternatives for `alpha = 2 / (period + 1)`: +/// + `alpha = 1 - 0.5^(1 / period)` for a half-life of `period` or +/// + `alpha = 1 - 0.5^(2 / period)` to have the same median as a `period`-length SMA. +/// See https://en.wikipedia.org/wiki/Moving_average#Relationship_between_SMA_and_EMA +/// +/// Note: Not used in the pallet except to check configured values. Not meant to be used by code +/// interacting with the pallet. Use the configured values. +pub fn smoothing_from_period(period: u64) -> Fraction { + fraction::frac(2, u128::from(period.max(1)).saturating_add(1)) +} + +/// Calculate a weighted average for the given prices. +/// `prev` is the previous oracle value, `incoming` is the new value to integrate. +/// `weight` is how much weight to give the new value. +/// +/// Note: Rounding is biased towards `prev`. +pub fn price_weighted_average(prev: EmaPrice, incoming: EmaPrice, weight: Fraction) -> EmaPrice { + debug_assert!(weight <= Fraction::one(), "weight must be <= 1"); + if incoming >= prev { + rounding_add(prev, multiply(weight, saturating_sub(incoming, prev)), Rounding::Down) + } else { + rounding_sub(prev, multiply(weight, saturating_sub(prev, incoming)), Rounding::Up) + } +} + +/// Calculate a weighted average for the given balances. +/// `prev` is the previous oracle value, `incoming` is the new value to integrate. +/// `weight` is how much weight to give the new value. +/// +/// Note: Rounding is biased towards `prev`. +pub fn balance_weighted_average(prev: Balance, incoming: Balance, weight: Fraction) -> Balance { + debug_assert!(weight <= Fraction::one(), "weight must be <= 1"); + if incoming >= prev { + // Safe to use bare `+` because `weight <= 1` and `a + (b - a) <= b`. + // Safe to use bare `-` because of the conditional. + prev + fraction::multiply_by_balance(weight, incoming - prev) + } else { + // Safe to use bare `-` because `weight <= 1` and `a - (a - b) >= 0` and the conditional. + prev - fraction::multiply_by_balance(weight, prev - incoming) + } +} + +/// Calculate a weighted average for the givenEmaVolumes. +/// `prev` is the previous oracle value, `incoming` is the new value to integrate. +/// `weight` is how much weight to give the new value. +/// +/// Note: Just delegates to `balance_weighted_average` under the hood. +/// Note: Rounding is biased towards `prev`. +pub fn volume_weighted_average(prev: EmaVolume, incoming: EmaVolume, weight: Fraction) -> EmaVolume { + debug_assert!(weight <= Fraction::one(), "weight must be <= 1"); + let (prev_a_in, prev_b_out, prev_a_out, prev_b_in) = prev; + let (a_in, b_out, a_out, b_in) = incoming; + ( + balance_weighted_average(prev_a_in, a_in, weight), + balance_weighted_average(prev_b_out, b_out, weight), + balance_weighted_average(prev_a_out, a_out, weight), + balance_weighted_average(prev_b_in, b_in, weight), + ) +} + +/// Calculate a weighted average for the givenEmaLiquidity values. +/// `prev` is the previous oracle value, `incoming` is the new value to integrate. +/// `weight` is how much weight to give the new value. +/// +/// Note: Just delegates to `balance_weighted_average` under the hood. +/// Note: Rounding is biased towards `prev`. +pub fn liquidity_weighted_average( + prev: (Balance, Balance), + incoming: (Balance, Balance), + weight: Fraction, +) -> (Balance, Balance) { + debug_assert!(weight <= Fraction::one(), "weight must be <= 1"); + let (prev_a, prev_b) = prev; + let (a, b) = incoming; + ( + balance_weighted_average(prev_a, a, weight), + balance_weighted_average(prev_b, b, weight), + ) +} + +// Utility functions for working with rational numbers. + +/// Subtract `r` from `l` and return a tuple of `U256` for full precision. +/// Saturates if `r >= l`. +pub(super) fn saturating_sub(l: EmaPrice, r: EmaPrice) -> (U256, U256) { + if l.n.is_zero() || r.n.is_zero() { + return (l.n.into(), l.d.into()); + } + let (l_n, l_d, r_n, r_d) = to_u128_wrapper!(l.n, l.d, r.n, r.d); + // n = l.n * r.d - r.n * l.d + let n = l_n.full_mul(r_d).saturating_sub(r_n.full_mul(l_d)); + // d = l.d * r.d + let d = l_d.full_mul(r_d); + (n, d) +} + +/// Multiply a `Fraction` `f` with a rational number of `U256`s, returning a tuple of `U512`s for full +/// precision. +pub(super) fn multiply(f: Fraction, (r_n, r_d): (U256, U256)) -> (U512, U512) { + debug_assert!(f <= Fraction::ONE); + if f.is_zero() || r_n.is_zero() { + return (U512::zero(), U512::one()); + } else if f.is_one() { + return (r_n.into(), r_d.into()); + } + // n = l.n * f.to_bits + let n = r_n.full_mul(U256::from(f.to_bits())); + // d = l.d * DIV + let d = r_d.full_mul(U256::from(hydra_dx_math::fraction::DIV)); + (n, d) +} + +/// Reduce the precision of a 512 bit rational number to 383 bits. +/// The rounding is done by shifting which implicitly rounds down both numerator and denominator. +/// This can effectivly round the complete rational number up or down pseudo-randomly. +/// Specify `rounding` other than `Nearest` to round the whole number up or down. +pub(super) fn round((n, d): (U512, U512), rounding: Rounding) -> (U512, U512) { + let shift = n.bits().max(d.bits()).saturating_sub(383); // anticipate the saturating_add + if shift > 0 { + let min_n = if n.is_zero() { U512::zero() } else { U512::one() }; + let (bias_n, bias_d) = rounding.to_bias(1); + ( + (n >> shift).saturating_add(bias_n.into()).max(min_n), + (d >> shift).saturating_add(bias_d.into()).max(U512::one()), + ) + } else { + (n, d) + } +} + +/// Round a 512 bit rational number to a 128 bit rational number. +/// The rounding is done by shifting which implicitly rounds down both numerator and denominator. +/// This can effectivly round the complete rational number up or down pseudo-randomly. +/// Specify `rounding` other than `Nearest` to round the whole number up or down. +pub(super) fn round_to_rational((n, d): (U512, U512), rounding: Rounding) -> EmaPrice { + let shift = n.bits().max(d.bits()).saturating_sub(128); + let (n, d) = if shift > 0 { + let min_n = if n.is_zero() { 0 } else { 1 }; + let (bias_n, bias_d) = rounding.to_bias(1); + let shifted_n = (n >> shift).low_u128(); + let shifted_d = (d >> shift).low_u128(); + ( + shifted_n.saturating_add(bias_n).max(min_n), + shifted_d.saturating_add(bias_d).max(1), + ) + } else { + (n.low_u128(), d.low_u128()) + }; + EmaPrice::new(n, d) +} + +/// Add `l` and `r` and round the result to a 128 bit rational number. +/// The precision of `r` is reduced to 383 bits so the multiplications don't saturate. +pub(super) fn rounding_add(l: EmaPrice, (r_n, r_d): (U512, U512), rounding: Rounding) -> EmaPrice { + if l.is_zero() { + return round_to_rational((r_n, r_d), Rounding::Nearest); + } else if r_n.is_zero() { + return l; + } + let (l_n, l_d) = (U512::from(l.n), U512::from(l.d)); + let (r_n, r_d) = round((r_n, r_d), rounding); + // n = l.n * r.d + r.n * l.d + let n = l_n.saturating_mul(r_d).saturating_add(r_n.saturating_mul(l_d)); + // d = l.d * r.d + let d = l_d.saturating_mul(r_d); + round_to_rational((n, d), rounding) +} + +/// Subract `l` and `r` (saturating) and round the result to a 128 bit rational number. +/// The precision of `r` is reduced to 383 bits so the multiplications don't saturate. +pub(super) fn rounding_sub(l: EmaPrice, (r_n, r_d): (U512, U512), rounding: Rounding) -> EmaPrice { + if l.is_zero() || r_n.is_zero() { + return l; + } + let (l_n, l_d) = (U512::from(l.n), U512::from(l.d)); + let (r_n, r_d) = round((r_n, r_d), rounding); + // n = l.n * r.d - r.n * l.d + let n = l_n.saturating_mul(r_d).saturating_sub(r_n.saturating_mul(l_d)); + // d = l.d * r.d + let d = l_d.saturating_mul(r_d); + round_to_rational((n, d), rounding) +} diff --git a/math/src/ema/mod.rs b/math/src/ema/mod.rs new file mode 100644 index 00000000000..80e57c39f10 --- /dev/null +++ b/math/src/ema/mod.rs @@ -0,0 +1,6 @@ +mod math; + +#[cfg(test)] +mod tests; + +pub use math::*; diff --git a/math/src/ema/tests/high_precision.rs b/math/src/ema/tests/high_precision.rs new file mode 100644 index 00000000000..a870d63170d --- /dev/null +++ b/math/src/ema/tests/high_precision.rs @@ -0,0 +1,188 @@ +use crate::ema::EmaPrice; +use crate::test_utils::{fraction_to_high_precision, into_rounded_integer}; +use hydra_dx_math::fraction; +use hydra_dx_math::types::Balance; + +use num_traits::{One, Pow}; +use proptest::prelude::*; +use rug::ops::PowAssign; +use rug::{Integer, Rational}; +use std::ops::{Mul, ShrAssign}; + +/// Round the given `r` to a close number where numerator and denominator have <= 256 bits. +pub(crate) fn round(r: &mut Rational) { + r.mutate_numer_denom(|n, d| { + let n_digits = n.significant_digits::(); + let d_digits = d.significant_digits::(); + if n_digits > 256 || d_digits > 256 { + let shift = n_digits.saturating_sub(256).max(d_digits.saturating_sub(256)); + n.shr_assign(shift); + d.shr_assign(shift); + } + }); +} + +/// Calculate the power of `r` via stepwise squaring and rounding to keep the memory size of `r` +/// within reasonable bounds. +/// +/// Much faster for big `i` but less accurate than the built-in `pow` function. +pub(crate) fn stepwise_pow_approx(mut r: Rational, i: u32) -> Rational { + if i <= 256 { + return r.pow(i); + } + let next_power = i.next_power_of_two(); + let mut iter = if next_power == i { i } else { next_power / 2 }; + let rest = i - iter; + let mut res_rest = stepwise_pow_approx(r.clone(), rest); + round(&mut res_rest); + while iter > 1 { + iter /= 2; + r.pow_assign(2); + round(&mut r); + } + r * res_rest +} + +/// Determine the smoothing factor from the given `period` as an arbitrary precision `Rational`. +pub fn smoothing_from_period(period: u64) -> Rational { + Rational::from((2u64, period.max(1).saturating_add(1))) +} + +/// Determine the final smoothing factor from initial `smoothing` and the number of `iterations`. +/// +/// Uses a `pow` approximation with 256 bit precision to reduce execution time. +pub fn precise_exp_smoothing(smoothing: Rational, iterations: u32) -> Rational { + debug_assert!(smoothing <= Rational::one()); + let complement = Rational::one() - smoothing; + // in order to determine the iterated smoothing factor we exponentiate the complement + let exp_complement = stepwise_pow_approx(complement, iterations); + debug_assert!(exp_complement <= Rational::one()); + Rational::one() - exp_complement +} + +/// Calculate the weighted average for the given balances by using arbitrary precision math. +/// +/// Note: Rounding is biased very slightly towards `incoming` (on equal distance rounds away from +/// zero). +pub fn precise_balance_weighted_average(prev: Balance, incoming: Balance, weight: Rational) -> Integer { + if incoming >= prev { + prev + into_rounded_integer(weight.mul(incoming - prev)) + } else { + prev - into_rounded_integer(weight.mul(prev - incoming)) + } +} + +/// Calculate the weighted average for the given values by using arbitrary precision math. +/// Returns a `Rational` of arbitrary precision. +pub fn precise_weighted_average(prev: Rational, incoming: Rational, weight: Rational) -> Rational { + prev.clone() + weight.mul(incoming - prev) +} + +/// Determine the exponential moving average of a history of balance values. +/// Starts the EMA with the first value. +/// Keeps track of arbitrary precision values during calculation but returns an `Integer` (rounded down). +pub fn naive_precise_balance_ema(history: Vec, smoothing: Rational) -> Integer { + assert!(!history.is_empty()); + let mut current = Rational::from(history[0]); + for balance in history.into_iter().skip(1) { + current = precise_weighted_average(current.clone(), balance.into(), smoothing.clone()); + } + // return rounded down integer + into_rounded_integer(current) +} + +/// Determine the exponential moving average of a history of balance values. +/// Starts the EMA with the first value. +/// Returns an arbitrary sized `Integer`. +/// Uses a `pow` approximation with 256 bit precision to reduce execution time. +pub fn precise_balance_ema(history: Vec<(Balance, u32)>, smoothing: Rational) -> Integer { + assert!(!history.is_empty()); + let mut current = Rational::from((history[0].0, 1)); + for (balance, iterations) in history.into_iter().skip(1) { + let smoothing_adj = precise_exp_smoothing(smoothing.clone(), iterations); + current = precise_weighted_average(current.clone(), balance.into(), smoothing_adj.clone()); + } + into_rounded_integer(current) +} + +/// Determine the exponential moving average of a history of price values. +/// Starts the EMA with the first value. +/// Returns an arbitrary precision `Rational` number. +pub fn naive_precise_price_ema(history: Vec, smoothing: Rational) -> Rational { + assert!(!history.is_empty()); + let mut current = Rational::from(history[0]); + for price in history.into_iter().skip(1) { + current = precise_weighted_average(current.clone(), Rational::from(price), smoothing.clone()); + } + current +} + +/// Determine the exponential moving average of a history of price values. +/// Starts the EMA with the first value. +/// Returns an arbitrary precision `Rational` number. +/// Uses a `pow` approximation with 256 bit precision to reduce execution time. +pub fn precise_price_ema(history: Vec<(EmaPrice, u32)>, smoothing: Rational) -> Rational { + assert!(!history.is_empty()); + let mut current = Rational::from(history[0].0); + for (price, iterations) in history.into_iter().skip(1) { + let smoothing_adj = precise_exp_smoothing(smoothing.clone(), iterations); + current = precise_weighted_average(current.clone(), Rational::from(price), smoothing_adj.clone()); + } + current +} + +// --- Tests + +#[test] +fn precise_balance_ema_works() { + let history = vec![1e12 as Balance, 2e12 as Balance, 3e12 as Balance, 4e12 as Balance]; + let smoothing = fraction::frac(1, 4); + let expected = { + let res = + ((Rational::from(history[0]) * 3 / 4 + history[1] / 4) * 3 / 4 + history[2] / 4) * 3 / 4 + history[3] / 4; + into_rounded_integer(res) + }; + let naive_ema = naive_precise_balance_ema(history.clone(), fraction_to_high_precision(smoothing)); + assert_eq!(expected, naive_ema); + let history = history.into_iter().map(|b| (b, 1)).collect(); + let ema = precise_balance_ema(history, fraction_to_high_precision(smoothing)); + assert_eq!(expected, ema); +} + +#[test] +fn precise_price_ema_works() { + let history = vec![ + EmaPrice::new(1, 8), + EmaPrice::new(1, 1), + EmaPrice::new(8, 1), + EmaPrice::new(4, 1), + ]; + let smoothing = fraction::frac(1, 4); + let expected = ((Rational::from(history[0]) * 3 / 4 + Rational::from(history[1]) / 4) * 3 / 4 + + Rational::from(history[2]) / 4) + * 3 / 4 + + Rational::from(history[3]) / 4; + let naive_ema = naive_precise_price_ema(history.clone(), fraction_to_high_precision(smoothing)); + assert_eq!(expected, naive_ema); + let history = history.into_iter().map(|p| (p, 1)).collect(); + let ema = precise_price_ema(history, fraction_to_high_precision(smoothing)); + assert_eq!(expected, ema); +} + +fn small_rational_close_to_one() -> impl Strategy { + (1u64..1_000, 5_000u64..200_000).prop_map(|(a, b)| Rational::one() - Rational::from((a, b))) +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(64))] + #[test] + fn stepwise_pow_close_enough( + num in small_rational_close_to_one(), + exponent in 1u32..200_000, + ) { + let res_pow = num.clone().pow(exponent); + let res_step = stepwise_pow_approx(num, exponent); + let boundary = Rational::from((1, u128::MAX)); + prop_assert!((res_pow - res_step).abs() < boundary); + } +} diff --git a/math/src/ema/tests/invariants.rs b/math/src/ema/tests/invariants.rs new file mode 100644 index 00000000000..a5c613c0091 --- /dev/null +++ b/math/src/ema/tests/invariants.rs @@ -0,0 +1,573 @@ +use super::high_precision; + +use crate::ema::*; +use crate::test_utils::{ + any_rational, bigger_and_smaller_rational, fraction_to_high_precision, prop_assert_approx_eq, + prop_assert_rational_approx_eq, prop_assert_rational_relative_approx_eq, +}; +use crate::test_utils::{MAX_BALANCE, MIN_BALANCE}; +use hydra_dx_math::fraction; +use hydra_dx_math::support::rational::Rounding; +use hydra_dx_math::types::{Balance, Fraction}; + +use proptest::prelude::*; + +use rug::Rational; +use sp_arithmetic::traits::{One, Zero}; + +/// 2 weeks at 6s block time +pub const MAX_ITERATIONS: u32 = 201_600; + +// +// --- Strategies +// + +/// Strategy for generating a random fixed point number between near 0 and 1. +fn fraction_above_zero_and_less_or_equal_one() -> impl Strategy { + (1..fraction::DIV).prop_map(Fraction::from_bits) +} + +fn typical_period() -> impl Strategy { + 1_u64..110_000 +} + +fn long_period() -> impl Strategy { + 10_000_u64..110_000 +} + +fn realistic_balance() -> impl Strategy { + MIN_BALANCE..MAX_BALANCE +} + +fn iterations_up_to(max: u32) -> impl Strategy { + 1_u32..max +} + +fn iterations() -> impl Strategy { + 1_u32..MAX_ITERATIONS +} + +fn high_balance() -> impl Strategy { + MIN_BALANCE..(MAX_BALANCE * 1000) +} + +fn realistic_price() -> impl Strategy { + (MIN_BALANCE..MAX_BALANCE, MIN_BALANCE..MAX_BALANCE).prop_map(|(n, d)| EmaPrice::new_unchecked(n, d)) +} + +fn any_price() -> impl Strategy { + any_rational().prop_map(|(n, d)| EmaPrice::new_unchecked(n, d)) +} + +fn any_volume() -> impl Strategy { + (any::(), any::(), any::(), any::()) +} + +fn any_liquidity() -> impl Strategy { + (any::(), any::()) +} + +fn period_fraction() -> impl Strategy { + (typical_period()).prop_map(smoothing_from_period) +} + +prop_compose! { + fn period_and_iterations()(p in long_period())( + period in Just(p), + iterations in iterations_up_to(p as u32 * 2), + ) -> (u64, u32) { + (period, iterations) + } +} + +fn ema_price_history() -> impl Strategy> { + prop::collection::vec( + ( + any_rational().prop_map(|(n, d)| EmaPrice::new_unchecked(n, d)), + iterations(), + ), + 2..50, + ) +} + +prop_compose! { + fn ema_balance_crash_history()(p in long_period())( + period in Just(p), + initial_balance in realistic_balance(), + big_balance in (1e16 as Balance)..MAX_BALANCE, big_iter in iterations_up_to(p as u32 * 2), + small_balance in MIN_BALANCE..100_000, small_iter in iterations_up_to(p as u32 * 2) + ) -> (u64, Vec<(Balance, u32)>) { + (period, vec![ + (initial_balance, 1), + (big_balance, big_iter), + (small_balance, small_iter) + ]) + } +} + +fn ema_balance_history() -> impl Strategy> { + prop::collection::vec(((1e6 as Balance)..(1e28 as Balance), 1_u32..MAX_ITERATIONS), 2..50) +} + +// +// --- Tests +// +proptest! { + #[test] + fn price_ema_stays_stable_if_the_value_does_not_change( + smoothing in period_fraction(), + price in realistic_price(), + ) { + let next_price = price_weighted_average(price, price, smoothing); + prop_assert_eq!(next_price, price); + } +} + +proptest! { + #[test] + fn balance_ema_stays_stable_if_the_value_does_not_change( + smoothing in fraction_above_zero_and_less_or_equal_one(), + balance in any::() + ) { + let next_balance = balance_weighted_average(balance, balance, smoothing); + prop_assert_eq!(next_balance, balance); + } +} + +proptest! { + #[test] + fn volume_ema_stays_stable_if_the_value_does_not_change( + smoothing in fraction_above_zero_and_less_or_equal_one(), + volume in any_volume() + ) { + let next_volume = volume_weighted_average(volume, volume, smoothing); + prop_assert_eq!(next_volume, volume); + } +} + +proptest! { + #[test] + fn iterated_volume_ema_approaches_zero( + smoothing in fraction_above_zero_and_less_or_equal_one(), + iterations in 1_u32..MAX_ITERATIONS, + volume in any_volume() + ) { + let next_volume = iterated_volume_ema(iterations, volume, smoothing); + let expected = ( + iterated_balance_ema(iterations, volume.0, 0, smoothing), + iterated_balance_ema(iterations, volume.1, 0, smoothing), + iterated_balance_ema(iterations, volume.2, 0, smoothing), + iterated_balance_ema(iterations, volume.3, 0, smoothing), + ); + prop_assert_eq!(next_volume, expected); + } +} + +proptest! { + #[test] + fn iterated_liquidity_ema_is_same_as_two_balance_emas( + smoothing in fraction_above_zero_and_less_or_equal_one(), + iterations in 1_u32..MAX_ITERATIONS, + (prev, incoming) in (any_liquidity(), any_liquidity()), + ) { + let next_liquidity = iterated_liquidity_ema(iterations, prev, incoming, smoothing); + let expected = ( + iterated_balance_ema(iterations, prev.0, incoming.0, smoothing), + iterated_balance_ema(iterations, prev.1, incoming.1, smoothing), + ); + prop_assert_eq!(next_liquidity, expected); + } +} + +proptest! { + #[test] + fn one_price_iteration_ema_is_same_as_simple_version( + smoothing in fraction_above_zero_and_less_or_equal_one(), + (prev_price, incoming_price) in (any_price(), any_price()) + ) { + let iter_price = iterated_price_ema(1, prev_price, incoming_price, smoothing); + let simple_price = price_weighted_average(prev_price, incoming_price, smoothing); + prop_assert_eq!(iter_price, simple_price); + } +} + +proptest! { + #[test] + fn calculate_new_by_integrating_incoming_is_same_as_weighted_average( + smoothing in fraction_above_zero_and_less_or_equal_one(), + (prev_price, incoming_price) in (any_price(), any_price()), + (prev_volume, incoming_volume) in (any_volume(), any_volume()), + (prev_liquidity, incoming_liquidity) in (any_liquidity(), any_liquidity()), + ) { + let simple_price = price_weighted_average(prev_price, incoming_price, smoothing); + let simple_volume = volume_weighted_average(prev_volume, incoming_volume, smoothing); + let simple_liquidity = liquidity_weighted_average(prev_liquidity, incoming_liquidity, smoothing); + let new_oracle = calculate_new_by_integrating_incoming((prev_price, prev_volume, prev_liquidity), (incoming_price, incoming_volume, incoming_liquidity), smoothing); + prop_assert_eq!(new_oracle, (simple_price, simple_volume, simple_liquidity)); + } +} + +proptest! { + #[test] + fn update_outdated_to_current_is_same_as_iterated_ema( + smoothing in fraction_above_zero_and_less_or_equal_one(), + iterations in 1_u32..MAX_ITERATIONS, + (prev_price, incoming_price) in (any_price(), any_price()), + prev_volume in any_volume(), + (prev_liquidity, incoming_liquidity) in (any_liquidity(), any_liquidity()), + ) { + let iterated_price = iterated_price_ema(iterations, prev_price, incoming_price, smoothing); + let iterated_volume = iterated_volume_ema(iterations, prev_volume, smoothing); + let iterated_liquidity = iterated_liquidity_ema(iterations, prev_liquidity, incoming_liquidity, smoothing); + let current_oracle = update_outdated_to_current(iterations, (prev_price, prev_volume, prev_liquidity), (incoming_price, incoming_liquidity), smoothing); + prop_assert_eq!(current_oracle, (iterated_price, iterated_volume, iterated_liquidity)); + } +} + +proptest! { + #[test] + fn one_balance_iteration_ema_is_same_as_simple_version( + smoothing in fraction_above_zero_and_less_or_equal_one(), + (prev_balance, incoming_balance) in (any::(), any::()) + ) { + let iter_balance = iterated_balance_ema(1, prev_balance, incoming_balance, smoothing); + let simple_balance = balance_weighted_average(prev_balance, incoming_balance, smoothing); + prop_assert_eq!(iter_balance, simple_balance); + } +} + +proptest! { + #[test] + fn new_balance_oracle_is_between_old_and_new_value( + smoothing in fraction_above_zero_and_less_or_equal_one(), + iterations in any::(), + (prev_balance, incoming_balance) in + (0..(Balance::MAX - 1)).prop_perturb(|n, mut rng| (n, rng.gen_range(n..Balance::MAX))) + ) { + let balance = iterated_balance_ema(iterations, prev_balance, incoming_balance, smoothing); + prop_assert!(balance <= incoming_balance, "{balance} not <= {incoming_balance}"); + prop_assert!(prev_balance <= balance, "{prev_balance} not <= {balance}"); + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1_000))] + #[test] + fn new_price_oracle_is_between_old_and_new_value_where_incoming_is_greater( + smoothing in fraction_above_zero_and_less_or_equal_one(), + i in iterations(), + ((incoming_n, incoming_d), (prev_n, prev_d)) in + bigger_and_smaller_rational(1, MAX_BALANCE * 1_000) + ) { + let prev_price = EmaPrice::new(prev_n, prev_d); + let incoming_price = EmaPrice::new(incoming_n, incoming_d); + let price = iterated_price_ema(i, prev_price, incoming_price, smoothing); + prop_assert!(prev_price <= price); + prop_assert!(price <= incoming_price); + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1_000))] + #[test] + fn new_price_oracle_is_between_old_and_new_value_where_previous_is_greater( + smoothing in fraction_above_zero_and_less_or_equal_one(), + i in iterations(), + ((prev_n, prev_d), (incoming_n, incoming_d)) in + bigger_and_smaller_rational(1, MAX_BALANCE * 1_000) + ) { + let prev_price = EmaPrice::new_unchecked(prev_n, prev_d); + let incoming_price = EmaPrice::new_unchecked(incoming_n, incoming_d); + let price = iterated_price_ema(i, prev_price, incoming_price, smoothing); + prop_assert!(incoming_price <= price); + prop_assert!(price <= prev_price); + } +} + +proptest! { + #[test] + fn balance_weighted_averages_work_on_typical_values_with_typical_smoothing( + period in typical_period(), + (start_balance, incoming_balance) in + (1e6 as Balance..(1e26 as Balance)) + .prop_perturb(|n, mut rng| (n, rng.gen_range(n..(1e26 as Balance)))) + ) { + let smoothing = smoothing_from_period(period); + let next_balance = balance_weighted_average(start_balance, incoming_balance, smoothing); + let expected: Rational = + start_balance + Rational::from(incoming_balance - start_balance) * 2 / (period + 1); + let tolerance = 1; + let expected_balance = expected.round(); + prop_assert_approx_eq!( + next_balance, + expected_balance, + tolerance, + "averaged balance values should be within tolerance of the expected value" + ); + } +} + +proptest! { + #[test] + fn smoothing_is_greater_zero_and_less_equal_one( + // We run into precision issues eventually, but any sane period value will be <10M + period in 0_u64..2_000_000_000_000_000_000, + ) { + let smoothing = smoothing_from_period(period); + prop_assert!(smoothing > Fraction::zero()); + prop_assert!(smoothing <= Fraction::one()); + } +} + +proptest! { + #[test] + fn smoothing_precision( + // We run into precision issues eventually, but any sane period value will be <10M + period in 0_u64..2_000_000_000_000_000_000, + ) { + let smoothing = smoothing_from_period(period); + let rug_smoothing = high_precision::smoothing_from_period(period); + let epsilon = Rational::from((1, 1e18 as u128)); + let smoothing = fraction_to_high_precision(smoothing); + prop_assert_rational_approx_eq!(smoothing, rug_smoothing, epsilon); + } +} + +proptest! { + #[test] + fn no_precision_loss_for_balances( + smoothing in fraction_above_zero_and_less_or_equal_one(), + (prev_balance, incoming_balance) in (any::(), any::()) + ) { + let balance = balance_weighted_average(prev_balance, incoming_balance, smoothing); + let rug_balance = high_precision::precise_balance_weighted_average( + prev_balance, incoming_balance, fraction_to_high_precision(smoothing)); + prop_assert_eq!(balance, rug_balance); + } +} + +proptest! { + #[test] + fn no_precision_loss_for_small_balance_values_with_small_smoothing_value( + (prev_balance, incoming_balance) in (0..Balance::from(u64::MAX), 0..Balance::from(u64::MAX)) + ) { + let smoothing = fraction::SMALLEST_NON_ZERO; + let balance = balance_weighted_average(prev_balance, incoming_balance, smoothing); + let rug_balance = high_precision::precise_balance_weighted_average( + prev_balance, incoming_balance, fraction_to_high_precision(smoothing)); + prop_assert_eq!(balance, rug_balance); + } +} + +proptest! { + #[test] + fn no_precision_loss_for_small_balance_values_with_big_smoothing_value( + (prev_balance, incoming_balance) in (0..Balance::from(u64::MAX), 0..Balance::from(u64::MAX)) + ) { + let smoothing = Fraction::from_bits(fraction::DIV - 1); + let balance = balance_weighted_average(prev_balance, incoming_balance, smoothing); + let rug_balance = high_precision::precise_balance_weighted_average( + prev_balance, incoming_balance, fraction_to_high_precision(smoothing)); + prop_assert_eq!(balance, rug_balance); + } +} + +proptest! { + #[test] + fn low_precision_loss_for_prices( + smoothing in fraction_above_zero_and_less_or_equal_one(), + (prev_price, incoming_price) in (realistic_price(), realistic_price()) + ) { + let price = price_weighted_average(prev_price, incoming_price, smoothing); + let rug_price = high_precision::precise_weighted_average(Rational::from(prev_price), Rational::from(incoming_price), fraction_to_high_precision(smoothing)); + let tolerance = Rational::from((1, 1e30 as u128)); + let price = Rational::from(price); + prop_assert_rational_relative_approx_eq!(price, rug_price, tolerance); + } +} + +proptest! { + #[test] + fn exponential_smoothing_precision_should_be_high_enough( + period in typical_period(), + iterations in 1_u32..MAX_ITERATIONS, + ) { + let smoothing = smoothing_from_period(period); + let result = exp_smoothing(smoothing, iterations); + let expected = high_precision::precise_exp_smoothing(fraction_to_high_precision(smoothing), iterations); + + let tolerance = Rational::from((1, 1e18 as u128)); + prop_assert_rational_approx_eq!( + fraction_to_high_precision(result), + expected, + tolerance, + "high precision should be equal to low precision within tolerance" + ); + } +} + +proptest! { + #[test] + fn iterated_balance_precision( + period in typical_period(), + iterations in 1_u32..MAX_ITERATIONS, + (start_balance, incoming_balance) in + (1e6 as Balance..(1e26 as Balance)) + .prop_perturb(|n, mut rng| (n, rng.gen_range(n..(1e26 as Balance)))) + ) { + let smoothing = smoothing_from_period(period); + + let expected = high_precision::precise_balance_weighted_average(start_balance, incoming_balance, high_precision::precise_exp_smoothing(fraction_to_high_precision(smoothing), iterations)); + let new_oracle = iterated_balance_ema(iterations, start_balance, incoming_balance, smoothing); + + let tolerance = 1; + prop_assert_approx_eq!( + new_oracle, + expected, + tolerance, + "high precision should be equal to low precision within tolerance" + ); + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1_000))] + #[test] + fn iterated_price_precision( + (period, iterations) in period_and_iterations(), + prev in realistic_price(), + incoming in realistic_price(), + ) { + let smoothing = smoothing_from_period(period); + + let res = iterated_price_ema(iterations, prev, incoming, smoothing); + let smoothing_adj = high_precision::precise_exp_smoothing(fraction_to_high_precision(smoothing), iterations); + let expected = high_precision::precise_weighted_average(Rational::from(prev), Rational::from(incoming), smoothing_adj); + + let res = Rational::from(res); + let tolerance = Rational::from((1, 1e30 as u128)); + + prop_assert_rational_relative_approx_eq!( + res, + expected, + tolerance + ); + } +} + +proptest! { + #[test] + fn ema_balance_history_precision( + history in ema_balance_history(), + period in typical_period(), + ) { + let smoothing = smoothing_from_period(period); + let rug_ema = high_precision::precise_balance_ema(history.clone(), fraction_to_high_precision(smoothing)); + + let mut ema = history[0].0; + for (balance, iterations) in history.into_iter().skip(1) { + ema = iterated_balance_ema(iterations, ema, balance, smoothing); + } + + let tolerance = 1; + prop_assert_approx_eq!( + ema, + rug_ema, + tolerance, + "high precision should be equal to low precision within tolerance" + ); + } +} + +proptest! { + #[test] + fn ema_balance_history_precision_crash_scenario( + (period, history) in ema_balance_crash_history(), + ) { + let smoothing = smoothing_from_period(period); + let rug_ema = high_precision::precise_balance_ema(history.clone(), fraction_to_high_precision(smoothing)); + + let mut ema = history[0].0; + for (balance, iterations) in history.into_iter().skip(1) { + ema = iterated_balance_ema(iterations, ema, balance, smoothing); + } + + let tolerance = 1; + prop_assert_approx_eq!( + ema, + rug_ema, + tolerance, + "high precision should be equal to low precision within tolerance" + ); + } +} + +proptest! { + #[ignore] + #[test] + fn ema_price_history_precision( + history in ema_price_history(), + period in typical_period(), + ) { + let smoothing = smoothing_from_period(period); + let rug_ema = high_precision::precise_price_ema(history.clone(), fraction_to_high_precision(smoothing)); + + let mut ema = history[0].0; + for (price, iterations) in history.into_iter().skip(1) { + ema = iterated_price_ema(iterations, ema, price, smoothing); + } + + let relative_tolerance = Rational::from((1, 1e24 as u128)); + prop_assert_rational_relative_approx_eq!( + Rational::from(ema), + rug_ema, + relative_tolerance, + "high precision should be equal to low precision within tolerance" + ); + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1_000))] + #[test] + fn rational_rounding_add_should_have_high_enough_precision( + (a, b) in (high_balance(), high_balance()), + (c, d) in (high_balance(), high_balance()), + ) { + let res = rounding_add(EmaPrice::new(a, b), (c.into(), d.into()), Rounding::Nearest); + let expected = Rational::from((a, b)) + Rational::from((c, d)); + + let res = Rational::from(res); + // make sure the result has a precision of 100 bits + let tolerance = Rational::from((1, 1u128 << 100)); + prop_assert_rational_relative_approx_eq!(res, expected, tolerance); + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1_000))] + #[test] + fn rational_rounding_sub_should_have_high_enough_precision( + ((a, b), (c, d)) in bigger_and_smaller_rational(MIN_BALANCE, MAX_BALANCE * 1000), + ) { + let res = rounding_sub(EmaPrice::new(a, b), (c.into(), d.into()), Rounding::Down); + let expected = Rational::from((a, b)) - Rational::from((c, d)); + + let res = Rational::from(res); + // make sure the result has a precision of 77 bits + let tolerance = Rational::from((1, 1u128 << 77)); + prop_assert_rational_relative_approx_eq!(res, expected, tolerance); + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1_000))] + #[test] + fn rational_rounding_sub_result_should_be_smaller_or_equal_to_input( + (a, b) in any_rational(), + (c, d) in any_rational(), + ) { + let res = rounding_sub(EmaPrice::new_unchecked(a, b), (c.into(), d.into()), Rounding::Down); + prop_assert!(res <= EmaPrice::new_unchecked(a, b)); + } +} diff --git a/math/src/ema/tests/mod.rs b/math/src/ema/tests/mod.rs new file mode 100644 index 00000000000..17c5e7a7612 --- /dev/null +++ b/math/src/ema/tests/mod.rs @@ -0,0 +1,365 @@ +use super::*; + +use crate::test_utils::fraction_to_high_precision; +use crate::test_utils::{assert_approx_eq, assert_rational_approx_eq, assert_rational_relative_approx_eq}; +use hydra_dx_math::fraction; +use hydra_dx_math::support::rational::Rounding; +use hydra_dx_math::transcendental::saturating_powi_high_precision; +use hydra_dx_math::types::Fraction; + +mod high_precision; +mod invariants; +mod test_data; +use test_data::*; + +use num_traits::One; +use primitive_types::{U128, U256, U512}; +use rug::Rational; +use sp_arithmetic::{FixedPointNumber, FixedU128}; + +pub const TEN_MINUTES_PERIOD: u64 = 100; +pub const DAY_PERIOD: u64 = 14_400; +pub const WEEK_PERIOD: u64 = 100_800; + +#[test] +fn saturating_sub_works() { + assert_eq!( + saturating_sub(EmaPrice::one(), EmaPrice::one()), + (U256::zero(), U256::one()) + ); + assert_eq!( + saturating_sub(EmaPrice::from(2), EmaPrice::one()), + (U256::one(), U256::one()) + ); + assert_eq!( + saturating_sub(EmaPrice::from(4), EmaPrice::new(30, 6)), + (U256::zero(), U256::from(6)) + ); + assert_eq!( + saturating_sub(EmaPrice::new(4, 5), EmaPrice::new(2, 3)), + (U256::from(2), U256::from(15)) + ); + assert_eq!( + saturating_sub(EmaPrice::new(1, 10), EmaPrice::new(2, u128::MAX)), + ( + U256::from(U128::MAX - 20), + U128::from(u128::MAX).full_mul(10_u128.into()) + ) + ); +} + +#[test] +fn round_to_rational_should_work() { + let res = round_to_rational((U512::from(1), U512::from(1)), Rounding::Nearest); + let expected = EmaPrice::new(1, 1); + assert_eq!(res, expected,); + + let res = round_to_rational((U512::MAX, U512::MAX), Rounding::Nearest); + let expected = EmaPrice::new(u128::MAX, u128::MAX); + assert_eq!(res, expected,); + + let res = round_to_rational((U512::MAX, U512::from(1)), Rounding::Nearest); + let expected = EmaPrice::new(u128::MAX, 1); + assert_eq!(res, expected,); + + let res = round_to_rational((U512::from(1), U512::MAX), Rounding::Nearest); + let expected = EmaPrice::new(1, u128::MAX); + assert_eq!(res, expected,); + + let d = 323853616005226055489000679651893043332_u128; + let res = round_to_rational( + ( + U512::from_dec_str("34599284998074995708396179719034205723253966454380752564716172454912477882716") + .unwrap(), + U512::from(d), + ), + Rounding::Down, + ); + let boundary = Rational::from_str_radix( + "34599284998074995708396179719034205723253966454380752564716172454912477882716", + 10, + ) + .unwrap() + / d; + assert!(Rational::from(res) <= boundary); +} + +#[test] +fn weighted_averages_work_on_small_values_with_correct_ratios() { + let smoothing = smoothing_from_period(7); + + // price + let tolerance = Rational::from((100, u128::MAX)); + let start_price = EmaPrice::new(4, 1); + let incoming_price = EmaPrice::new(8, 1); + let next_price = price_weighted_average(start_price, incoming_price, smoothing); + let expected = Rational::from((5, 1)); + // oracle should be biased towards previous value + assert!(Rational::from(next_price) < expected); + assert_rational_approx_eq!(Rational::from(next_price), expected, tolerance); + + let tolerance = Rational::from((100, u128::MAX)); + let start_price = EmaPrice::new(4, 100); + let incoming_price = EmaPrice::new(8, 100); + let next_price = price_weighted_average(start_price, incoming_price, smoothing); + let expected = Rational::from((5, 100)); + // oracle should be biased towards previous value + assert!(Rational::from(next_price) < expected); + assert_rational_approx_eq!(Rational::from(next_price), expected, tolerance); + + let start_price = EmaPrice::new(8, 1); + let incoming_price = EmaPrice::new(4, 1); + let next_price = price_weighted_average(start_price, incoming_price, smoothing); + let expected = Rational::from((7, 1)); + // oracle should be biased towards previous value + assert!(Rational::from(next_price) > expected); + assert_rational_approx_eq!(Rational::from(next_price), expected, tolerance); + + let start_price = EmaPrice::new(8, 100); + let incoming_price = EmaPrice::new(4, 100); + let next_price = price_weighted_average(start_price, incoming_price, smoothing); + let expected = Rational::from((7, 100)); + // oracle should be biased towards previous value + assert!(Rational::from(next_price) > expected); + assert_rational_approx_eq!(Rational::from(next_price), expected, tolerance); + + // balance + let start_balance = 4u128; + let incoming_balance = 8u128; + let next_balance = balance_weighted_average(start_balance, incoming_balance, smoothing); + assert_eq!(next_balance, 5u128); + + // volume + let start_volume = (4u128, 1u128, 8u128, 0u128); + let incoming_volume = (8u128, 1u128, 4u128, 0u128); + let next_volume = volume_weighted_average(start_volume, incoming_volume, smoothing); + assert_eq!(next_volume, (5u128, 1u128, 7u128, 0u128)); + + // liquidity + let start_liquidity = (4u128, 8u128); + let incoming_liquidity = (8u128, 4u128); + let next_liquidity = liquidity_weighted_average(start_liquidity, incoming_liquidity, smoothing); + assert_eq!(next_liquidity, (5u128, 7u128)); +} + +#[test] +fn balance_weighted_averages_work_on_typical_values_with_minutes_smoothing() { + let smoothing = smoothing_from_period(TEN_MINUTES_PERIOD); + let start_balance = 4_000_000_000_000u128; + let incoming_balance = 8_000_000_000_000u128; + let next_balance = balance_weighted_average(start_balance, incoming_balance, smoothing); + let expected_balance: Rational = + start_balance + Rational::from((incoming_balance - start_balance, 1)) * 2 / (TEN_MINUTES_PERIOD + 1); + assert_eq!(next_balance, expected_balance.round()); +} + +#[test] +fn balance_weighted_averages_work_on_typical_values_with_day_smoothing() { + let smoothing = smoothing_from_period(DAY_PERIOD); + let start_balance = 4_000_000_000_000u128; + let incoming_balance = 8_000_000_000_000u128; + let next_balance = balance_weighted_average(start_balance, incoming_balance, smoothing); + let expected: Rational = + start_balance + Rational::from((incoming_balance - start_balance, 1)) * 2 / (DAY_PERIOD + 1); + let tolerance = 1; + let expected_balance = expected.round(); + assert_approx_eq!( + next_balance, + expected_balance, + tolerance, + "averaged balance values should be within 1 of the expected value" + ); +} + +#[test] +fn balance_weighted_averages_work_on_typical_values_with_week_smoothing() { + let smoothing = smoothing_from_period(WEEK_PERIOD); + let start_balance = 4_000_000_000_000u128; + let incoming_balance = 8_000_000_000_000u128; + let next_balance = balance_weighted_average(start_balance, incoming_balance, smoothing); + let expected_balance: Rational = + start_balance + Rational::from((incoming_balance - start_balance, 1)) * 2 / (WEEK_PERIOD + 1); + assert_eq!(next_balance, expected_balance.round()); +} + +#[test] +fn price_weighted_average_boundary_values() { + let smoothing = fraction::frac(1, 2); + + let tolerance = Rational::from((1, 1e30 as u128)); + let max_price = EmaPrice::new(1_000_000_000_000_000_000_000_000_u128, 1); // 1e24 + let half_max_price = EmaPrice::new(1_000_000_000_000_000_000_000_000_u128, 2); // 1e24 / 2 + + // previously zero, incoming max + let next_price = price_weighted_average(EmaPrice::zero(), max_price, smoothing); + assert_rational_relative_approx_eq!(Rational::from(next_price), Rational::from(half_max_price), tolerance); + // previously max, incoming zero + let next_price = price_weighted_average(max_price, EmaPrice::zero(), smoothing); + assert_rational_relative_approx_eq!(Rational::from(next_price), Rational::from(half_max_price), tolerance); + + // we can only guarantee 14 digits of precision for extreme values + let tolerance = Rational::from((1, 1e14 as u128)); + let max_price = EmaPrice::new(1_000_000_000_000_000_000_000_001_u128, 1); // 1e24 + 1 + let half_max_price = EmaPrice::new(1_000_000_000_000_000_000_000_002_u128, 2); // (1e24 + 2) / 2 + + // previously one, incoming max + let next_price = price_weighted_average(EmaPrice::one(), max_price, smoothing); + assert_rational_relative_approx_eq!(Rational::from(next_price), Rational::from(half_max_price), tolerance); + // previously max, incoming one + let next_price = price_weighted_average(max_price, EmaPrice::one(), smoothing); + assert_rational_relative_approx_eq!(Rational::from(next_price), Rational::from(half_max_price), tolerance); +} + +#[test] +fn balance_weighed_average_does_not_saturate_on_big_balances() { + let smoothing = Fraction::one(); + let start_balance = u128::MAX; + let incoming_balance = u128::MAX; + let next_balance = balance_weighted_average(start_balance, incoming_balance, smoothing); + assert_eq!(next_balance, incoming_balance); +} + +#[test] +fn exp_smoothing_works() { + let smoothing = smoothing_from_period(7); + let alpha = exp_smoothing(smoothing, 10); + let expected_complement: Fraction = saturating_powi_high_precision(fraction::frac(3, 4), 10); + assert_eq!(alpha, Fraction::one() - expected_complement); +} + +#[test] +fn smoothing_from_period_works() { + let period = 0; + assert_eq!(smoothing_from_period(period), Fraction::one()); + + let period = 3; + assert_eq!(smoothing_from_period(period), fraction::frac(1, 2)); + + let period = 999; + assert_eq!(smoothing_from_period(period), fraction::frac(2, 1_000)); +} + +#[test] +fn exponential_smoothing_small_period() { + let smoothing = Fraction::from_num(0.999); + let iterations = 100_000; + let exp = exp_smoothing(smoothing, iterations); + let rug_exp = high_precision::precise_exp_smoothing(fraction_to_high_precision(smoothing), iterations); + + let tolerance = Rational::from((1, FixedU128::DIV)); + assert_rational_approx_eq!( + fraction_to_high_precision(exp), + rug_exp, + tolerance, + "high precision should be equal to low precision within low precision tolerance" + ); +} + +#[test] +fn precision_of_ema_over_price_history_should_be_high_enough_in_crash_scenario() { + let history = vec![ + (EmaPrice::zero(), 1), + (EmaPrice::new(1e15 as u128, 1), invariants::MAX_ITERATIONS), + (EmaPrice::new(1, 1e15 as u128), invariants::MAX_ITERATIONS), + ]; + let smoothing = smoothing_from_period(WEEK_PERIOD); + let precise_ema = high_precision::precise_price_ema(history.clone(), fraction_to_high_precision(smoothing)); + + let mut ema = history[0].0; + for (price, iterations) in history.into_iter().skip(1) { + ema = iterated_price_ema(iterations, ema, price, smoothing); + } + + let tolerance = Rational::from((1, 1e20 as u128)); + assert_rational_relative_approx_eq!( + Rational::from(ema), + precise_ema, + tolerance, + "high precision should be equal to low precision within tolerance" + ); +} + +// balancer history +#[test] +fn precision_of_ema_over_balancer_three_months_data_scrape_history_should_be_high_enough() { + let data = balancer_data_weth_wbtc_three_months(); + let history: Vec<(EmaPrice, u32)> = data.into_iter().map(|(n, d)| (EmaPrice::new(n, d), 1_u32)).collect(); + let smoothing = smoothing_from_period(WEEK_PERIOD); + + let mut precise_ema = Rational::from(history[0].0); + let mut ema = history[0].0; + for (price, iterations) in history.into_iter().skip(1) { + let smoothing_adj = high_precision::precise_exp_smoothing(fraction_to_high_precision(smoothing), iterations); + precise_ema = + high_precision::precise_weighted_average(precise_ema.clone(), Rational::from(price), smoothing_adj); + ema = iterated_price_ema(iterations, ema, price, smoothing); + + let tolerance = Rational::from((1, 1e25 as u128)); + assert_rational_relative_approx_eq!( + Rational::from(ema), + precise_ema, + tolerance, + "high precision should be equal to low precision within tolerance" + ); + } +} + +#[ignore] +#[test] +fn precision_of_ema_over_balancer_one_year_data_scrape_history_should_be_high_enough() { + let data = balancer_data_weth_wbtc_one_year(); + let history: Vec<(EmaPrice, u32)> = data.into_iter().map(|(n, d)| (EmaPrice::new(n, d), 1_u32)).collect(); + let smoothing = smoothing_from_period(WEEK_PERIOD); + + let mut precise_ema = Rational::from(history[0].0); + let mut ema = history[0].0; + for (price, iterations) in history.into_iter().skip(1) { + let smoothing_adj = high_precision::precise_exp_smoothing(fraction_to_high_precision(smoothing), iterations); + precise_ema = + high_precision::precise_weighted_average(precise_ema.clone(), Rational::from(price), smoothing_adj); + ema = iterated_price_ema(iterations, ema, price, smoothing); + + let tolerance = Rational::from((1, 1e20 as u128)); + assert_rational_relative_approx_eq!( + Rational::from(ema), + precise_ema, + tolerance, + "high precision should be equal to low precision within tolerance" + ); + } +} + +#[ignore] +#[test] +fn precision_of_ema_over_balancer_expanded_one_year_data_scrape_history_should_be_high_enough() { + let data = balancer_data_weth_wbtc_one_year(); + let mut expanded_data = vec![]; + for _i in 0..20 { + expanded_data.extend(data.clone()); + } + let history: Vec<(EmaPrice, u32)> = expanded_data + .into_iter() + .map(|(n, d)| (EmaPrice::new(n, d), 1_u32)) + .collect(); + let smoothing = smoothing_from_period(WEEK_PERIOD); + + let mut precise_ema = Rational::from(history[0].0); + let mut ema = history[0].0; + for (price, iterations) in history.into_iter().skip(1) { + let smoothing_adj = high_precision::precise_exp_smoothing(fraction_to_high_precision(smoothing), iterations); + precise_ema = + high_precision::precise_weighted_average(precise_ema.clone(), Rational::from(price), smoothing_adj); + // reduces precision of the high precision comparison ema but speeds up the test by orders + // of magnitude. + high_precision::round(&mut precise_ema); + ema = iterated_price_ema(iterations, ema, price, smoothing); + + let tolerance = Rational::from((1, 1e20 as u128)); + assert_rational_relative_approx_eq!( + Rational::from(ema), + precise_ema, + tolerance, + "high precision should be equal to low precision within tolerance" + ); + } +} diff --git a/math/src/ema/tests/test_data.rs b/math/src/ema/tests/test_data.rs new file mode 100644 index 00000000000..4397c15f7b9 --- /dev/null +++ b/math/src/ema/tests/test_data.rs @@ -0,0 +1,5536 @@ +// data from https://github.com/enthusiastmartin/omnihack +pub fn balancer_data_weth_wbtc_three_months() -> Vec<(u128, u128)> { + vec![ + (24000000000000000, 189695), + (60559458942335890, 460657), + (9371800000000000, 70187), + (27882803373282060, 207118), + (61665090943018904, 466155), + (5982000000000000, 45327), + (6181400000000000, 46711), + (3791956574376494, 28929), + (47950947655644220, 370069), + (18222557019270010, 142742), + (61470088171883490, 472163), + (4472990970304615, 33854), + (35913568196284976, 269408), + (19940000000000000, 147750), + (19940000000000000, 146466), + (103141277299929950, 779477), + (15983007104875646, 124033), + (26064959969415116, 204194), + (63270053437400270, 505815), + (73425836704090990, 605736), + (8300000000000000, 68821), + (650000000000000, 5378), + (7700000000000000, 63590), + (70000000000000010, 567890), + (113677171732830980, 941059), + (10000000000000000, 83956), + (129610000000000000, 1053836), + (54425638413660890, 439263), + (28213000000000000, 229984), + (10059592423412448, 80021), + (38147214000000000, 300114), + (34895000000000004, 269985), + (36296844802398380, 283752), + (27487350000000000, 219762), + (20956940000000000, 168329), + (132994973628250580, 1030570), + (75030816806468240, 572015), + (31995678315914480, 237888), + (18558672346501348, 136378), + (30421701023623160, 221052), + (66497233475863990, 472658), + (106784040000000000, 769501), + (105769297290485000, 729367), + (48593776133389176, 331656), + (37354586315049480, 261246), + (72781000000000000, 499888), + (12145546617844230, 83084), + (22398881857140172, 154452), + (9970000000000000, 68474), + (15325884000000000, 104432), + (11964000000000000, 81018), + (26660465129041580, 180834), + (10264081662316798, 69407), + (49850000000000000, 339331), + (16103544000000000, 109706), + (64805000000000000, 431763), + (4985000000000000, 33582), + (56850029984611490, 380784), + (69093142405910970, 497984), + (62390679035020390, 480228), + (24925000000000000, 192070), + (24909306237890504, 189661), + (29970703125000000, 231673), + (127413941116536370, 997938), + (102686077821543440, 802252), + (94715000000000000, 698608), + (24864291557399052, 176604), + (13363435898526386, 95961), + (46586312002211624, 340369), + (23636616699481788, 176258), + (19990191832874204, 151383), + (27553504525486860, 200375), + (20995233477529908, 153979), + (40000000000000000, 289148), + (22008892091629852, 156777), + (35975531748167708, 252807), + (42409341942364664, 301480), + (41682401584126650, 302261), + ] +} + +pub fn balancer_data_weth_wbtc_one_year() -> Vec<(u128, u128)> { + vec![ + (26920146043179460000, 216579921), + (33195600000000000000, 266516965), + (19602953258546500000, 157101033), + (29115510888437174000, 233739419), + (29115736821859740000, 234209064), + (33171999999999996000, 266427336), + (33115600000000000000, 265369240), + (35101171864925872000, 281693895), + (4839285318465622000, 38889590), + (33113799999999996000, 265479768), + (5570507812500000000, 44600531), + (37732617187500000000, 301659649), + (24992598187063960000, 200000000), + (24949782598887707000, 200000000), + (21779816117645984000, 174869776), + (24869827111745237000, 200000000), + (32394599999999996000, 261027246), + (24772021165251480000, 200000000), + (16424571527590742000, 132458455), + (12542735622439375000, 101051924), + (33205199999999996000, 267100562), + (33195500000000004000, 266413549), + (33396299999999996000, 267412757), + (33416900000000000000, 266965068), + (27500600000000000000, 219241982), + (4333590499757841400, 34569483), + (33581899999999996000, 267243794), + (30705665095274280000, 244673152), + (33413400000000004000, 265852461), + (47695430779427365000, 380204723), + (21317065613429650000, 169844988), + (33374699999999996000, 265417703), + (55600717540518670000, 443130645), + (33338700000000004000, 265536088), + (33424400000000000000, 265611217), + (18980704726630617000, 150562566), + (56259800000000000000, 445130845), + (34970797431128994000, 276877385), + (33686300000000004000, 266346362), + (36569384238965477000, 289575679), + (2313505812469759500, 18415134), + (19765721899196023000, 156386198), + (28316467253100265000, 223672538), + (12648828358125638000, 100000000), + (36799323863873348000, 291422022), + (25406439561779220000, 201627167), + (23383758673398755000, 185884845), + (33073000000000000000, 263416082), + (32942700000000004000, 262972286), + (36617212976297423000, 291859565), + (23794041469464965000, 189834094), + (32949399999999996000, 263389424), + (112345407639536860, 897815), + (44851958637169670000, 359491477), + (12116845206397950000, 97090579), + (31884960937500000000, 255104240), + (13247691671252238000, 105827732), + (23730040148729020000, 189324762), + (25406818450598867000, 202998313), + (24988319718370394000, 200000000), + (20423210334774910000, 163717105), + (32817100000000004000, 263551067), + (33607713910695610000, 269515796), + (32799400000000000000, 263394868), + (8745427290354426000, 70330371), + (32672500000000000000, 263125690), + (28316467253100265000, 227759992), + (1237175886054996000, 9940955), + (26480749074422650000, 213261492), + (29086628244887593000, 233899333), + (32892200000000004000, 264907137), + (1651188457091057200, 13240029), + (32591099999999996000, 263074862), + (8475036168888703000, 68371465), + (32771400000000000000, 264004662), + (20675292636033630000, 166722991), + (774291040113448200, 6239326), + (32516800000000004000, 262678552), + (1769531110664171000, 14311614), + (15135689225829265000, 122485836), + (7196665017637927000, 58173593), + (6578216529919325000, 53149166), + (33402754510000000000, 269508424), + (2061913935657667800, 16679190), + (32564300000000004000, 263104017), + (20686624230911713000, 166996434), + (2188100364554916400, 17649903), + (22822547411428040000, 183935361), + (24870740392671420000, 200113701), + (24938982919039656000, 200319308), + (24054023377971380000, 192885941), + (40182007229023306000, 322844624), + (19542322210738352000, 156905622), + (33287900000000000000, 266784505), + (25032832328382005000, 200223337), + (33632300000000000000, 268465038), + (31007812500000000000, 246967980), + (23766762919042257000, 188940670), + (33990400000000000000, 269683457), + (25251650267145134000, 201144709), + (87486944836478730000, 696377677), + (34181199999999996000, 271720880), + (34288200000000004000, 271934279), + (36335897674352013000, 288598321), + (34215400000000004000, 271396029), + (1011323573893359000, 8114954), + (37741279298433425000, 299818950), + (40948828125000000000, 324809671), + (47381250000000000000, 374700673), + (34447400000000000000, 272678462), + (34582500000000004000, 273363963), + (33510293291770806000, 265250027), + (34516900000000000000, 272826508), + (13244893938615347000, 104760181), + (1320728590340027400, 10498024), + (37732617187500000000, 297779316), + (31007812500000000000, 244136031), + (38317382812500000000, 300976433), + (35161800000000000000, 275501175), + (28961132812500000000, 226424143), + (42221724345702250000, 330709694), + (31150205865955643000, 244598803), + (25800000000000000000, 202341234), + (5447267188184311000, 42675861), + (20371150507691240000, 159455192), + (43956000000000000000, 343315933), + (9459878237805173000, 73752174), + (36027299999999996000, 280448053), + (36248300000000000000, 281479425), + (20565875303941423000, 159839476), + (21390737936839220000, 166486512), + (19171834359278998000, 149421582), + (21252945891748626000, 165868360), + (25585620349527335000, 200000000), + (25541274186592660000, 200000000), + (25497043231422312000, 200000000), + (35977600000000004000, 282800334), + (1401714363400813600, 11032135), + (35427400000000000000, 279178738), + (25327248021371640000, 200000000), + (32325217495368450000, 254842768), + (45370225295677374000, 356741363), + (26119086012105978000, 205524746), + (32131135889517752000, 253334004), + (26329687499999998000, 207343890), + (21359179687500000000, 167928850), + (35718100000000000000, 279883541), + (20647026060687315000, 162098112), + (23971516398195250000, 188026640), + (3816210902484056000, 30033901), + (35387400000000000000, 278130627), + (34634588457223004000, 271910845), + (35827000000000000000, 280599882), + (7886181063867276000, 61793084), + (2944498066106140700, 23080444), + (40656445278700360000, 319157917), + (36334700000000000000, 284874840), + (19179234230999417000, 150493856), + (25449756709870256000, 200000000), + (19328356368180285000, 152125788), + (32748469670322140000, 257272325), + (53711835236321180000, 422853778), + (44457421875000000000, 349618118), + (19020117187500000000, 149253740), + (21359179687500000000, 167378985), + (18701592898854826000, 146353912), + (25586613641585857000, 199933776), + (36679299999999996000, 286007925), + (36151042454779236000, 282278826), + (26196250681596408000, 204981607), + (25619218328043004000, 200819347), + (13757226562500000000, 107558835), + (23462710897500873000, 183671566), + (39929598036996740000, 312899087), + (68725195114755380000, 540541989), + (108447229819976660000, 856186272), + (95624414028449320000, 756335114), + (187724999968083640000, 1488188072), + (166323986720031080000, 1317657266), + (107166178030402550000, 848465996), + (5422049992328903000, 43093308), + (22786583929594425000, 181277772), + (12340733430233514000, 98294321), + (63462304667720696000, 506793787), + (25120015173172900000, 200584975), + (34690073546666670000, 276435577), + (8228787159055598000, 65605321), + (8841275614002028000, 70529713), + (26812484767818050000, 214153366), + (46882445202994995000, 375401563), + (75145486092253070000, 604240768), + (74400000000000000000, 597426545), + (91706300000000000000, 737866561), + (90692200000000000000, 734308366), + (6000000000000000000, 48654336), + (3455821441147306000, 28014297), + (69387488906647536000, 564557652), + (76000000000000000000, 617354789), + (68140429650503250000, 554135704), + (70815904062256410000, 578671593), + (39520636157165140000, 322841247), + (102641601562500000000, 834357405), + (86604426272336330000, 704588740), + (81590039062500000000, 662981646), + (24627111649826116000, 200000000), + (24585234558173925000, 200000000), + (70899032801555580000, 578671593), + (63462304687500000000, 517383582), + (63552700000000000000, 518848299), + (69309960937499990000, 564948281), + (107027343668932580000, 874751187), + (71241669827877900000, 585884809), + (64678226432159605000, 531286118), + (66386132812499990000, 542839143), + (62877538840045360000, 514807204), + (66437976140000000000, 543131542), + (69619356753619034000, 570000000), + (27639280120778535000, 226306299), + (33689675225751314000, 276290694), + (45573606930768536000, 373075188), + (31014722672659694000, 254120358), + (34373216382854090000, 282278826), + (39051000000000000000, 320193339), + (23194043016299390000, 190337974), + (24331198987444285000, 200000000), + (158984623543023440000, 1315216612), + (95585606882472310000, 791384989), + (78715960886164910000, 652244135), + (39980410560000000000, 331264150), + (175082925426486440000, 1459603420), + (158294685297665570000, 1318582428), + (89786500000000000000, 741456510), + (65748680084906390000, 543257172), + (26138746337195430000, 215970902), + (38005600000000000000, 314590920), + (37636500000000000000, 312359715), + (21288402157738710000, 176534331), + (32177343749999997000, 266333468), + (53458739149980220000, 441161607), + (34199831137242333000, 282435617), + (23867660166306984000, 197508063), + (62292773244031700000, 517034517), + (38233000000000000000, 317159604), + (38326000000000000000, 317082424), + (41533593750000000000, 342664431), + (35762675160252654000, 295406695), + (44909489005736770000, 372006692), + (1384311365090490000, 11366290), + (9900000000000000000, 81991854), + (39041565184079190000, 322791010), + (26480955885470327000, 219152123), + (20979036333420420000, 173409607), + (38939443882039575000, 322520919), + (39276164603844900000, 324851382), + (31015767980261163000, 256815455), + (37905700000000000000, 314621602), + (7635159322350671000, 63351011), + (38267200000000000000, 317005096), + (62101341684500420000, 512649491), + (22578160729329775000, 186387889), + (24708879019754390000, 204314027), + (12078066650340493000, 100000000), + (30270992167335928000, 250118568), + (27215337495651460000, 225161909), + (38760300000000000000, 321416832), + (38494200000000000000, 320073337), + (38271400000000000000, 319076933), + (7000000000000000000, 58342735), + (46000000000000000000, 382684962), + (46000000000000000000, 381456186), + (38086000000000000000, 316184259), + (30715429517366776000, 255609127), + (63152300000000000000, 527274539), + (31080439109899380000, 259427072), + (64631835937500000000, 537674929), + (54106054585934300000, 450575165), + (29253515395646730000, 244324736), + (24283007804920426000, 203192308), + (1406627934204175600, 11685947), + (42682869483892250000, 356427173), + (5676499564885490000, 47406997), + (73403320312500000000, 610718121), + (6447656074266818000, 53730323), + (36260183915110937000, 301716037), + (32177343648375680000, 268506830), + (37648300000000000000, 314929786), + (28961132706932750000, 242828311), + (32469726333397758000, 272834924), + (39779296875000000000, 333702515), + (37249500000000000000, 312890527), + (22284868959343428000, 187026335), + (50012695312500000000, 418668937), + (6000000000000000000, 50128865), + (5920014805521334000, 49529783), + (47381249766011630000, 397157485), + (36563085937500000000, 306165732), + (33346874999999996000, 278550415), + (44457421875000000000, 370347455), + (37943087501369240000, 316451267), + (64924218512971325000, 543434820), + (26192968059999998000, 219234042), + (31100000000000000000, 259783174), + (49699378348245850000, 416000000), + (21459969641079906000, 179553584), + (23969511565887365000, 200231426), + (12407920527301710, 97314), + (20960303777841754000, 174818261), + (11897585461373820000, 99117020), + (12100000000000000000, 100718670), + (20962533916438127000, 174787918), + (35964141052364450000, 300471791), + (37483900000000000000, 312714646), + (20001887132201624000, 167000000), + (37197200000000000000, 309946446), + (10695161889017975000, 89278640), + (19020117148433170000, 158606593), + (37078600000000000000, 308798130), + (31133303795597830000, 258666458), + (20047399199813812000, 166729608), + (24010750420404412000, 200000000), + (36612900000000004000, 304410344), + (9663867187500000000, 80218270), + (18936699394824315000, 157461971), + (36373800000000004000, 303040509), + (36237900000000004000, 302677251), + (31775756082506020000, 265077594), + (36535100000000000000, 304052647), + (36006250662411290000, 300065850), + (28479655021313094000, 237207705), + (36797300000000000000, 305968234), + (26210033469251965000, 218160172), + (30370866503791830000, 253293587), + (30306440254047710000, 253293587), + (40627202064974030000, 338954905), + (30473407178191282000, 254507060), + (36928900000000000000, 307921239), + (37144000000000000000, 308913961), + (31114156807199003000, 259073846), + (10099790586586464000, 84217766), + (31805312522992816000, 265599826), + (36614900000000000000, 305284978), + (31080439109899380000, 258527664), + (26481327184516870000, 220545408), + (69630364659189460000, 578223494), + (47126305810429930000, 391586002), + (60872600000000000000, 507720723), + (36253100000000004000, 303406423), + (35337232783693970000, 296484692), + (4000000000000000000, 33550514), + (545202839033356860, 4566967), + (55307730209739590000, 462937828), + (48179408398343420000, 403736400), + (35300985254104580000, 296684807), + (35378361962402636000, 296918699), + (36661900000000004000, 306914703), + (25549655592535384000, 214104967), + (19810000000000000000, 165808740), + (23990624981329070000, 201111268), + (36371699999999996000, 305547185), + (47712290523538540000, 402001735), + (36250900000000000000, 305129328), + (35943100000000000000, 302959249), + (22569411842115490000, 190626353), + (39621815867553190000, 335388672), + (16640748762956274000, 141139413), + (33607713910695610000, 284476927), + (23839829055587840000, 202008590), + (35978299999999996000, 305508853), + (35708399999999996000, 303986657), + (892382770325368200, 7606717), + (35678199999999996000, 303324480), + (35518000000000000000, 302383992), + (23529605479183315000, 200124935), + (35833199999999996000, 304132006), + (23541479198866362000, 200000000), + (31114923125867670000, 264852085), + (35826500000000004000, 304480372), + (29903503713625117000, 254445230), + (43872656085027226000, 374282040), + (6507189489434486000, 55612554), + (171059179541696250000, 1453754804), + (59661327957303470000, 508411990), + (168272247804649050000, 1427927640), + (76933274252001950000, 655080005), + (36118545618627797000, 308833871), + (108133531041926020000, 920965135), + (10833398325052475000, 92427992), + (53493600602244580000, 455358021), + (35100000000000000000, 298789758), + (19567035813429720000, 166706796), + (35552600000000000000, 303491384), + (18441789816040130000, 157301626), + (35736300000000000000, 304234203), + (11572886076112943000, 98577386), + (6993769621195192000, 59611773), + (875211541702694300, 7456771), + (23439147923930400000, 200000000), + (981375658770202500, 8368747), + (35319899999999996000, 301981839), + (34929071249903590000, 298224343), + (35762500000000004000, 304577690), + (892382812500000000, 7590292), + (35987000000000000000, 305694617), + (23576416842564956000, 199851359), + (36247500000000004000, 306613893), + (53601777807309900000, 454325414), + (36279600000000004000, 307261448), + (13372401505432005000, 113321509), + (29508264300515647000, 250439870), + (36149700000000004000, 306305861), + (22883614720526820000, 194079733), + (36203899999999996000, 306478120), + (36409999999999996000, 306924014), + (23671718511357650000, 199966785), + (26635041735125172000, 224761744), + (23750233371941880000, 200158136), + (23772153044501443000, 200008528), + (46559994679624150000, 392599042), + (23660316589858850000, 200000000), + (23698242110318150000, 200655071), + (36530099999999996000, 309961135), + (47047998492361680000, 398500835), + (49720312500000000000, 419702790), + (23681652505581880000, 200000000), + (35895500000000000000, 303787023), + (34693750000000000000, 292483003), + (35685937500000000000, 301593561), + (19762690330010330000, 166753702), + (19925544276340370000, 168362836), + (6955692699364052000, 58828471), + (23621907445470100000, 200000000), + (36531900000000000000, 309962033), + (2000000000000000000, 16966306), + (40364062500000010000, 341903713), + (6861138164262672000, 58129984), + (23698842860141478000, 200385219), + (20400335731363246000, 172227133), + (23772486190379510000, 200377467), + (9191712941091780000, 77545426), + (21627061490105418000, 182653590), + (23643240724312887000, 200000000), + (21473957546710127000, 181938908), + (23525639895145185000, 200000000), + (2061913907026590700, 17513252), + (23568210111609266000, 200000000), + (38170045624356340000, 323876396), + (23645430884587287000, 200196753), + (5782978411087263000, 49000000), + (21016187201332990000, 178241504), + (23544648692703314000, 200000000), + (25594313362265750000, 217091174), + (17260086600642886000, 146562453), + (29508351089666770000, 250982526), + (5005741649243255000, 42553539), + (4857618465614084000, 41279940), + (21600000000000000000, 183384676), + (35978320232991870000, 306040912), + (31491243500998365000, 267540691), + (1732523259165073000, 14724138), + (23627009227997442000, 200362001), + (22037418027742806000, 186580618), + (23703297501720670000, 200361017), + (22409434054281445000, 189116240), + (6448522567668624000, 54465543), + (23767713287508144000, 200343820), + (3408325120234715000, 28702090), + (24801240000000000000, 208648195), + (6583169919370565000, 55425016), + (24709069940439130000, 208260040), + (23785695001470734000, 200203564), + (21666029946801950000, 182070830), + (23807506819925246000, 199747013), + (41533593750000000000, 347671361), + (2064113511108054000, 17386851), + (23906708149697030000, 200275740), + (12385288838878652000, 103653164), + (9912500000000000000, 82893333), + (16983994722185556000, 142263129), + (6447656238748963000, 54142734), + (23842639552390517000, 200000000), + (17618288679370660000, 148070908), + (37350000000000000000, 313247576), + (37328700000000000000, 312248650), + (37376700000000000000, 311831753), + (27206835937500000000, 226471933), + (16402773060601053000, 136677623), + (50045452256309710000, 417981131), + (37693114479560720000, 314510246), + (1477148437500000000, 12266894), + (48194663262058170000, 400926673), + (15200000000000000000, 126153949), + (28952820331074937000, 240749514), + (5366150664987550000, 44595183), + (22057015900624327000, 183668181), + (6504530041664396000, 54116744), + (23990534948951265000, 200000000), + (37814400000000000000, 315928352), + (49720312500000000000, 414645294), + (36833799999999996000, 307468948), + (37070500000000000000, 308554824), + (21024907313088537000, 175356486), + (36970000000000000000, 308148490), + (36856700000000004000, 308000505), + (36711599999999996000, 307581488), + (36899800000000000000, 308724135), + (36753300000000004000, 307927801), + (8456200000000001000, 70819303), + (33175954367025340000, 277437505), + (20418226454880063000, 170428776), + (44749804687500000000, 372669963), + (29116658759736824000, 242686137), + (36820300000000004000, 307606088), + (36791200000000004000, 308158355), + (36582400000000000000, 307200838), + (23766071256976204000, 200000000), + (4985742149653811000, 42106565), + (36168900000000000000, 305017686), + (23657621871607300000, 200000000), + (721438620387331700, 6050366), + (20807104702670336000, 176178292), + (19090449196253053000, 161871036), + (35974900000000000000, 305631671), + (26413901330000003000, 224166417), + (23535748089883540000, 200000000), + (35756500000000004000, 304486960), + (2095424308133116000, 17840026), + (846987629938410900, 7218814), + (32761406244165270000, 278580265), + (19858842142188663000, 169025206), + (21485922567360300000, 183141885), + (10478266422852215000, 89416000), + (28296528474261144000, 241800000), + (23698242154620494000, 202880783), + (31592577931959357000, 270996162), + (31300195281553850000, 269089490), + (20189648219478700000, 173890032), + (21066796661533975000, 181711735), + (14502070061376752000, 125246430), + (9663866985678262000, 83533522), + (9956249916203220000, 86121144), + (12295312432432970000, 106438474), + (23990624959180014000, 207952258), + (37732617150255464000, 327791428), + (22969990308262400000, 199371520), + (36270703124999995000, 314151297), + (34394551794084385000, 297150748), + (23255614919274762000, 200503518), + (44200000000000000000, 380165930), + (23332575363447070000, 200202642), + (23392996171632075000, 200388007), + (13464843750000000000, 115191007), + (35877699116802126000, 307606851), + (23277963408117436000, 200000000), + (22072282500877517000, 189947387), + (37220905425307640000, 319691719), + (33488641222040015000, 288000000), + (27846303286417183000, 240000000), + (44749804687500000000, 384916107), + (23821597502180962000, 204402384), + (41808613569427060000, 359473710), + (33639257812499997000, 288912629), + (25160156250000000000, 215638045), + (25452539062500000000, 217752119), + (37269974355612070000, 319433899), + (6635977898518694000, 56858010), + (2782979826806514000, 23836990), + (22200162249690890000, 189981940), + (4566663147920880000, 39110316), + (20596980271705870000, 176051934), + (23478069469547897000, 200364427), + (1000000000000000000, 8564791), + (30000000000000000000, 255538519), + (9079101456052675000, 77515166), + (23452402641281740000, 200000000), + (26329687358097980000, 225079167), + (19020117089826333000, 162855453), + (19556598656765526000, 167678716), + (17785617823527342000, 152696963), + (23261303826273174000, 200000000), + (23667246711546008000, 203202800), + (34138800000000004000, 292507866), + (22050472005369844000, 189116174), + (9302407613285730000, 79706739), + (19659282328149360000, 168275337), + (26120210689986820000, 223942994), + (23286592662505255000, 200000000), + (34079600000000000000, 292175829), + (34132900000000000000, 291924358), + (5618689099639821000, 48072911), + (5823105472549667000, 49842129), + (39270239491780450000, 336667746), + (22821093750000000000, 195488251), + (34465600000000000000, 294636432), + (34581300000000000000, 294902145), + (34391100000000000000, 293689202), + (38317382812500000000, 326715592), + (30423046875000000000, 258772856), + (864836133554224900, 7358737), + (34183100000000004000, 290108870), + (892382812500000000, 7564177), + (578061488132176400, 4906683), + (34579800000000000000, 292756559), + (21524492657807655000, 182400000), + (23678628406760247000, 200358452), + (18960171461315654000, 160191508), + (34616700000000000000, 293042997), + (986819247653543700, 8352015), + (1655683291665595100, 14032965), + (19157761075846620000, 162493676), + (34852200000000004000, 295034938), + (17008267597952655000, 144130530), + (10249289657224247000, 86937729), + (34978000000000000000, 297169709), + (33607713910695610000, 285142593), + (34742700000000000000, 295477758), + (13409692037218957000, 113851739), + (20023300000000000000, 170143550), + (8346147120637844000, 70989559), + (47842989689842590, 397596), + (34775599999999996000, 296242025), + (20485330560000000000, 174352113), + (34803900000000000000, 296784299), + (34608300000000000000, 295844187), + (24965871093874954000, 213191798), + (125157061406072240, 1067805), + (28961132721474085000, 247688199), + (23424403438834340000, 200094885), + (34972400000000000000, 298121488), + (35685937436437463000, 304638072), + (16096289033638439000, 137889980), + (23379340010846216000, 200000000), + (2000000000000000000, 17117740), + (29253515516805747000, 250971060), + (13172460847840500000, 113179606), + (16176738162926973000, 139138107), + (34663400000000004000, 297531483), + (34383500000000000000, 295539646), + (34257700000000000000, 295179339), + (27561481475443843000, 237206367), + (14165840343751473000, 122030096), + (362861405683192000, 3108725), + (34341400000000000000, 296342458), + (3047194070682439000, 26287716), + (17265820231325640000, 149234281), + (34227200000000004000, 296374668), + (45923927548634145000, 396935595), + (23125681305564983000, 200000000), + (7324804579746382000, 63416748), + (9912500000000000000, 85692526), + (35019900000000000000, 303439851), + (9663029328194990000, 83861959), + (35422199999999996000, 306704143), + (26120241267285107000, 226404492), + (18665200550880043000, 162045222), + (298502483611895600, 2589577), + (34939300000000004000, 303907891), + (34820000000000000000, 303628598), + (27937096290198290000, 243329520), + (38902148337787380000, 339442569), + (28668749990486320000, 250758366), + (18435351457033153000, 161522708), + (34519300000000000000, 303020339), + (44279213112123695000, 388016235), + (7466117550753236000, 65430113), + (36330077834698900000, 318884703), + (34092300000000000000, 298860043), + (49427929687500000000, 431991730), + (33825600000000000000, 294744416), + (4693359375000000000, 40839604), + (11328690906968533000, 98739154), + (33857400000000000000, 294444601), + (29116779595843670000, 253528884), + (14692044843966124000, 128130147), + (33911900000000004000, 295129865), + (34526946302844380000, 300910299), + (33907500000000000000, 295105193), + (8401259310385182000, 73153472), + (13612131039246027000, 118620784), + (34100700000000004000, 296531074), + (2858357512212041000, 24862427), + (3231445206794572300, 28182782), + (34062300000000000000, 296672896), + (4893777617852737000, 42693170), + (34083300000000000000, 296614096), + (11463155353882794000, 99818011), + (1586422517872504000, 13820624), + (33768600000000000000, 294560627), + (33884300000000004000, 296291458), + (7617187399646064000, 66869356), + (33844800000000000000, 296670268), + (40071679503897930000, 352386133), + (33405800000000000000, 294549293), + (29477494527336470000, 259585762), + (33911299999999996000, 297954782), + (20000000000000000000, 175383907), + (16396606176573002000, 143967805), + (32469726534467027000, 285599438), + (31623262064823566000, 278800000), + (34214000000000000000, 301190831), + (23353564676440280000, 205792005), + (5210038455578743000, 45876838), + (6623647207578556000, 58299358), + (6132848467529020000, 53954589), + (34335700000000004000, 301631608), + (39486913899269660000, 347434799), + (36270703081331483000, 320012634), + (25738460799561340000, 226856768), + (61123242187499995000, 537045887), + (34139300000000000000, 298926755), + (13209062214768220000, 115734319), + (12874758295231285000, 112911531), + (34683700000000000000, 303511519), + (23453747881781735000, 205444324), + (34759200000000000000, 303925422), + (34799200000000000000, 304702046), + (5201711739736288000, 45531113), + (2939062500000000000, 25700190), + (22877210059045790000, 200232880), + (6677979975048959000, 58374339), + (14146750194883004000, 123568397), + (35085700000000004000, 305921811), + (25762349182269972000, 224868167), + (35000100000000004000, 304971856), + (4200000000000000000, 36544874), + (20798897439733907000, 181336560), + (169234899808116060, 1484497), + (2514584302188202000, 21941998), + (169102690984311000, 1475716), + (663539432667258400, 5799375), + (3317697163336291300, 28908879), + (24365621059952914000, 212769671), + (33175954367025340000, 289207956), + (22976456327070300000, 199890252), + (35393554687500000000, 307270628), + (22166869672992596000, 192044895), + (35955000000000000000, 310850645), + (20457816603550470000, 176511495), + (36208100000000000000, 311772677), + (30892542294110570000, 266324709), + (168823067636834240000, 1465904750), + (80207072216773050000, 697689864), + (10000000000000000000, 86704122), + (84357000000000000000, 728938956), + (35926499999999996000, 310340169), + (12880078039835390000, 111455635), + (35747300000000004000, 309874029), + (24283007812500000000, 210288522), + (26482286202498703000, 229673619), + (25384614653031023000, 219853050), + (10753316364936710000, 93011417), + (34929071249903590000, 301622529), + (23813390913768160000, 205199460), + (756578510790408600, 6544641), + (29117008562961460000, 251300407), + (14506620389767487000, 125400000), + (18435351487328731000, 159551259), + (440434194370741000, 3808943), + (19727514523565230000, 170965026), + (14006184231005567000, 121237452), + (36493100000000000000, 315307801), + (46200273316791090000, 399879675), + (18727734375000003000, 161687543), + (29209047040000000000, 252616416), + (36773300000000000000, 316849825), + (24709328341048185000, 213108474), + (26481980612908290000, 228819844), + (14668319443272606000, 126931661), + (11545118100966664000, 100000000), + (19748605495926084000, 171249835), + (35795000000000000000, 311021407), + (36753371708225390000, 318891248), + (3007653232772207000, 26100584), + (25739310173107050000, 223600000), + (21927980800000000000, 190250496), + (36244400000000000000, 313800366), + (11529337467637463000, 99870317), + (36223599999999996000, 313060399), + (36307499999999996000, 312964162), + (24365533023405330000, 210230135), + (35773600000000000000, 308097192), + (10261148169988284000, 88415646), + (18630476994972557000, 160697925), + (5499500720448266000, 47392269), + (21651562500000002000, 186400891), + (36180900000000000000, 310836746), + (156104707819431420, 1341261), + (2335620007623607300, 20069575), + (4733957919412204000, 40688443), + (22991042956341244000, 197806071), + (36104900000000000000, 310051791), + (36094400000000000000, 309156571), + (35958199999999996000, 308420115), + (35822000000000004000, 308047895), + (26456803861632524000, 227271421), + (36157800000000000000, 309905897), + (21418671446741680000, 183737555), + (36276300000000000000, 310590791), + (12353886257678025000, 105586681), + (36520800000000000000, 311589784), + (14136106356705364000, 120329837), + (40364062500000010000, 343430672), + (36912100000000000000, 313509001), + (1409506730223010800, 11973022), + (2396792752342301700, 20362277), + (11390313352923400000, 96601417), + (37260700000000000000, 315458811), + (89928000000000000, 768109), + (2649378962831621600, 22433953), + (2009999999999999700, 17013515), + (1015323717232777600, 8598511), + (36770400000000004000, 311820462), + (28961132812500000000, 245321526), + (36426499999999996000, 309073638), + (16336542637795172000, 138875613), + (2375890681942435300, 20179091), + (2360594551412950500, 20045773), + (25738460799561340000, 218346853), + (2342711915691991000, 19885081), + (33215187774955370000, 282292084), + (22513032033442263000, 191718583), + (36070700000000004000, 307821188), + (35959800000000000000, 307670549), + (32671816520000000000, 279180955), + (23003868945736700000, 196175309), + (27561481475443843000, 234616021), + (36068199999999996000, 306329349), + (1090820482136228200, 9265759), + (34808789062499996000, 294906492), + (11928365417164855000, 100890371), + (13488153101912836000, 113979443), + (8417819635633637000, 71220190), + (11191737329376010000, 94755787), + (36753371708225390000, 310456538), + (26621718766658190000, 224365586), + (28961132602416280000, 244444478), + (11830471487878236000, 100000000), + (11911898107874960000, 100547130), + (15000000000000000000, 126491822), + (23581023558062580000, 199193555), + (23900076383668187000, 201604053), + (28635381372419183000, 241927198), + (29475936181778500000, 248673036), + (23911739651517157000, 201346587), + (23895298863506883000, 200865274), + (26241131519585354000, 220912118), + (25353336699999998000, 213146491), + (42225201973650645000, 355700621), + (45597012827541670000, 383521567), + (45237139486580900000, 379264763), + (76140000000000000000, 635602575), + (846695041469036400, 7136043), + (12607183194929396000, 105152109), + (19929365395012830000, 166416146), + (48573659790437196000, 406593989), + (37858300000000000000, 316577010), + (23895677333454160000, 200000000), + (44279213112123695000, 369818317), + (17420899292246050000, 145179995), + (38063900000000000000, 316588108), + (2732272382012532000, 22728409), + (40000000000000000000, 331836173), + (33031930788979850000, 274345990), + (24029919552993770000, 199984255), + (28668750000000000000, 238217227), + (37497400000000000000, 312111571), + (16786113229020326000, 139989599), + (19792741282142044000, 165278362), + (5041671997592946000, 42137435), + (2053078933663377400, 17318374), + (37276900000000000000, 310762233), + (16028247063794172000, 133707196), + (37041200000000000000, 309580050), + (23969300278462603000, 200141619), + (47047998492361680000, 391857433), + (1489117971407334700, 12400000), + (37850300000000000000, 314336062), + (25056562450267103000, 208284765), + (24136634099573617000, 200363764), + (761495814666602900, 6345199), + (24161634261025812000, 200228452), + (38902148437500000000, 321665213), + (45042187307239890000, 373037615), + (38509900000000000000, 318565344), + (38634300000000000000, 318724038), + (24341359927757190000, 200364494), + (38875900000000000000, 319292203), + (38200500000000000000, 312894412), + (37969700000000000000, 311437297), + (37642300000000000000, 309575854), + (37905800000000000000, 312575284), + (37710300000000000000, 311795314), + (26456803861632524000, 218530539), + (37572300000000000000, 310900617), + (27206835937500000000, 224896888), + (15880113910637433000, 131399342), + (8991433113727107000, 74464752), + (24121206879836650000, 200000000), + (24080047704719577000, 200000000), + (2939062472325179400, 24434167), + (29796048787787555000, 248000000), + (41533593750000000000, 345055525), + (21885032079446890000, 181409722), + (16973437500000000000, 140262737), + (24198432118392120000, 200259083), + (15511811081887803000, 128037249), + (29116977127777714000, 240789369), + (47088867187500000000, 388620879), + (17364864346678622000, 143361027), + (29545898281019965000, 244330214), + (21066796677070082000, 174524432), + (14866602819942207000, 123316753), + (16400249288485626000, 136188966), + (24050033370489938000, 200000000), + (24009057070698504000, 200000000), + (18305501678182533000, 152717606), + (29521738826595900, 249467), + (11125781063197774000, 92916357), + (41133474085623775000, 342678370), + (12295312500000000000, 102138445), + (13570868683927343000, 112838064), + (4400976562500000300, 36482274), + (21442123965384480000, 177909170), + (24076098001688904000, 200000000), + (14293532554386979000, 118611327), + (17973620187029185000, 148979270), + (22753788766078267000, 188329338), + (20798718365028684000, 172376871), + (18142968750000000000, 150170205), + (24364734772719956000, 201995187), + (3700148065720265000, 30655485), + (3563669619002191000, 29566006), + (3406877296371384300, 28225781), + (25160156062594810000, 208903515), + (6129553300331342000, 50949859), + (3544021332370140700, 29419965), + (37125200000000000000, 308986991), + (27029688346042370000, 225476647), + (15554254846728047000, 129622053), + (5807885420928009000, 48363565), + (191642314147052000, 1592892), + (36969500000000000000, 307386711), + (2950106999988863000, 24533716), + (34277728704070873000, 284346361), + (12047538503278651000, 100000000), + (12067632057887020000, 100252433), + (2154990621182417000, 17911721), + (14142432739986674000, 117616157), + (20000000000000000000, 166066637), + (10047697486644802000, 83340571), + (37453500000000000000, 310136014), + (2316976447354922500, 19188868), + (37386500000000000000, 308813426), + (22236328125000000000, 183286037), + (37633100000000000000, 309541472), + (35799839332689773000, 294856048), + (17689007401753262000, 145966354), + (37065300000000000000, 306448453), + (12441308606446768000, 102807849), + (37250700000000000000, 307278556), + (24294799215530963000, 199971107), + (21830404617853160000, 179923106), + (36783000000000000000, 303788715), + (36658700000000004000, 303549603), + (17500000000000000000, 144802914), + (12281672851660198000, 101517111), + (36778200000000000000, 304689154), + (32325217495368450000, 267466192), + (23415792157549003000, 193366012), + (29253515624999997000, 241124498), + (17173048374145380000, 141318441), + (6310018056716938000, 51978500), + (4108593750000000000, 33741658), + (24341494827870323000, 200104229), + (30695434697687896000, 252675179), + (25000000000000000000, 205548685), + (730466452549225100, 6009127), + (15511523437500000000, 127360622), + (11951172104339698000, 98252796), + (37090714976844325000, 305457733), + (22528710937500000000, 185369269), + (12360555973767789000, 101579217), + (19604882633851100000, 161378573), + (37072500000000000000, 305775541), + (20783304440876765000, 171280389), + (24283007812500000000, 199804184), + (37187700000000000000, 305323320), + (37403200000000000000, 306286740), + (14653486780074359000, 120066152), + (37495600000000000000, 306551362), + (15915132637789825000, 130200164), + (19595843464732540000, 160512215), + (831553370010490600, 6824167), + (37364000000000000000, 306668376), + (26821371900248842000, 219912706), + (7763539252822620000, 63700905), + (11996905244071162000, 98504836), + (126206675293990660, 1035247), + (37000500000000000000, 304328461), + (3123790071756089300, 25661360), + (14631358552318570000, 120269227), + (29545898437500000000, 242434897), + (33346874999999996000, 273017871), + (224329255564712200, 1837061), + (15219140625000000000, 124391451), + (14049609374999998000, 114714329), + (22821093750000000000, 186091797), + (16681054687500001000, 135835010), + (20482031250000000000, 166569253), + (1482539802888190700, 12129789), + (385034346068194800, 3133454), + (15438900683422261000, 125401495), + (888763211576501400, 7225352), + (22231568053860810000, 180347504), + (36791300000000000000, 299030298), + (6142507857327406000, 50000000), + (8539581395963535000, 69409077), + (36927300000000000000, 300862685), + (35378361962402636000, 287855570), + (36406999999999996000, 296650941), + (6021500388805200000, 49137482), + (19232411436180906000, 157082363), + (16973437307264305000, 138808647), + (36155400000000000000, 296232080), + (23698242136678433000, 194576725), + (36009300000000004000, 296281184), + (36077800000000004000, 297601390), + (2894015646293302000, 23866954), + (33607713910695610000, 276806008), + (22821829419281200000, 188161041), + (15076046280089113000, 124158842), + (4543120492700201500, 37453388), + (25452538945893300000, 210052675), + (15215765849977151000, 125752135), + (36461100000000000000, 300689069), + (23958792358974902000, 197163291), + (61612100000000000000, 505495392), + (25160156250000000000, 205796002), + (62030900000000000000, 505825805), + (50845807613225900000, 415035654), + (37659800000000000000, 307115735), + (9371484375000000000, 76298291), + (2652536883335258600, 21620893), + (32469726512189070000, 264988311), + (2536139670408881700, 20723150), + (27588474631117586000, 225668249), + (15803906250000001000, 129145541), + (16049742435316400000, 131339400), + (17554184819610690000, 143820698), + (22353562342649446000, 182854783), + (22826700755187670000, 186428621), + (17864000000000000000, 145689081), + (17265820296442862000, 141005030), + (20189648208798216000, 165100440), + (16096288983237081000, 131795270), + (26095845407556952000, 213455133), + (24418118837788692000, 200000000), + (1372362809747959800, 11226818), + (8976407012726236000, 73459598), + (127080651235481950, 1039547), + (37623600000000000000, 308608002), + (77094022674981120, 635921), + (19462031431558226000, 159959215), + (19312500000000000000, 158509052), + (14214525000000000000, 116529164), + (3099999999891962000, 25439119), + (19302515383642763000, 158524832), + (3096412175957822500, 25408692), + (2491318305909228000, 20439356), + (384264683270458700, 3163346), + (3110245396929134000, 25553498), + (27791601562499998000, 227815654), + (2500000000000000000, 20471342), + (5210859743658895000, 42733201), + (22050153314643747000, 181002668), + (2242580820854169900, 18424412), + (373133524077841000, 3061663), + (18791548611415830000, 154500658), + (19312500000000000000, 158558840), + (38040200000000000000, 311685849), + (17906227282677350000, 146427481), + (35106279297576920000, 286545522), + (26702485722280330000, 218192745), + (7203863248378776000, 58934865), + (33209400771631600000, 271058405), + (12014031804541600000, 98156579), + (4726500835270991000, 38593546), + (38647200000000000000, 315017377), + (38863400000000000000, 315918660), + (1606060008633845500, 13176094), + (64339453125000000000, 521123962), + (39263300000000000000, 316865875), + (40656445312500000000, 327194088), + (24867773437500000000, 199673194), + (61139365921194900000, 492223277), + (39695800000000000000, 319376888), + (24836380167183217000, 200000000), + (59999316000000000000, 481890190), + (26329687416401457000, 211517007), + (23498483602864046000, 189101340), + (12410823100020419000, 100000000), + (21014942170058070000, 169525442), + (1288873546706080800, 10442196), + (22018229668295148000, 177886342), + (4102672235293578000, 33120062), + (63339487275797635000, 510124421), + (17460312515105202000, 140593565), + (2450171100277168000, 19742945), + (22800000000000000000, 183330140), + (39233900000000000000, 316095318), + (19416335334809820000, 156320771), + (39610000000000000000, 318243702), + (8487687620263675000, 68079384), + (39973800000000000000, 320087538), + (23949433423065743000, 191935034), + (24913304169944390000, 200000000), + (9956249856773530000, 80024448), + (24852809271812272000, 200000000), + (40614900000000000000, 327591902), + (20189648437500002000, 162452212), + (24827014755963474000, 200080242), + (40675500000000000000, 326593657), + (63412204913582465000, 510270873), + (55103110735439420000, 442954339), + (73988085937500000000, 594323443), + (16918954053921710000, 135996321), + (3701619389823933400, 29732599), + (278766087019941920, 2243272), + (39876000000000000000, 321151151), + (115733130247972500000, 928327301), + (38595957833367150000, 309189410), + (22528710860290253000, 180860721), + (24871613233083728000, 200000000), + (32177343503282885000, 259263472), + (23108965358723273000, 186556683), + (39421400000000000000, 318942592), + (6317113974032690000, 51096893), + (24200000000000000000, 195536370), + (39567300000000000000, 320324785), + (39532400000000000000, 320930547), + (39305400000000000000, 319971663), + (23548123445920154000, 191535004), + (39198500000000000000, 318130697), + (1851924832890993700, 15008395), + (39698400000000000000, 321256800), + (39695500000000000000, 320342305), + (22371243280931615000, 180679189), + (33346874999999996000, 268843141), + (39965600000000000000, 321379661), + (3081358222049495000, 24781250), + (4957003524797392000, 39876964), + (5404297146176743000, 43490977), + (12395405290806206000, 99813797), + (33054492187500003000, 265607018), + (15854595881875102000, 127181322), + (24974193299230930000, 200058554), + (12587695312499999000, 100703313), + (59542947519067540000, 475158897), + (64035555279518564000, 511806585), + (1389362703671888600, 11129383), + (40237000000000000000, 321429881), + (15277607067940330000, 121808478), + (23113476562500000000, 184038372), + (1000000000000000000, 8003190), + (9635085536186468000, 76789801), + (20112726531411976000, 160460390), + (15803906065284213000, 126241947), + (12587695279916935000, 100785583), + (19315032995872956000, 154477533), + (21359179588896477000, 171218333), + (16388671769580341000, 131546962), + (12772187251366824000, 102622832), + (39420700000000000000, 317317576), + (23113476420801340000, 186459165), + (25160156250000000000, 202671667), + (239232479586237100, 1927598), + (238715341414822900, 1923934), + (39432200000000000000, 316926787), + (20493122152707613000, 164830335), + (21651562312300663000, 174404333), + (170000000000000000, 1368468), + (22353562342649446000, 179800634), + (2419975029430472700, 19478762), + (10833398292546030000, 87240091), + (22301658480851706000, 179800634), + (4175804573561692700, 33640405), + (7625993004063687000, 61409912), + (7730093845442888000, 62214839), + (16965490624228803000, 136427327), + (5495172768502728000, 44233430), + (39334000000000000000, 317115448), + (1857827027521383000, 14976669), + (8901793707386011000, 71733874), + (24894179643856495000, 200999799), + (24812272419158060000, 200058905), + (23900657736692093000, 192972571), + (39773200000000000000, 320499922), + (26119534404243157000, 210670510), + (21670721473848754000, 174570718), + (17862386173862375000, 143693768), + (19312500000000000000, 155157788), + (19020117050516443000, 153027411), + (49427929687500000000, 396698171), + (24956870277252653000, 199779599), + (11895000000000000000, 95097222), + (23307309235008918000, 186107308), + (22528710937500000000, 179603640), + (39088700000000000000, 310956900), + (39017500000000000000, 310824729), + (38737800000000000000, 309432328), + (20528927447768430000, 164321097), + (9663867040736340000, 77434596), + (19343467216903877000, 154726263), + (39050500000000000000, 311726474), + (12684492943000205000, 101073761), + (16018916232038742000, 127837140), + (38898100000000000000, 311015849), + (24957990126459204000, 200000000), + (26456803861632524000, 211703193), + (12578418823720352000, 100742844), + (12641975367439854000, 101110016), + (478161364906847700, 3828070), + (25200000000000000000, 201244430), + (211068854100039100, 1686074), + (38856700000000000000, 310933646), + (14406978183200373000, 115248720), + (13782976599863204000, 110408492), + (14459061841362776000, 115969035), + (26622070312500000000, 213109398), + (17991000000000000000, 143734161), + (10988151519348535000, 87880000), + (26214392431289786000, 210000000), + (1000000000000000000, 8008580), + (7500000000000000000, 60041808), + (23698241961761400000, 190120115), + (8246408297867218000, 66109784), + (19020117187500000000, 152006456), + (21590806310677500000, 172860984), + (39771600000000000000, 317026419), + (3213592487335490000, 25610666), + (15190606975057201000, 120828113), + (40259600000000000000, 319449676), + (2136929954950361300, 16951287), + (34516406250000003000, 273031154), + (21749507260100870000, 172187046), + (24586770639450866000, 194352810), + (54690820312500000000, 430817773), + (30689472259030823000, 241074345), + (35978320312500003000, 282289575), + (1833072959107650300, 14497186), + (11061045196954050000, 86840652), + (35393554621418496000, 278562328), + (31950900742272610000, 252210978), + (20319207070235804000, 160251330), + (26487682142500696000, 209249632), + (40127500000000000000, 317931915), + (18965165111608910000, 150652977), + (22485280714412120000, 178942027), + (24867773291095580000, 198310618), + (20122861663761457000, 160790781), + (9956249942199476000, 79660717), + (25074391062177860000, 200207898), + (32177343749999997000, 256273872), + (15429865505185006000, 122971267), + (32177343749999997000, 255896121), + (32469726438356640000, 258586572), + (38628600000000000000, 308601901), + (24964347201809780000, 200000000), + (55860351422435795000, 449124910), + (12295312500000000000, 98604303), + (34779477313751216000, 279501785), + (26492959539752518000, 212100708), + (47966015478531105000, 384916275), + (37774600000000000000, 304285811), + (49720312500000000000, 399741238), + (32593619866952565000, 262214152), + (24797134427899064000, 200000000), + (40364062320443900000, 326497463), + (2407640704880253400, 19280576), + (16220356540048658000, 131132546), + (2407638297241869000, 19480521), + (38609765474854350000, 312887261), + (38392300000000000000, 310693277), + (24694408860443780000, 200000000), + (10833398414751242000, 87878422), + (26877159048924373000, 218388544), + (38609765577881700000, 314637907), + (37241200000000000000, 304514316), + (21817386323536777000, 178868186), + (46211718603274660000, 380018845), + (2908527023525229000, 23930988), + (36650700000000000000, 302437334), + (29477494527336470000, 242983071), + (36877699999999996000, 304510175), + (45626952890800560000, 378154601), + (36937100000000000000, 305825105), + (37071900000000000000, 305922699), + (26126786011632587000, 215798079), + (19218180000000000000, 158562624), + (37297200000000000000, 306947833), + (4748317304927490000, 39075322), + (12506365309454326000, 102998233), + (31294882978585485000, 258241007), + (37182000000000000000, 306311103), + (24029797142100720000, 198121682), + (31592578073552360000, 261126632), + (29086628244887593000, 240104836), + (37175800000000000000, 305969022), + (22375886044106400000, 184296599), + (37435100000000000000, 307691728), + (20497166362934424000, 168581216), + (21091137485285536000, 173219249), + (687629324678281900, 5641920), + (231814913306672700, 1903759), + (19599535700691235000, 161173784), + (13630732197040552000, 112257276), + (687631184496051700, 5658414), + (38317382655993910000, 316283403), + (37380800000000000000, 308134408), + (29545898228464284000, 243805935), + (21216131766765564000, 174891191), + (6300000000000000000, 51868813), + (7000459274976001000, 57563222), + (36865299999999996000, 303966704), + (31884960746739450000, 263714441), + (32681512500000000000, 269915179), + (23990624841469272000, 198337766), + (1991158875245533000, 16454727), + (37062100000000000000, 307190344), + (18999265273907610000, 157383525), + (19582150505913164000, 161931050), + (12080041279374537000, 100000000), + (30715429450426135000, 254998810), + (12316822733112005000, 102452146), + (1647888797031035400, 13694643), + (36761500000000000000, 306415848), + (36636300000000000000, 304574102), + (13602434694257040000, 113339170), + (30423046857780482000, 253204104), + (28668749984930558000, 239239613), + (28668749919311750000, 239859293), + (25335706586353480000, 212490871), + (25740619851651130000, 216386162), + (32372717632892764000, 272855389), + (66680339887912350000, 564550959), + (41546030509501530000, 351660212), + (2898627894087366000, 24306649), + (30069278854600905000, 254740722), + (36625999999999996000, 309762144), + (721963219150156500, 6095614), + (36855468750000000000, 309978163), + (23743044127587180000, 200243004), + (63203564830752960000, 532963949), + (36671000000000000000, 309167473), + (20755028495417663000, 174527782), + (66902855138917745000, 564550614), + (35079943410000000000, 296030308), + (13757226562500000000, 115836838), + (37175600000000000000, 312300739), + (6362835884291752000, 53452537), + (37571400000000000000, 314742188), + (126330686748911070, 1061602), + (22153283499326720000, 185712514), + (26456803861632524000, 221436141), + (16096289062499998000, 134174467), + (23819212544347970000, 198908404), + (26914453125000000000, 223917761), + (3641424586394650600, 30253581), + (90735551963736820, 758051), + (546607700775805600, 4547042), + (37853800000000000000, 313925445), + (37940000000000000000, 315082494), + (36174655085660254000, 301425685), + (26000000000000000000, 216441594), + (38101000000000000000, 316265113), + (22181670713780210000, 183625251), + (16697156949854112000, 138382721), + (13027858944696646000, 107839066), + (36270703124999995000, 299570187), + (5860594890479935000, 48312944), + (15135589975759161000, 125000000), + (28668750000000000000, 236291682), + (18779758962189607000, 154456674), + (88839231300630900, 733196), + (23113476562500000000, 189743989), + (8086161537982555000, 66429564), + (27206835937500000000, 223006826), + (16048811832069770000, 131293677), + (9663867187500000000, 78968419), + (12895015506460180000, 105265827), + (34516406250000003000, 281173105), + (1309133120612514800, 10739639), + (2610776183428697000, 21267115), + (12218276824093112000, 99594600), + (28083984375000000000, 228438939), + (12974208144571638000, 105341300), + (15219140625000000000, 123413769), + (10482868325328517000, 84909758), + (18732624262896824000, 152000000), + (13291079575292720000, 108000000), + (27791601562499998000, 225366571), + (571069058318147460, 4647060), + (28376367090340200000, 230437015), + (39779296875000000000, 322422440), + (39828600000000000000, 321683168), + (21207371889081130000, 171383645), + (258074344243326980, 2084601), + (5757484907672290000, 46431766), + (15057583227320740000, 121545401), + (12192976035363641000, 98497295), + (39665400000000000000, 321163488), + (23333907635194065000, 188803109), + (39911600000000000000, 322034631), + (20314760487447904000, 164000722), + (23990624918693577000, 194395471), + (19621196448033630000, 158682486), + (27499218596588966000, 223336132), + (18762044338910650000, 152690788), + (24527869459836270000, 200000000), + (39947200000000000000, 326667135), + (3753673195681562000, 30702175), + (39789700000000000000, 326430716), + (34929071249903590000, 286216349), + (39301800000000000000, 322561860), + (39122200000000000000, 322216691), + (7424595345485199000, 61151376), + (2220000000000000300, 18276742), + (34808788946658530000, 287393844), + (5120000000000000000, 42269662), + (20189648418428068000, 167028095), + (8341607323641785000, 68949883), + (9371484183686244000, 77743255), + (24145140180699886000, 200000000), + (24072571834728006000, 200000000), + (16403330862143465000, 136138701), + (1950711441200363500, 16129621), + (10556305524509139000, 87340379), + (21021464441795437000, 174173514), + (14634375000000000000, 120681850), + (24246421424474055000, 200296195), + (32796858631749520000, 271057957), + (38460500000000000000, 318885315), + (25131492535529562000, 208968009), + (14868750000000000000, 123517572), + (12978550434479553000, 107957237), + (21920699782684950000, 182625954), + (9371484216634542000, 78185980), + (22109815576893768000, 184097821), + (892382787520542300, 7459445), + (38271300000000000000, 319345977), + (1441007479231554600, 11967359), + (38378300000000000000, 319815600), + (38779300000000000000, 323615980), + (23898573803652690000, 200000000), + (331888318009393, 2776), + (34224023401587552000, 287163703), + (45370225295677374000, 379965129), + (39541942276347280000, 331531321), + (38817200000000000000, 325010826), + (23984956819534160000, 200254091), + (10248632812500000000, 85250593), + (24044005350692100000, 200312996), + (39544800000000000000, 328207517), + (24714517420132884000, 205271970), + (62292773329508540000, 519417903), + (38409800000000000000, 321731922), + (36636945587562870000, 306477718), + (23888685980924695000, 200000000), + (25159077990000000000, 210742504), + (21714576047747600000, 182172960), + (17225258027868047000, 144436058), + (7679400000000000000, 64330444), + (45042187499999990000, 376422671), + (8742496061607658000, 73044634), + (21066796861801062000, 176252624), + (16516201886980465000, 138415394), + (38146300000000000000, 320406792), + (7891652441888494000, 66283218), + (18999265273907610000, 159383945), + (12051171819243442000, 101206592), + (11998960286506291000, 100627403), + (21651562485984924000, 181911319), + (24575390625000000000, 206160726), + (26329687351779455000, 221204472), + (23990624922326143000, 202012756), + (1190913086069932800, 10000000), + (22528710722627770000, 190102972), + (19897265417340375000, 168221535), + (28668750000000000000, 241945037), + (37738100000000000000, 317527794), + (29838281184015200000, 251320715), + (25744921875000000000, 216581372), + (37681200000000000000, 317612355), + (19877972010972295000, 167450835), + (16119792783297954000, 135959181), + (150000000000000000, 1264289), + (1310000000000000000, 11040732), + (11205124580309078000, 94383735), + (5485646086555527000, 46172136), + (25744921760090820000, 217195432), + (16000000000000000000, 134853781), + (23113476359512960000, 195144684), + (91237342876040900000, 774319297), + (70000000000000000000, 593824311), + (7400000000000000000, 62555238), + (897721323702095500, 7585949), + (28083984375000000000, 237004581), + (22375966022657160000, 189049514), + (9508926543548842000, 80455101), + (37610000000000000000, 318900267), + (28961132718279627000, 246309829), + (23667246711546008000, 201053098), + (26622070312500000000, 225637720), + (25452539062500000000, 215215573), + (17882294613492732000, 151364731), + (16184368763774700000, 136811600), + (12515213830299240000, 105657380), + (23990625000000000000, 202201551), + (38458600000000000000, 322679337), + (18763403295945060000, 157838649), + (25578788144442675000, 214789334), + (38280400000000000000, 320813499), + (5009549617869899000, 41978778), + (1187429551583412500, 9953152), + (8049608415260881000, 67500781), + (13371682682869156000, 111945787), + (86788200000000000000, 730018873), + (41572994462226285000, 349917894), + (26914453125000000000, 225836456), + (24283007812500000000, 203285342), + (545782302947642900, 4570520), + (20774414062500000000, 173568268), + (31007812274908590000, 259550366), + (24843860653684744000, 207722211), + (2391102794902132000, 20000000), + (300101480868195400, 2510457), + (15501674318371105000, 129769607), + (14562841911790096000, 121744992), + (25744921694928413000, 215637443), + (2262919137914063400, 18947605), + (21716069348739772000, 181640902), + (10889547272537250000, 90954537), + (18154157376915364000, 151440084), + (38384100000000000000, 319408909), + (17605185437690920000, 146572132), + (17881667323484557000, 149104268), + (6326099799576282000, 52702201), + (38394600000000000000, 319240445), + (17331506884662030000, 144176344), + (960960000000000000, 8022087), + (6032016188368957000, 50229853), + (12952758439573877000, 107949526), + (16096289062499998000, 133942056), + (1198958333731134000, 9984397), + (11864920651979230000, 98862045), + (17558202897175839000, 146487836), + (21651562275704360000, 180947771), + (19582150505913164000, 163439067), + (2394703800652829700, 20000000), + (4699470681242940000, 39190010), + (26622070312500000000, 221705269), + (45626953125000000000, 378783300), + (36563085937500000000, 302455510), + (13824411994252098000, 114404920), + (766480286769189200, 6347083), + (26477221386313270000, 219512608), + (22528710937500000000, 186547858), + (21736620928518717000, 180235043), + (37596000000000000000, 312542632), + (1248222006101281000, 10394262), + (98092154097739710, 815736), + (18712143835552096000, 155483283), + (12021483961415592000, 100000000), + (4140361237117256000, 34404958), + (28668749803984550000, 238816089), + (22945771640000000000, 191640034), + (42995507731573060000, 359281224), + (3823247556238519300, 31893996), + (38316200000000000000, 320568480), + (25508116995392287000, 214006675), + (14502250798614835000, 121558519), + (19599143057860518000, 164547777), + (2269698351176495400, 19043379), + (38050000000000000000, 318688307), + (1671854447527000000, 14000000), + (12204680833830916000, 102263140), + (13398647845738030000, 112393044), + (6191553152617642000, 51981637), + (16149591485962265000, 135717590), + (1141377331169207300, 9569088), + (15202951159055297000, 127588830), + (7611381614519700000, 63945841), + (35685937441653137000, 300378399), + (450000000000000000, 3788314), + (20802381519831114000, 175526219), + (23667246711546008000, 199395136), + (1572372885322030600, 13252880), + (2507023259357395500, 21134435), + (26037304687500000000, 218964235), + (38269900000000000000, 320932443), + (15487297928649163000, 129929440), + (2677466172899093500, 22443518), + (38423000000000000000, 321498824), + (19599057840811835000, 164087111), + (6084091124204510000, 50895948), + (4060142168685445000, 33949743), + (23698242187500000000, 197918244), + (24076739408931860000, 200661089), + (38773500000000000000, 322264662), + (2253268841334138600, 18724437), + (548167667118127800, 4555774), + (18788090060899760000, 155804154), + (902653663089417600, 7500184), + (29253515624999997000, 242085399), + (3282805608813972500, 27174038), + (38969200000000000000, 323167357), + (38932400000000000000, 322411606), + (39240000000000000000, 323858794), + (5097817964539977000, 42070362), + (1212145812565559300, 10006118), + (27791601562499998000, 228831885), + (3622555880107192300, 29838134), + (1364040932357836000, 11237709), + (28376367187500003000, 233180252), + (13181560181608675000, 108398788), + (31592578002051180000, 260306165), + (41533593718066120000, 343301321), + (18146401171994990000, 149933709), + (19995000000000000000, 164934733), + (28668750000000000000, 235984935), + (26329687390055800000, 217012843), + (24212462865747763000, 200000000), + (11883562645955019000, 98075826), + (1685936443323629000, 13927486), + (21359179574573160000, 176624180), + (18456792427323466000, 152429409), + (18479339403149930000, 152371496), + (22528710911899040000, 186053615), + (27927394454389400000, 230262420), + (3636573848596932600, 30000000), + (2263577789761514500, 18668665), + (23113476437576253000, 190896373), + (13964969357359352000, 115523646), + (24136857015844643000, 200000000), + (20232142745985480000, 167968726), + (23281585172841546000, 192989605), + (523774640503635500, 4343548), + (16000000000000000000, 132409839), + (3361399791838836700, 27841353), + (9863057488207798000, 81739341), + (1170180500738077200, 9686333), + (35101171640793248000, 291467291), + (29838281174004330000, 248417447), + (26456803861632524000, 220077516), + (24021678422333325000, 200000000), + (23971514719454000000, 200000000), + (23921507998606010000, 200000000), + (31491243500998365000, 262938444), + (30130664062500000000, 250903666), + (33931640480560964000, 282884731), + (1340798376392090000, 11182798), + (31884960742391460000, 266554390), + (1507923062151715300, 12610154), + (29545898289221180000, 247630743), + (299689082737231000, 2512458), + (50012695233440140000, 420617158), + (38609765501738770000, 325978833), + (1749758271110949400, 14666629), + (1736082063879938800, 14666629), + (18891369309759324000, 159452338), + (28699631925631275000, 241734385), + (31884960937500000000, 267853111), + (23539124656017318000, 197868608), + (6078606267681479000, 51084372), + (6000000000000000000, 50397139), + (1697323606763886000, 14251911), + (4297517460680113700, 36075495), + (34224023437500002000, 286810527), + (33639257812499997000, 281076218), + (12349785646236830000, 103197239), + (29545898437500000000, 246459990), + (31592578125000000000, 262831902), + (67731815094516690000, 564942592), + (68725195312500010000, 572632122), + (31007812500000000000, 257244208), + (18424012081893403000, 152519747), + (29545898437500000000, 244081768), + (1991159088188746000, 16445967), + (24867773272660670000, 205634653), + (1953206691817957400, 16151210), + (176313104251706430, 1459293), + (27791601562499998000, 229518188), + (26329687310764016000, 217648696), + (474766737600399900, 3925670), + (16364462484839678000, 135524160), + (21402048860138385000, 177027754), + (5485572115474049000, 45388132), + (17100000000000002000, 141274419), + (3958013771093071000, 32669923), + (17751800796773868000, 146387764), + (18488641490869216, 152549), + (31300195312500003000, 257565188), + (13295686604277885000, 109432598), + (10362305110939906000, 85376263), + (5921303613399416000, 48746937), + (5924340256924797000, 48746937), + (11528701036501055000, 94978981), + (32469726562500000000, 266992042), + (25452539062500000000, 208767598), + (18910135034488193000, 155216601), + (12166703208316875000, 100000000), + (12623051219945791000, 103645070), + (16613484522805766000, 136569720), + (39628963712410075000, 325117665), + (37658500000000000000, 309234719), + (4000000000000000000, 32861173), + (25160156250000000000, 206437734), + (13230853872254863000, 108611042), + (16670122408307421000, 137020800), + (37489000000000000000, 308865808), + (22677097966075933000, 186766088), + (2441766685301330400, 20112611), + (37304400000000000000, 307786171), + (18823255383400886000, 155273571), + (7942503605823397000, 65441990), + (22349946189622206000, 183910319), + (5404565967476192000, 44418991), + (37341300000000000000, 306333896), + (25412248594537000000, 208573458), + (37312600000000000000, 305783793), + (15012014608992889000, 123030771), + (27206835698258850000, 223380485), + (22250000000000000000, 182539257), + (14422832020684296000, 118403412), + (37426900000000000000, 307943990), + (28699631925631275000, 235990393), + (37310300000000000000, 307215496), + (23667246711546008000, 194798061), + (3018774269705700000, 24817942), + (37269200000000000000, 307159410), + (12107569709794157000, 100000000), + (37057600000000000000, 306723362), + (41644808826480020000, 344278889), + (9680740823185093000, 80000000), + (7404584911145632000, 61135114), + (15345786434895012000, 126575882), + (51283711200561180000, 421782779), + (2277678172382957600, 18711772), + (28735703812643942000, 236388933), + (36914600000000000000, 303260690), + (36964800000000000000, 303977655), + (22500000000000000000, 184958200), + (20920554602610754000, 171651985), + (19454560652485886000, 159773200), + (16072749296501733000, 132202634), + (2470205900734126600, 20309743), + (8000000000000000000, 65745279), + (2500000000000000000, 20536070), + (36991000000000000000, 303341939), + (18727173052969870000, 153603129), + (16681054687500001000, 136689855), + (7221759045789262000, 59212401), + (5875589075799388000, 48129578), + (7817582000627414000, 64225265), + (21359179535924650000, 175254916), + (3184208908734302700, 26138924), + (23507754153330287000, 192750922), + (22236328125000000000, 181966055), + (14730729529206833000, 120353497), + (24602892916963934000, 200670838), + (9371484375000000000, 76325674), + (21066796875000000000, 171353038), + (5058259858432201000, 41155656), + (22236328000682950000, 181134783), + (23034786935064834000, 188005332), + (2425601999940733000, 19795071), + (35685937387038757000, 291939175), + (1104929809911514600, 9053568), + (3161528435580494000, 25876719), + (27561481475443843000, 225288563), + (23469668731188388000, 192000000), + (33931640625000000000, 277184766), + (36563085852444330000, 299013698), + (22750000000000000000, 185974957), + (24438165816491102000, 200000000), + (25034271933694090000, 204668613), + (34484228960300590000, 281204593), + (35444421122059395000, 289335797), + (24597942616268860000, 200688345), + (26914453125000000000, 219101446), + (26125001257283715000, 212880380), + (4536744346146291700, 36965213), + (230000000000000000, 1875760), + (6643681358203400000, 54191546), + (4734565318921444000, 38638109), + (22067104510165135000, 180294727), + (45042187399382100000, 369075647), + (25384614653031023000, 207970255), + (26400000000000000000, 215806113), + (3729802404330602500, 30449559), + (34224023437500002000, 278943503), + (24575390625000000000, 199795650), + (12295312500000000000, 99801329), + (35432501263133807000, 288181043), + (38270700000000000000, 310916162), + (13940182181507710000, 113246560), + (20194089441010967000, 164292858), + (580264148821288200, 4725074), + (15395759736277383000, 125453442), + (3742975858718716400, 30484708), + (12000000000000000000, 97667961), + (27206835937500000000, 221063391), + (1528037430127968500, 12257969), + (712545284528640000, 5744059), + (2172834231552915000, 17469238), + (16072369070000000000, 130349966), + (37945800000000000000, 307035162), + (34516406082910196000, 279524849), + (38902148360848320000, 316037020), + (31300195312500003000, 254168100), + (24679301579321647000, 199922871), + (37273400000000000000, 301144267), + (12119899568176736000, 97913022), + (10586464864020716000, 85608176), + (36648400000000004000, 296961201), + (12263764031174347000, 99377705), + (36618899999999996000, 296114603), + (30969012787872973000, 251321173), + (6151097569402772000, 49914527), + (24651084485730940000, 200301166), + (24669920597794128000, 200253864), + (18818520411277914000, 152471948), + (14167646065936062000, 114332806), + (30130664062500000000, 243615045), + (2295510605952978700, 18533891), + (9051497531171016000, 73116983), + (36306399999999996000, 293848338), + (23034419472014040000, 186904679), + (2046088315593934300, 16600583), + (21071506526594675000, 170790970), + (40482555047850300000, 327260906), + (14242745782729564000, 115124289), + (29537268901617054000, 238355905), + (36479200000000000000, 294757034), + (1176507309677720800, 9454108), + (1160695986400072200, 9418698), + (24283007812500000000, 196029468), + (5183244982043535000, 41895484), + (3250899496965131300, 25883224), + (23356891297080193000, 188734430), + (618142820663564500, 5000000), + (39486914062499996000, 318710334), + (40138617086230010000, 322873663), + (34599115895813940000, 278526902), + (12139891357642828000, 97723266), + (15780000000000000000, 126874461), + (27937096290198290000, 224202937), + (765892792499640600, 6145550), + (2620704665919780400, 21031650), + (24575390574708134000, 197411696), + (27499218750000000000, 220650511), + (18980157769006035000, 152391758), + (12193205442881597000, 98029149), + (36600900000000004000, 293659949), + (17728858549766375000, 142272067), + (298403684450689300, 2396492), + (24283007812500000000, 194624480), + (25452539062500000000, 203567870), + (4887316605285349000, 39093445), + (32918522303869075000, 263736852), + (24687397954152560000, 197662195), + (4760009510447612, 38904), + (245612554296138270, 1974229), + (14441727664423332000, 115694538), + (23026094583532724000, 184758849), + (2649553765572288500, 21256878), + (10971270000000000000, 87969552), + (20735504634211365000, 166496368), + (19305098684116074000, 155275074), + (12054696386207605000, 96891524), + (12329371439111213000, 98996569), + (5580000000000000000, 44769553), + (12185140946564125000, 97690285), + (9128160676744551000, 73115754), + (36379300000000000000, 290832182), + (6771806181792783000, 54037629), + (36583599999999996000, 291393320), + (48708182414423870000, 388555544), + (23657494434941977000, 188732915), + (30423046875000000000, 242150458), + (36800400000000004000, 293283133), + (1766561597897502000, 14101786), + (36975400000000000000, 295646730), + (22353562342649446000, 178666343), + (5096160879480071000, 40743186), + (30715429687499997000, 245054113), + (37217100000000000000, 296071469), + (22698790338211676000, 180644059), + (12045097573698540000, 96000000), + (27791601562499998000, 221131464), + (16078827284201960000, 128000000), + (37206200000000000000, 295629884), + (1439806921503935000, 11434403), + (22642284263909945000, 180000000), + (17809962841184387000, 141827360), + (12500000000000000000, 99465082), + (12347853836209887000, 98352118), + (9663867155230405000, 77045761), + (3094634329646835700, 24654368), + (2596468626278647000, 20680566), + (19897265420522406000, 158754460), + (20067368876273873000, 160383558), + (36785100000000000000, 294707227), + (16096289015290740000, 129247353), + (36555500000000004000, 294186516), + (15941115758851875000, 128273271), + (32177343749999997000, 258391205), + (1453878683619327700, 11658118), + (19909214596766695000, 159930032), + (36714500000000000000, 295638763), + (2456836020743535000, 19816429), + (6239245436862439000, 50266296), + (11152385643991646000, 89957637), + (11870292962562548000, 95649831), + (22821093750000000000, 183618764), + (37011000000000000000, 297033213), + (6155273418509396000, 49531256), + (34981162689205293000, 280999328), + (36896600000000000000, 296221064), + (21091137485285536000, 168911011), + (3809737099288303600, 30518851), + (31161670193680736000, 250000000), + (27189585619251340000, 217952247), + (29545898339534807000, 237101299), + (36533900000000004000, 294005230), + (36491700000000000000, 294581735), + (17735020797228667000, 143138682), + (13757226315251546000, 111126293), + (26329687262704595000, 213046975), + (31491243500998365000, 254485207), + (21359179560866087000, 172704967), + (72053962500000000, 582554), + (22528710797658878000, 182500248), + (26329687499999998000, 213043743), + (13739411148180138000, 110981955), + (22528710779672200000, 182228825), + (23405859292549833000, 189693637), + (5799276135457110000, 46988619), + (11652900050024700000, 94347617), + (2133547202583038000, 17264134), + (1870469097087786500, 15132798), + (14203365184146340000, 115085847), + (36820500000000004000, 298994129), + (18783526181645750000, 152492765), + (18235104877716445000, 148185138), + (37219700000000000000, 301915104), + (15449533644456970000, 125331291), + (26036738486426410000, 210912027), + (4186733929487113000, 33917294), + (16155405304643344000, 130500723), + (16161086984078459000, 130725809), + (15745805582800835000, 127309011), + (12143578985705361000, 98100944), + (37261800000000000000, 300386727), + (6610672127398155000, 53276108), + (39921054360327880000, 322363506), + (24480000000000000000, 197608549), + (19795078590635910000, 159918827), + (21520537758126070000, 174163512), + (16819071815932926000, 136006194), + (2666443040181889500, 21544166), + (8214264115509572000, 66338489), + (9407436409721006000, 76056444), + (7537095126707285000, 60979118), + (181252523792825100, 1461879), + (17364499966342730000, 140636728), + (7471714904787386000, 60578027), + (2489009887634279400, 20164111), + (17417487870623350000, 141334454), + (4771796163638108000, 38702914), + (4781376746656977000, 38764874), + (16101848708122202, 130518), + (3156775470000000000, 25584796), + (18712143835552096000, 151515976), + (18587426367976497000, 150655935), + (2766841998244968000, 22418629), + (1067195954479556900, 8651231), + (17327684691861336000, 140626938), + (15548233482173938000, 126068847), + (13854853269150583000, 112442835), + (18300000000000000000, 148342225), + (3659748060000000000, 29638724), + (19713269499593390000, 159918154), + (23990625000000000000, 194387236), + (25452539062500000000, 205799985), + (36605400000000004000, 295199943), + (36704400000000000000, 295080549), + (28961132812500000000, 232183637), + (36636899999999996000, 292908229), + (25773520120118837000, 206168209), + (19598441216597553000, 157073103), + (24907631559958450000, 200000000), + (20783304440876765000, 166745412), + (28668750000000000000, 229551399), + (28376367187500003000, 226663738), + (15036200429139446000, 120158135), + (1800000000000000, 14619), + (13552766640000000000, 108202192), + (16264890082697175000, 130000000), + (12490356436119103000, 99952644), + (5038846989895404000, 40295170), + (3855743461724884500, 30822430), + (14109078255059022000, 112948343), + (13410000000000000000, 107247866), + (36270703124999995000, 289471456), + (5837815371301402000, 46577579), + (1109076466487047800, 8851468), + (26100000000000000000, 207875247), + (17184677343183622000, 136619251), + (36971872307421980000, 294468243), + (38025000000000000000, 302540329), + (16800000000000000000, 133358576), + (40554577206753395000, 321147731), + (36855468666397344000, 292101484), + (38990374331550800000, 308685757), + (28961132754778110000, 229417223), + (24140907850112774000, 191660929), + (36563085728610340000, 291026534), + (121483458664738910, 963054), + (31592577904838468000, 252186795), + (13552766640000000000, 108158716), + (11168669186997625000, 89212500), + (46293727437536680000, 368866919), + (500000010792096900, 3973473), + (22582306067091063000, 179413789), + (8205495076175044000, 65217460), + (30147463550373503000, 240000000), + (25034271933694090000, 199138390), + (3637485578069332500, 28937721), + (23959289778301837000, 190827870), + (15858892190042958000, 126523024), + (1517166907443435500, 12108379), + (32762109214284075000, 261914472), + (1100000000000000100, 8796835), + (616231089320051000, 4927719), + (37693114479560720000, 300938617), + (18750000000000000000, 149342515), + (26401934877154330000, 209890240), + (26532901772913630000, 210462194), + (30309922169669090000, 240700838), + (2354296852868660000, 18721945), + (16973437500000000000, 134544946), + (18914314403774804000, 150156300), + (25196938641245975000, 200000000), + (45334570239984360000, 360911915), + (34923362968193920000, 277871736), + (37440234309250010000, 298227273), + (47673632619110150000, 381106212), + (53573554344055090000, 427736942), + (38409700000000000000, 305480416), + (25766730201026850000, 205024056), + (15872367524679182000, 126517048), + (14292754177430559000, 113819856), + (27791601562499998000, 220925683), + (1870582178460193300, 14868593), + (23026357184179530000, 183220271), + (3980407027343520300, 31665753), + (397132167533892600, 3162033), + (29838281250000003000, 237046051), + (6447656250000000000, 51040719), + (24132648015057445000, 191283757), + (742158229255685600, 5934348), + (19400119173914804000, 153811973), + (85391015413433470000, 680008161), + (42592000000000000000, 339452420), + (42995507690953180000, 343017088), + (23432223709999997000, 186909070), + (20176751731082007000, 160645997), + (14947602795761672000, 119104699), + (16879084413886020000, 134349727), + (12175534199461929000, 96989396), + (20052226527261065000, 159951671), + (19791651679271895000, 157717159), + (20475395932280103000, 162889298), + (28376367159130776000, 226045595), + (12339165262394737000, 98261710), + (38909100000000000000, 309181123), + (7323526132777029000, 58175339), + (23026130256450392000, 183144732), + (42161256914744820000, 334737004), + (31948603515018863000, 253798888), + (33175954367025340000, 263272225), + (27593671168976232000, 219140914), + (25127669562465903000, 200000000), + (4217065025466760000, 33606632), + (15161351478927900000, 120922563), + (21063566853230387000, 168253805), + (41533593569134820000, 332644574), + (39326500000000000000, 314682811), + (4095170591054591500, 32752750), + (34770938473124750000, 277457342), + (20319479161228194000, 162204140), + (26049351099501850000, 207686091), + (39289200000000000000, 312383868), + (2620599661560836000, 20824757), + (4403118985247677400, 35000000), + (7750144459013871000, 61636732), + (8694264097990151000, 69193190), + (39502100000000000000, 313656189), + (25178149548733944000, 200000000), + (24337836180243956000, 193728460), + (14467200894514616000, 115091269), + (28678460354959045000, 228511574), + (16506167961090736000, 131458077), + (11668201819609104000, 92817432), + (29086628244887593000, 230979952), + (39885000000000000000, 317192138), + (17558202923660974000, 139972798), + (27189585619251340000, 216449211), + (21023925781250000000, 167026596), + (40529000000000000000, 321154425), + (27969728774603870000, 221738585), + (40093300000000000000, 317372990), + (21438750298941130000, 169742858), + (37160323571515015000, 294945198), + (8073272189112732000, 64092691), + (25209768637538832000, 199857374), + (29771008144631886000, 236299391), + (39707000000000000000, 314717631), + (437271207542629570, 3463556), + (472518018040744000, 3742727), + (5990482233522130000, 47462369), + (39990500000000000000, 316075386), + (20782676679886390000, 164293125), + (17228479691485856000, 136080393), + (22582306067091063000, 178070455), + (11291153033545531000, 88908908), + (22726897461492900000, 179221348), + (11710546750364027000, 92481303), + (7560354717563581000, 59754432), + (33607713910695610000, 265068781), + (40554500000000000000, 318866929), + (67578812727066034000, 528954087), + (33854055841701183000, 264874532), + (28045934080061334000, 220000000), + (41449000000000000000, 324630963), + (14054473369966910000, 110059497), + (10758818173223140000, 84338881), + (6000000000000000000, 46996619), + (673875524471282300, 5282419), + (21452397614275590000, 168681050), + (25744921770338845000, 202033968), + (31592578125000000000, 248060386), + (20008531271916945000, 157185096), + (40543100000000000000, 319311324), + (537865242165988300, 4239011), + (22752342224121094000, 179140407), + (28526886094039843000, 224885452), + (2478125000000000000, 19537551), + (31592578125000000000, 248720899), + (14084630828263156000, 110914521), + (21000000000000000000, 165159064), + (12600000000000000000, 98956163), + (29253515573375460000, 230137625), + (33054492137801482000, 260719735), + (24391495245944517000, 192796770), + (32762109151261336000, 259128125), + (27499218612735664000, 217606961), + (24687397954152560000, 195184381), + (38609765625000000000, 304448590), + (40102100000000000000, 315175225), + (4412606050608600000, 34662956), + (24712886988670878000, 194367372), + (39984700000000000000, 313965928), + (2922853956474419000, 22938059), + (4806176665337734000, 37730249), + (15379439899120452000, 120836240), + (39873700000000000000, 314013339), + (27189585619251340000, 214023246), + (27920077475504194000, 220000000), + (34516406207461400000, 272689714), + (4963874935120802000, 39225486), + (4280242229923019000, 33810172), + (29872269472609830000, 235627200), + (8328629463899432000, 65589626), + (12462441756625953000, 98058804), + (12647433581297648000, 99614746), + (12643108732818899000, 99686283), + (40206700000000000000, 317718718), + (25738460799561340000, 203309010), + (40071679626226570000, 317035191), + (23448775357941900000, 185463815), + (23356562294742540000, 184918630), + (2080000000000000000, 16466031), + (300000000000000000, 2374670), + (21423999517678770000, 169903699), + (26821371900248842000, 212447120), + (5209983207051657000, 41211812), + (2646679687499999700, 20872079), + (32325217495368450000, 255295427), + (20814154864983335000, 164432815), + (27561481475443843000, 217458033), + (24810204309040333000, 195923939), + (39655300000000000000, 314002971), + (78299660733740910000, 618379975), + (33570006892014375000, 264890064), + (39705100000000000000, 312906935), + (15237065554258956000, 119803779), + (25505644765397774000, 200200559), + (20790308595481590000, 163319716), + (13994909347498623000, 110098157), + (39470400000000000000, 309873778), + (533585006176068740, 4186431), + (3157715619806720000, 24778801), + (571754665122494200, 4487297), + (6323945350605945000, 49646467), + (34324200990991286000, 269922712), + (39387700000000000000, 309366955), + (25572339337963390000, 200940259), + (6454340420675261000, 50706256), + (4079152525654305000, 32032307), + (99976133047751180, 784943), + (28276488998668886000, 221744464), + (28005377840805732000, 219835697), + (18147987279449297000, 142732845), + (10105037639967255000, 79569607), + (21480553711540896000, 169367296), + (16085814982887148000, 127031451), + (396500000000000000, 3130133), + (1581567066397461500, 12484503), + (17348992854420726000, 137176500), + (8046785931753705000, 63586252), + (25386629594053226000, 200953918), + (35978320312500003000, 284384207), + (31213170530498710000, 246916408), + (15138244653783732000, 119714441), + (17339243742273948000, 136933373), + (25268008909416600000, 199815487), + (25738460799561340000, 203328466), + (32177343749999997000, 253577806), + (4798267938734224000, 37807808), + (27220942306574720000, 214774675), + (12653006139187094000, 100000000), + (6496027610289922000, 51381078), + (24038623948271360000, 190380248), + (20774413883408515000, 164838639), + (27937096290198290000, 221384317), + (21563869256483710000, 170525480), + (39194531151483314000, 310487581), + (21599881266217700000, 171063396), + (22566622532207583000, 178905769), + (844217782525788800, 6666498), + (966471865385251300, 7669670), + (33054492084803265000, 262687581), + (27937096290198290000, 221845138), + (17218552293292070000, 136805563), + (18843404019013267000, 149942836), + (20496066738029450000, 163364095), + (24687397954152560000, 196539911), + (10129673469789053000, 80525621), + (518368059335994200, 4115452), + (40023835283178960000, 318888430), + (34043791049802550000, 271040115), + (2939062500000000000, 23362960), + (56784000000000010000, 450251288), + (48291758652271660000, 383160900), + (22053922721604450000, 175500884), + (13056490265397338000, 104054826), + (2677515044242852400, 21352844), + (10576691876719892000, 84235434), + (52644140625000000000, 420030000), + (53016697410534630000, 423418239), + (12500000000000000000, 99459781), + (21502474589835903000, 170845858), + (29545898437500000000, 234250747), + (39208314256376685000, 311295560), + (40364062500000010000, 320136254), + (21721546960076520000, 172315578), + (17964032382396790000, 142387591), + (1431139954321782000, 11334343), + (24343958370448077000, 192590806), + (30130664062500000000, 237826586), + (8013002023148524000, 63146928), + (14247802230845915000, 112422386), + (22353562342649446000, 176426454), + (40798700000000000000, 321153942), + (2756739575733228500, 21687245), + (39309110978585050000, 309790311), + (22677097966075933000, 178661492), + (40414700000000000000, 318963231), + (16352638392596732000, 129060554), + (1893989438436219100, 14953885), + (26958809620625867000, 213109781), + (24003919178661460000, 189585339), + (18314979311809872000, 144396832), + (20801433472801948000, 164181504), + (13718523922673430000, 108434575), + (18712143835552096000, 147726634), + (500000000000000000, 3965974), + (500000000000000000, 3950285), + (19231192966351280000, 151582849), + (39873200000000000000, 313508501), + (23356456319428410000, 183699883), + (1345567943067372000, 10593931), + (40009700000000000000, 315551412), + (5099490112731234000, 40237728), + (676300614743687400, 5335083), + (4936234470753560000, 38986053), + (40015300000000000000, 316635575), + (22033230042227167000, 174303421), + (39782500000000000000, 315266967), + (19196318946976240000, 152105962), + (10640944403034841000, 84369706), + (11896844649696877000, 94416956), + (32469726562500000000, 257209592), + (26637405681336620000, 211168079), + (9372062382115723000, 74276716), + (39486914062499996000, 312305178), + (6325600552067874000, 50010000), + (7953561435133841000, 62813467), + (38425490914891310000, 304159329), + (36654225440848564000, 289870716), + (39991500000000000000, 316623650), + (21337017469024040000, 169367296), + (34484228960300590000, 273301729), + (24369024826869674000, 193245557), + (40097700000000000000, 318837636), + (9118947252466688000, 72531620), + (26329687499999998000, 209112590), + (8123575725845219000, 64424605), + (2379552480845702700, 18862875), + (39981200000000000000, 317753613), + (17761095697985876000, 141501527), + (25058441030146380000, 200000000), + (29802122833529864000, 238412697), + (43287890625000006000, 345754363), + (36109727275220914000, 288621113), + (3346332821506866700, 26757146), + (21651562295074970000, 174006803), + (39062600000000000000, 313128220), + (9703158487960095000, 77942741), + (2130041469451524600, 16997486), + (39220800000000000000, 315759772), + (25256595981491830000, 203253596), + (39218500000000000000, 316115702), + (6378569990572326000, 51433862), + (39506600000000000000, 319330875), + (25390792642841305000, 205799999), + (26689782685189890000, 216100738), + (30673702089009290000, 247753070), + (39194531132930335000, 317007853), + (6252907431339319000, 50671695), + (23003868945736700000, 186097703), + (7987026876767418000, 64528769), + (25357617000589240000, 205225671), + (36000000000000000000, 290934796), + (28959362335285084000, 234199835), + (5000000000000000000, 40436674), + (15000000000000000000, 121221180), + (15575594938593243000, 126001850), + (39273600000000000000, 318453476), + (31906155936008360000, 258536591), + (18390657897817223000, 149083440), + (12319705437668776000, 100000000), + (12306794353466302000, 100000000), + (39146300000000000000, 317406600), + (9252395933867650000, 75000000), + (28668750000000000000, 231965484), + (9435939614476884000, 76362305), + (7253946622673707000, 58650840), + (116509284641545730, 945481), + (12352975671803750000, 100000000), + (24241875609589182000, 195948185), + (9126954654667267000, 73800000), + (11726027243620882000, 94900000), + (39307300000000000000, 318809480), + (3065849532565025300, 24911054), + (11407481725649824000, 92564095), + (18780621118698630000, 152196619), + (12330757101303951000, 100000000), + (58784179687500000000, 475313202), + (24698651269896280000, 199617064), + (13350000000000000000, 107840246), + (11010269235000000000, 88848149), + (16864867896420660000, 136262320), + (1758299223329130500, 14217695), + (486949683463100900, 3942295), + (4300000000000000000, 34731506), + (24000000000000000000, 193617625), + (1005564805221383700, 8103689), + (13506398496160545000, 108779005), + (12994271045041603000, 104756845), + (4931394136301179000, 39786024), + (40202200000000000000, 324969810), + (39779296667290950000, 322646573), + (25738460799561340000, 208678636), + (29872269472609830000, 241622211), + (8229658512275448000, 66571033), + (23314489377780048000, 188847719), + (2188658789383491300, 17726367), + (10947750516030254, 88675), + (7373555226176114000, 59803324), + (39896200000000000000, 322808955), + (27656760061400658000, 223884297), + (15003615688476471000, 121676363), + (20455703645240197000, 166142314), + (17724941235997405000, 144197264), + (39340300000000000000, 320824026), + (3287898663430205000, 26827581), + (18390413949057330000, 150303512), + (36563085781326287000, 299530227), + (590353896197648000, 4833679), + (7475920240004740000, 61359343), + (22033230042227167000, 180546733), + (12695191568540803000, 104090616), + (24306336070638567000, 199608790), + (12051654856515924000, 99125000), + (24372367284607336000, 200157119), + (21387846237510300000, 175303174), + (24373469510268854000, 200000000), + (18939360025467716000, 155698140), + (38609765394862810000, 318190227), + (38025000000000000000, 313066131), + (65108900000000010000, 537213299), + (50000000000000000000, 412405384), + (24250546203370170000, 200000000), + (43092645421040730000, 356424615), + (38651746080599880000, 319435220), + (30109823711238537000, 248107519), + (33223307749365740000, 274073496), + (24475512207316726000, 202409999), + (29872269472609830000, 246736771), + (24196159356451234000, 200000000), + (37693114479560720000, 311071496), + (38937373857870954000, 321678827), + (39523300000000000000, 326185333), + (12037259092974582000, 99325461), + (16578495026955952000, 136634177), + (39490500000000000000, 324685730), + (15898223066285296000, 130711658), + (60935836439509970, 501344), + (4728324933228500000, 38909819), + (39250500000000000000, 322196756), + (24355483797613937000, 200000000), + (39246100000000000000, 321750579), + (18295560483867437000, 150000000), + (24349594104402964000, 200000000), + (39438000000000000000, 323399281), + (2438743065592873000, 19986508), + (36544819643900596000, 300000000), + (39272400000000000000, 322031622), + (24000000000000000000, 196266947), + (39392200000000000000, 322675876), + (26095845407556952000, 213668534), + (12822971765945110000, 105037823), + (31119834269943575000, 254460759), + (26110527467587820000, 213668534), + (20615397908682818000, 168571677), + (36855468750000000000, 300627948), + (30309677826570973000, 247412547), + (40167500000000000000, 327415245), + (4182334541007540700, 34073001), + (40507400000000000000, 329169782), + (26622070130459200000, 217174941), + (34810000000000004000, 283587315), + (40764500000000000000, 331592580), + (101472070139750550000, 829848224), + (47728047440000000000, 390828919), + (40666400000000000000, 331751053), + (40194906822448880000, 328226229), + (27182709417009353000, 221871633), + (26531004665564170000, 216762960), + (41176600000000000000, 335874731), + (56152734283074220000, 458785316), + (51766992055431390000, 424904291), + (74635627354924610000, 611403186), + (54398437463265760000, 445683720), + (42407577309487760000, 347274004), + (29119836783859940000, 238564453), + (14492358685422866000, 118950000), + (24000000000000000000, 196709952), + (48481821214728400000, 396142935), + (29165750997901988000, 238354160), + (27221282730325205000, 222998788), + (39100412793228485000, 319831738), + (42082500000000000000, 344612828), + (2939062308535473700, 24114216), + (42127200000000000000, 344720389), + (24532941135163830000, 200179631), + (23605734286320470000, 192799110), + (24437288498341140000, 200000000), + (42137900000000000000, 344261598), + (1593356100145254100, 13008056), + (36270703124999995000, 295379633), + (42779900000000000000, 347220238), + (18044869475849880000, 146452521), + (89068091810774780000, 718863260), + (119307421875000000000, 963196089), + (92408203125000000000, 744973154), + (54383157503220040000, 438156117), + (24898427032231300000, 200652309), + (18142968750000000000, 145945173), + (46211718688708714000, 373333941), + (24830833358573257000, 200000000), + (24764374916916556000, 200047614), + (44457421875000000000, 358078047), + (43523900000000000000, 350896032), + (6740038902779527000, 54454960), + (16096288822753937000, 130446387), + (24721550951262280000, 200000000), + (24636133319853070000, 200000000), + (42912200000000000000, 349369864), + (24688860849763690000, 200959409), + (24686747119873620000, 200520847), + (42596400000000000000, 345007204), + (47381249951114770000, 384223979), + (28330911299965854000, 229697223), + (24647243650579165000, 200000000), + (17265820251037833000, 140353169), + (42734200000000000000, 346662701), + (4933911852816051000, 40000000), + (4931845739302139000, 40000000), + (10554883120426004000, 85662264), + (29761019113288217000, 241951296), + (18315389644860391000, 149205310), + (37693114479560720000, 306505675), + (42414000000000000000, 343722545), + (42584000000000000000, 345412623), + (1231912727564793600, 10000000), + (33607713910695610000, 272406184), + (36799999999999996000, 297391815), + (18807191202786390000, 151628898), + (43565100000000000000, 350308992), + (24000000000000000000, 192434920), + (20000000000000000000, 160064967), + (27723987598979494000, 222770075), + (31592577998648287000, 253220170), + (25738460799561340000, 206628219), + (43689700000000000000, 349714582), + (24395380237225560000, 194713315), + (43371600000000000000, 346797068), + (43494300000000000000, 347429318), + (32762109375000003000, 260862398), + (974168130509271600, 7816756), + (40656445312500000000, 322722237), + (2939062500000000000, 23200765), + (44229400000000000000, 349835241), + (4029455394015623000, 31841542), + (44521600000000000000, 350871776), + (44866300000000000000, 352269262), + (2047781487541355000, 15866668), + (23238676482044790000, 181941105), + (44951600000000000000, 350938087), + (45408700000000000000, 353176102), + (25524655797149168000, 198557924), + (319800633211306050, 2485905), + (4787204660586830000, 37286949), + (7521741760648197000, 58615936), + (29392496039473746000, 229965955), + (29346915748565670000, 229047957), + (26456803861632524000, 206815784), + (44603600000000000000, 349284652), + (29872269472609830000, 233835662), + (17853581509423325000, 139477327), + (44569700000000000000, 348928481), + (3768005425384090600, 29519783), + (21718475210000003000, 169968876), + (20935640268628128000, 163551332), + (15194194510354140000, 118520067), + (3618569855812922400, 28240748), + (15750000000000000000, 122734386), + (12583485602412827000, 98144011), + (44453300000000000000, 347535340), + (13088453597691427000, 102571194), + (44294100000000000000, 347955591), + (29559133073731523000, 232114917), + (4377235662333780500, 34323812), + (6456076704158952000, 50679974), + (27561481475443843000, 215950209), + (40656445282949930000, 319045379), + (1000000000000000000, 7852502), + (4985741954335780000, 39254992), + (17903564489962146000, 140827951), + (19599588755354370000, 154475216), + (36431213135068484000, 287809169), + (31691071080000000000, 250161404), + (43866200000000000000, 346792374), + (2064320604096177000, 16197817), + (2064320604096177000, 16332152), + (23289785743692788000, 184609058), + (44488800000000000000, 351980377), + (44581700000000000000, 351401676), + (30309393041323725000, 239000709), + (44049500000000000000, 348430386), + (27189585619251340000, 215006021), + (71190715536764460000, 564557652), + (40071679687500005000, 317874619), + (71005260765362580000, 564557652), + (23386359550000000000, 186129643), + (380074412472887550, 3021940), + (827483787139858400, 6567591), + (4986973121540955000, 39642044), + (14512226676929235000, 115521248), + (27206835937500000000, 216241756), + (17340403201349616000, 137564329), + (25177092401234862000, 200000000), + (573550575326666000, 4600061), + (2990481530404781000, 23783785), + (5100000000000000000, 40516980), + (43888800000000000000, 347956861), + (21422836519684035000, 169852622), + (12368066173449850000, 98200745), + (24780983256785330000, 197065754), + (35000000000000000000, 277932910), + (43964600000000000000, 347962388), + (5925047747023682000, 46866299), + (42995507812500005000, 339220487), + (44642900000000000000, 350922148), + (12725983718919110000, 100000000), + (192691745552159100, 1525786), + (577242938941712400, 4556966), + (25371487579146154000, 199062481), + (25568378738780398000, 200177944), + (76327148437500000000, 595024822), + (7051703731849971000, 54868366), + (25801993445296906000, 200403887), + (51766992187500000000, 400771652), + (25957489880703648000, 200307128), + (26017835375701455000, 200338015), + (28376367187500003000, 218004169), + (5958218338862150000, 45777625), + (89191991971213930000, 687996622), + (4985742187499999000, 38412866), + (44280675873082180000, 341864778), + (26054374981713478000, 200477585), + (36848000000000000000, 282788392), + (658745026463888900, 5113699), + (47088867149615686000, 361897541), + (31126488967393505000, 240001102), + (32459267654541423000, 250942705), + (44760957472231160000, 345524319), + (46565700000000000000, 359842577), + (1350000000000000000, 10441576), + (495086282536430500, 3832941), + (742677583044099200, 5750082), + (25384614653031023000, 196138590), + (35978320312500003000, 277281801), + (36270703124999995000, 278694770), + (2039720525414035700, 15666020), + (1509066675256830500, 11592060), + (39486914062499996000, 302541739), + (39486914062499996000, 301550622), + (32014764913458143000, 244656584), + (40948828125000000000, 312502404), + (17755524074084491000, 135506926), + (18211039577698142000, 139191030), + (34516406250000003000, 263374864), + (43287890625000006000, 329241248), + (2366933148577222700, 18158583), + (2389108385509018000, 18158583), + (38902148437500000000, 294937206), + (4397990235368489000, 33329176), + (26357674120816020000, 200000000), + (10248632754613856000, 77883768), + (13146135353374919000, 100000000), + (15790936650783030000, 120262621), + (38317382584709380000, 292478215), + (35978320143824000000, 275472854), + (18954062830965862000, 145456265), + (20774413958477804000, 159689828), + (4302329656537602600, 33060989), + (34043791049802550000, 261190372), + (90624216505126930000, 697625928), + (32762109375000003000, 251824816), + (8874233765679853000, 68478606), + (26062784389959918000, 200822369), + (24116741314471277000, 184934065), + (21754553800000000000, 166997484), + (35685937404048994000, 274055823), + (12341968078522098000, 94800000), + (12980611617034273000, 99810697), + (28699631925631275000, 220312979), + (14359040635995380000, 110029968), + (33221720735108923000, 255025191), + (3201576326315500500, 24582907), + (36270703124999995000, 278043291), + (18800068068696180000, 143787578), + (36855468750000000000, 281229268), + (10432018925272990000, 79594839), + (18907743038150533000, 144439227), + (19604882595786637000, 150004566), + (26089436181341030000, 200000000), + (46224100000000000000, 353701365), + (46689700000000000000, 355888617), + (35101171730497413000, 267694892), + (31884960937500000000, 242956461), + (26388256936781345000, 200587713), + (16681054687500001000, 126573450), + (31576701476672980000, 239987281), + (26252326456074895000, 200000000), + (20482031103148306000, 156342555), + (46997200000000000000, 359682547), + (46990500000000000000, 359272528), + (47841400000000000000, 364341686), + (37122356123808640000, 282866649), + (47900200000000000000, 364465185), + (50889843750000000000, 385632795), + (26514111662967005000, 200276737), + (21201354165349680000, 160271429), + (25521299107951270000, 193300852), + (30574846429090222000, 232114917), + (26413597503378825000, 200358222), + (20230285440905010000, 153159474), + (18344417196224672000, 139010085), + (26344178709368040000, 200000000), + (47161700000000000000, 359134612), + (51000000000000000000, 387914002), + (26295120078307287000, 200000000), + (47169900000000000000, 359867618), + (46564200000000000000, 354901062), + (17960812167040657000, 136867409), + (31822561033396916000, 243000000), + (27561481475443843000, 210289015), + (47470200000000000000, 361064205), + (3231445312500000000, 24527191), + (34533715197170848000, 262719229), + (46873600000000000000, 357802248), + (46673300000000000000, 357660523), + (38651746080599880000, 295993853), + (26720555682606604000, 204728307), + (5859445170750082000, 44888114), + (6374902045776828000, 48886855), + (28126235966833082000, 216000000), + (1328775288275979300, 10205725), + (47028400000000000000, 360478447), + (47055900000000000000, 361050613), + (22836302254882710000, 175729023), + (2825810330263781000, 21737776), + (16661053600167840000, 127773830), + (27117148330000000000, 208341027), + (38317382723408224000, 294415939), + (46778300000000000000, 358941339), + (46499600000000000000, 357244935), + (29703743201008964000, 228932256), + (35087490803306480000, 270095211), + (22873916625976560000, 175653331), + (46766100000000000000, 358087621), + (25060485553359130000, 191906589), + (34516406155423896000, 264973412), + (1866292977940321500, 14332186), + (5144553788811160000, 39496049), + (1150614541269014800, 8787975), + (873948581991929000, 6707845), + (57696377447103336, 442735), + (26004222691311900000, 200000000), + (3523828114093201400, 27135337), + (124032327448132900, 952437), + (28699631925631275000, 220550134), + (25098379148491686000, 192443919), + (31884960759910590000, 244794425), + (3799869410000000000, 29178150), + (27189585619251340000, 208512380), + (46856800000000000000, 358232914), + (23102498358950050000, 176627122), + (46988500000000000000, 358302273), + (22698659893941010000, 173085182), + (15731411688484854000, 119872266), + (41533593750000000000, 315733423), + (5381951358429384000, 40892617), + (25725210276185997000, 195103247), + (7226636729527775000, 54710327), + (5032133800846365000, 38115820), + (26505023801648243000, 200380928), + (23649063065355354000, 178419841), + (48602900000000000000, 365593499), + (17220541137358535000, 129495831), + (32000000000000000000, 240248628), + (47673632812500000000, 356752347), + (49364500000000000000, 367937292), + (2737421869461094000, 20603538), + (2737421869461094000, 20384719), + (24856576058087363000, 184746729), + (75169104493440470000, 556415545), + (27045208183493775000, 200000000), + (49647400000000000000, 368296561), + (26876249018621465000, 200000000), + (30181909186532467000, 224344479), + (2668870103373147600, 19835409), + (26997354901327077000, 200891975), + (103959965650000000, 773662), + (34251635331019990000, 253586959), + (45862000000000000000, 340660428), + (28961132558285726000, 215060472), + (26994722745468203000, 200000000), + (29965328543839613000, 222286138), + (49427929687500000000, 365474410), + (21943945153534497000, 162492372), + (19364367112593780000, 143149144), + (49909000000000000000, 368780277), + (49456200000000000000, 365793454), + (5037951383823618000, 37345307), + (49382600000000000000, 365035960), + (13939429486776687000, 102994086), + (37599983406277970000, 278400000), + (48923800000000000000, 361715744), + (14378207465875845000, 106260884), + (48500400000000000000, 357582212), + (14878111735900477000, 109652128), + (13539740978937778000, 99904007), + (21651562292010340000, 160248515), + (19974728467327656000, 147586756), + (5455573854858770000, 40364382), + (48202000000000000000, 355854256), + (19923336827724653000, 147062567), + (47985000000000000000, 355181150), + (48048100000000000000, 357047754), + (34929071249903590000, 259405970), + (7707549316350653000, 57141467), + (19436656463427530000, 143937786), + (20794523757105680000, 153740565), + (22613931958198350000, 167371793), + (48579900000000000000, 360601249), + (21057458636048028000, 156326111), + (47673632787749585000, 354659666), + (26802216492968112000, 200000000), + (10248632573095682000, 76592379), + (26853494350680510000, 200350545), + (20774414062500000000, 154692879), + (22373863547863196000, 166780556), + (15906730637041680000, 118759209), + (30270992167335928000, 225643724), + (30187161249503020000, 225243252), + (7422181281163506000, 55377383), + (47871400000000000000, 358123586), + (33175954367025340000, 248089540), + (45266128688490540000, 339007012), + (55031635120361430000, 411566642), + (47883500000000000000, 358360708), + (24206191279935120000, 181154596), + (18546434952327730000, 138554544), + (14850389131724186000, 110790612), + (18896468052519408000, 141140710), + (25384614653031023000, 189361925), + (11223231849255550000, 83596476), + (5075404654514801000, 37779011), + (20261277971525894000, 151060724), + (48471000000000000000, 360604502), + (13681404408640573000, 101740769), + (48204600000000000000, 359380468), + (48486700000000000000, 361118760), + (13432673360808452000, 100000000), + (33639257591799534000, 250912400), + (18373464376073070000, 137338942), + (47472700000000000000, 355812965), + (24925891350121650000, 186808687), + (47441900000000000000, 356242212), + (26548511770643130000, 200000000), + (12618563302374408000, 95214056), + (46799100000000000000, 352276114), + (29737500000000000, 234451), + (10379702542701030000, 78093171), + (46853700000000000000, 353343155), + (31906155936008360000, 240525449), + (19200000000000000000, 144435175), + (26057382217975894000, 196272606), + (19716338029337375000, 148400234), + (1212900752244792600, 9131390), + (18024260716490772000, 135804240), + (47553200000000000000, 357498182), + (4395355391682280000, 33017980), + (66093749986295330000, 497941473), + (15750087875910269000, 118786715), + (10626190723979254000, 80055316), + (5604908079318216000, 42259617), + (20332853729785220000, 153058573), + (655886975044845400, 4928024), + (25105954033283110000, 189215160), + (26637745672286327000, 200546609), + (64000000000000000000, 480040886), + (48411200000000000000, 361441697), + (6191129460367923000, 46189585), + (26930446270199500000, 200546218), + (49263400000000000000, 365713311), + (40790116994712550000, 303008643), + (48550781250000000000, 360184404), + (47673632812500000000, 352289209), + (74527962290335150000, 551888912), + (6770077722644658000, 50222047), + (27123383261700980000, 200929178), + (64104903749212470000, 476082549), + (27008721177286984000, 200687443), + (51766992187500000000, 383416055), + (27118850858836038000, 200211584), + (41063929814336190000, 303640857), + (27124921663062180000, 200484769), + (27186346003809518000, 200493975), + (50008100000000000000, 367642057), + (32367556359095760000, 238021910), + (27131270273531023000, 200000000), + (48779700000000000000, 358907405), + (27262040723051180000, 199966451), + (130125585937500010000, 961363763), + (166856349704283720000, 1232112954), + (106487333192210350000, 786751127), + (59661328125000000000, 441192626), + (48980200000000000000, 360604431), + (33653999190861950000, 247862106), + (43700000000000000000, 321398299), + (35828575197140283000, 262655269), + (4677781698223266000, 34283149), + (48592100000000000000, 356900898), + (27146170593548250000, 200000000), + (12295312290939939000, 90932606), + (27086198014119133000, 200000000), + (75157617187500000000, 553868345), + (29205301991510360000, 215038109), + (10530732410434267000, 77663277), + (7541968114730836000, 55662405), + (8794045073450940000, 64946452), + (895820404518706400, 6618499), + (27039343534449775000, 200000000), + (26979724543295914000, 200000000), + (13757226378386846000, 102152020), + (47932000000000000000, 355059551), + (27219745327509807000, 201662981), + (15992159945670652000, 118690674), + (6208975087797835000, 46123677), + (7586066417728067000, 56385297), + (234071126581121630, 1738574), + (48030300000000000000, 357804534), + (29121741259231334000, 217509994), + (11359935019787280000, 84824246), + (32082127648804770000, 240000000), + (24146437037478736000, 181052424), + (861174023478626600, 6441094), + (47342000000000000000, 356020732), + (47194500000000000000, 356296812), + (47011000000000000000, 354560015), + (34567200000000000000, 259833296), + (30308554198240930000, 228010074), + (48843164057168520000, 368645855), + (26550182629705980000, 200372598), + (23698241930399007000, 179398794), + (26474400436828210000, 200000000), + (46763200000000000000, 353313798), + (46634700000000000000, 352693667), + (48550781049734660000, 368632004), + (46206300000000000000, 350514931), + (26483266160514896000, 200295978), + (14634375000000000000, 110493771), + (46361900000000000000, 350855529), + (5526694102622503000, 41853397), + (13238448220845666000, 100176490), + (49364375993625540000, 374221642), + (6810902461412084000, 51593106), + (26512701670791442000, 201111701), + (9750000000000000000, 73935637), + (46475800000000000000, 351617821), + (26430794748255937000, 200000000), + (21659834131108410000, 164223426), + (2265017894647871200, 17149214), + (46735800000000000000, 353628811), + (27593145284854817000, 208829100), + (37090422269242650000, 281455210), + (32186751445597913000, 244941347), + (44165039005831150000, 336265734), + (16670410791237777000, 126602879), + (3507497697469070000, 26649192), + (23405859296004735000, 178259762), + (14518218580539666000, 110391481), + (45647000000000000000, 348681594), + (23333907635194065000, 178232391), + (47673632706263540000, 364893944), + (22945162660000002000, 175633541), + (11418164041850760000, 87641045), + (26098786097028846000, 200000000), + (15539175160452610000, 119131886), + (45318000000000000000, 346524652), + (35886937287629017000, 274573051), + (20789712499513400000, 159451720), + (26023955170130158000, 200000000), + (44602200000000000000, 343824116), + (44908700000000000000, 345836821), + (44622400000000000000, 343971694), + (24381226913689480000, 187919040), + (44221600000000000000, 341473101), + (44534500000000000000, 343541486), + (961841118274432900, 7375336), + (44394900000000000000, 341153121), + (30010353954364940000, 230702485), + (10531856338274599000, 80949950), + (44576200000000000000, 341809497), + (37280251292076610000, 286060401), + (11471045069739807000, 88029958), + (10175017860245383000, 78011358), + (4750000000000000000, 36394620), + (45080900000000000000, 344671838), + (44908100000000000000, 343691726), + (12988690719363338000, 99653333), + (44954900000000000000, 344090298), + (23514923404371247000, 180000000), + (26071985079908830000, 200000000), + (26456803861632524000, 202745942), + (3399356663343091700, 26050423), + (1000000000000000000, 7656468), + (44508000000000000000, 341755050), + (44458700000000000000, 341036583), + (43991800000000000000, 337785967), + (44355400000000000000, 340232657), + (27369907916905026000, 210000000), + (44977900000000000000, 344494620), + (12600000000000000000, 96250285), + (45595100000000000000, 347427991), + (37331020170130596000, 284640503), + (45839800000000000000, 350769462), + (12974496852868467000, 99440269), + (37693114479560720000, 288295626), + (5296304423299329000, 40492808), + (46156600000000000000, 351918862), + (46025600000000000000, 351269264), + (23879316203819110000, 182239208), + (43750000000000000000, 332917903), + (46079200000000000000, 351028104), + (45959500000000000000, 351503822), + (119693582549031920, 916321), + (45555800000000000000, 349743478), + (35964000000000000000, 275946111), + (13230581233805530000, 101518244), + (4687511078524580000, 35944546), + (46744600000000000000, 357652624), + (21404865759533203000, 163758239), + (46777200000000000000, 357122920), + (46611300000000000000, 356209930), + (46566900000000000000, 355516225), + (4443090782533541000, 33895261), + (46702700000000000000, 355191712), + (28101651302585573000, 213766854), + (2655858222370424000, 20229561), + (8826072804881038000, 67260961), + (2174688448102779100, 16580505), + (2652598522277614000, 20228433), + (15919341015333520000, 121208838), + (24883024863121480000, 189720362), + (45615100000000000000, 348847145), + (31491243500998365000, 240738854), + (45319100000000000000, 347000871), + (8485869076125804000, 65012924), + (45294400000000000000, 347913399), + (160000000000000000, 1230146), + (400000000000000000, 3075294), + (800000000000000000, 6150279), + (3605700000000000000, 27714941), + (45356700000000000000, 349593721), + (28400118733782300000, 218835826), + (20489365878657364000, 157985853), + (40364062500000010000, 310661608), + (15386627678331180000, 118145615), + (26124837379253640000, 200889999), + (19444054273144476000, 149804292), + (44457421687282024000, 343440092), + (54983203005660710000, 426539582), + (32748469670322140000, 254035405), + (44663100000000000000, 345329231), + (44778900000000000000, 344973722), + (23877766302119780000, 183974830), + (44560500000000000000, 342691559), + (51346389885794020000, 395386420), + (30656838500000000000, 236730171), + (1438513820096139500, 11105563), + (5593818094413191000, 43197969), + (45336000000000000000, 349185721), + (43872656020101830000, 338232140), + (45236500000000000000, 348378609), + (44934200000000000000, 346392421), + (31939693983688323000, 246107826), + (35978320189994080000, 277551607), + (997661617081126300, 7700000), + (36563085824466420000, 282901362), + (45252800000000000000, 349659438), + (25998205306526167000, 200281816), + (20684965938610450000, 159474165), + (16543937069404699000, 127748067), + (25854698487672095000, 200000000), + (2733811235709590500, 21172981), + (49427929603328740000, 383655255), + (20450256347656250000, 158768446), + (450000000000000000, 3490558), + (10866382830116602000, 84409765), + (22821093666114466000, 177525905), + (6000000000000000000, 46660646), + (6174118174636509000, 47991281), + (7585403098796204000, 58930427), + (45156000000000000000, 350113806), + (42229180294808400000, 326845144), + (12295312349277352000, 95506259), + (20330364244426043000, 157725306), + (2683874666495154700, 20834244), + (11664032255536103000, 90495831), + (13100000000000000000, 101541715), + (18184815749380772000, 140788981), + (13490464201247943000, 104530733), + (45409400000000000000, 351079578), + (45653800000000000000, 351758704), + (19604882812500000000, 150387624), + (26074233456610310000, 200357616), + (15803906250000001000, 120832009), + (26116686439766270000, 199995193), + (4473808945940972500, 34225089), + (7444304592839345000, 56975178), + (2680686636341225500, 20524512), + (26093391088789365000, 200000000), + (12587695060941597000, 96622309), + (38651746080599880000, 296101702), + (46097800000000000000, 352022102), + (27217402296645313000, 207904027), + (46023500000000000000, 350958604), + (18921467697857253000, 144285891), + (14041702289905172000, 107207644), + (15272331453390199000, 116731783), + (46115600000000000000, 351718691), + (3279864131478706000, 25000000), + (7552427351799810000, 57590000), + (16332163243272522000, 124650281), + (45962800000000000000, 351618453), + (256203244359419040, 1963378), + (45976400000000000000, 351378046), + (26279717785673896000, 200300899), + (894090477915223900, 6807712), + (46389300000000000000, 354171054), + (32748469670322140000, 249904783), + (7883469011747085000, 60067425), + (46967800000000000000, 357132978), + (59661328125000000000, 451846302), + (12587695093195129000, 95708577), + (62701445297298720000, 475399999), + (8726630905434170000, 66404560), + (46588800000000000000, 355249337), + (46755500000000000000, 356162425), + (7058765708401357000, 53662172), + (24715143590727850000, 187666306), + (5429160000000000000, 41178065), + (10807809085316665000, 81923282), + (47683300000000000000, 360651166), + (34808789004461920000, 263411887), + (11637938128161016000, 88221862), + (46736900000000000000, 355065559), + (28942443098914476000, 219805748), + (5168644631806828000, 39258026), + (40364062269204960000, 307670061), + (24523980064077287000, 186477071), + (3013680248392707600, 22980602), + (4607277779172139000, 35122429), + (1010481319889703800, 7701529), + (35685937500000000000, 271889480), + (46833700000000000000, 355722313), + (47004700000000000000, 355770073), + (30305376891371630000, 229462087), + (47242800000000000000, 357123505), + (2976153855593059300, 22483002), + (47267900000000000000, 356134282), + (37654571385755030000, 283885853), + (29092191297190580000, 219879328), + (6642763173488341000, 50271498), + (14401637395444510000, 109075334), + (897874650431520600, 6804229), + (47525600000000000000, 359170206), + (6974716458149978000, 52683631), + (26537787684468687000, 200704661), + (47503900000000000000, 358631480), + (23688250315208060000, 178854632), + (42118359262068830000, 318791151), + (8486633397801949000, 64356428), + (23976000000000000000, 181529659), + (18000000000000000000, 136069918), + (48016800000000000000, 362087075), + (18480660726276563000, 139345482), + (11823755286726717000, 89084976), + (48190100000000000000, 362273011), + (43580273337696940000, 327889762), + (25744921875000000000, 193378447), + (17804972164037245000, 133956002), + (21480993584804676000, 161486518), + (48115800000000000000, 360998507), + (48481100000000000000, 362435322), + (1926348778419254500, 14452169), + (48185200000000000000, 360579758), + (48414100000000000000, 361928034), + (1748569881054840800, 13062141), + (33669746282668642000, 251852276), + (5341716346585368000, 40014755), + (180000000000000000, 1347290), + (47440900000000000000, 354462322), + (8168012795534091000, 61000125), + (47252100000000000000, 353618316), + (10000000000000000000, 74865915), + (47212300000000000000, 352704798), + (34249487828125696000, 255996642), + (47390800000000000000, 353693875), + (47408700000000000000, 354181799), + (12596337912706521000, 94133221), + (8552242256639036000, 63860982), + (3926385450617354000, 29336475), + (47556700000000000000, 354393644), + (30709059175503100000, 228929642), + (222729388818556700, 1672707), + (20000000000000000000, 149006391), + (51182226562500000000, 380314187), + (996907814117739000, 7451371), + (30698328794352120000, 228160745), + (10541015412441450000, 78464987), + (5485596775299967000, 40857973), + (6370028212485560000, 47396434), + (10798494499204862000, 80295229), + (21403300946076725000, 158952470), + (35978320312500003000, 266624661), + (38024999954187970000, 282095492), + (24257896219900230000, 179874034), + (19100000000000000000, 141399687), + (5853084832234002000, 43353123), + (9682934795055070000, 71761823), + (28730738306154040000, 213232767), + (31642025206285210000, 234579737), + (234798632812500000000, 1723602538), + (159349903982320500000, 1167645662), + (45440117586727180000, 335498756), + (38609765541959970000, 285959559), + (31080439109899380000, 230028808), + (19795535133363030000, 146593420), + (6740039022893106000, 49961811), + (20415495676092240000, 151105663), + (30715429610030297000, 227655526), + (22800000000000000000, 168869122), + (29509700116970303000, 218838145), + (42703124753777295000, 317530519), + (31776330579034317000, 236141539), + (47771200000000000000, 355572520), + (25623522884007820000, 190688849), + (47933500000000000000, 357372810), + (19349096763955610000, 144268655), + (36753371708225390000, 273464076), + (5780060599917544000, 43000000), + (80915100000000000000, 599678135), + (54923729093440230000, 407064027), + (18271647928214065000, 135468481), + (19937670909989860000, 147610734), + (27590088097088967000, 204528879), + (47973100000000000000, 356631745), + (47606000000000000000, 355166172), + (27900000000000000000, 208093944), + (47996100000000000000, 358609366), + (37838013768226390000, 282536720), + (47979500000000000000, 358757769), + (29335482443018134000, 219284189), + (48028900000000000000, 357983367), + (48444700000000000000, 359786667), + (32788477922447614000, 243613342), + (16678823463693965000, 124149682), + (26037304687500000000, 193548930), + (645577711635384300, 4794148), + (3881628242074329600, 28857830), + (39486913960269310000, 294039007), + (48069100000000000000, 357474647), + (11404039159653170000, 84777148), + (34516406201790410000, 257033049), + (645290589757469000, 4803463), + (5795398179271076000, 43231172), + (47742200000000000000, 356849005), + (31983733817403470000, 239775907), + (26456803861632524000, 198184445), + (47787200000000000000, 356976045), + (13543945284500302000, 101146626), + (47562300000000000000, 354563853), + (44457421759748210000, 331711031), + (40015113865235960000, 299509328), + (47329500000000000000, 353806552), + (17529328521706258000, 131023662), + (47172200000000000000, 353444616), + (15749187371220724000, 118281315), + (2880876215217182700, 21625074), + (1347332006405431800, 10112042), + (46591300000000000000, 349052203), + (12322857784771963000, 92294194), + (17558202904607967000, 131652328), + (28757565439166490000, 216000000), + (23608803882609582000, 177675642), + (16719999999999998000, 125738482), + (27891892139846000000, 209403614), + (2149540433389755100, 16119929), + (13082621950306021000, 98053888), + (915243641128470400, 6856133), + (3004969317674640000, 22507065), + (6408527770464038000, 47982649), + (47589700000000000000, 357225906), + (12975331849317861000, 97426517), + (48175700000000000000, 360905219), + (30681385119205253000, 229170977), + (23129537203343350000, 172416570), + (19897265624999997000, 148084092), + (5595043695887662000, 41660188), + (49098800000000000000, 364628697), + (48926600000000000000, 363711155), + (43287890625000006000, 321540370), + (43371129762388080000, 322482069), + (31455814410694975000, 233757021), + (49621300000000000000, 367638724), + (9199999999999999000, 68012790), + (46211718750000005000, 341159587), + (4662940092968229000, 34405638), + (50367100000000000000, 370635471), + (44538268441578290000, 328000000), + (31768112840336810000, 233831815), + (11125781250000000000, 81762139), + (46796484375000000000, 343165958), + (50947600000000000000, 374038140), + (6764282684934666000, 49767069), + (55860351562500000000, 409827317), + (51681300000000000000, 377662524), + (51405400000000000000, 376018471), + (56162725495398360000, 410335245), + (51436600000000000000, 376115657), + (34043791049802550000, 248846870), + (51776300000000000000, 377267947), + (4625707898274653000, 33680308), + (21651802369489523000, 157392948), + (52297600000000000000, 379132656), + (33791005366507540000, 245046796), + (52751400000000000000, 383765576), + (53046100000000000000, 387418498), + (17273482224116443000, 126196193), + (27586424790447040000, 201818841), + (33478488111017290000, 245478097), + (52787200000000000000, 388295959), + (35318381049493860000, 259706134), + (52905700000000000000, 389674172), + (28482827449140695000, 209769088), + (52303500000000000000, 385929158), + (13709761452646664000, 101203282), + (5387534150163337000, 39741738), + (12174572064991357000, 89748582), + (78191796138824810000, 574488872), + (50472155266698486000, 370817593), + (2939062430322137000, 21635979), + (11284920247223466000, 83118031), + (5831730074892003000, 42980341), + (52478300000000000000, 385716104), + (33650065313119433000, 247403126), + (36650675945213110000, 269165374), + (52335700000000000000, 384965815), + (52627000000000000000, 386718101), + (52558500000000000000, 386600268), + (52500600000000000000, 387682123), + (37693114479560720000, 278213617), + (52795500000000000000, 388379275), + (17677274437928616000, 130000000), + (52426300000000000000, 386550503), + (8443789695002241000, 62297250), + (31157715989080773000, 230302084), + (8124077152510036000, 60040406), + (2191343015115921200, 16188758), + (52159900000000000000, 384558764), + (27589828320221725000, 203429172), + (34649441359400450000, 256073022), + (26821371900248842000, 198080096), + (39258179647411470000, 289218035), + (36804022299494752000, 271384690), + (115798828125000000000, 850517321), + (69735818928988810000, 511832065), + (24576082794162897000, 181009380), + (17344753485599887000, 127947501), + (34043791049802550000, 250725636), + (23302266593968980000, 171252132), + (21943945312500000000, 160999699), + (52916100000000000000, 387165287), + (31527870595792703000, 230724699), + (52977800000000000000, 387004294), + (37147851562500000000, 270465102), + (40364062500000010000, 293043723), + (36973633781019650000, 268664226), + (28000000000000000000, 203322416), + (19109665422523920000, 138858508), + (24687627295763935000, 179679914), + (53945300000000000000, 391807087), + (54320000000000000000, 392960612), + (44165038868815580000, 319698101), + (17297370189624430000, 125494029), + (25578223342017516000, 185865526), + (13757226337695693000, 100112585), + (33607713910695610000, 244143578), + (38902148371642170000, 282943076), + (29682879361101718000, 216436039), + (18534562812747485000, 135067350), + (21359179687500000000, 155422506), + (12998717277127406000, 94652126), + (39194531249999995000, 284840910), + (54059200000000000000, 391522294), + (16910332295781302000, 122427769), + (53925000000000000000, 391426073), + (36917212571323640000, 267871455), + (24867773412847710000, 180979060), + (32889144188298727000, 238847159), + (12678629894946007000, 92219900), + (45626952934449275000, 332610528), + (47381249820001710000, 346586981), + (51766992187500000000, 378228947), + (27791601317554880000, 203468062), + (25901749197910524000, 189256245), + (38000000000000000000, 277823303), + (6740039062500000000, 49003112), + (53268500000000000000, 388143984), + (56455765167727660000, 409505561), + (46111808151354790000, 334682183), + (53836000000000000000, 390244065), + (26466834700289982000, 191850271), + (54204000000000000000, 392116817), + (27700983729795043000, 200396660), + (573239938399416600, 4164981), + (28345789058694394000, 205484323), + (32788269256580470000, 238224151), + (13959392952369125000, 101391316), + (35378361962402636000, 256497798), + (54087700000000000000, 392805989), + (41489377466172160000, 301150851), + (54574000000000000000, 394728983), + (38223438275962540000, 276577113), + (37664429118189980000, 272265737), + (55301600000000000000, 398398687), + (21797776045706790000, 156997563), + (55119300000000000000, 396114484), + (54687600000000000000, 393399156), + (24569528467716424000, 176761035), + (55440200000000000000, 397688161), + (54931100000000000000, 394423221), + (54917700000000000000, 393933759), + (17066081283740900000, 122370649), + (55063200000000000000, 393883832), + (46796484375000000000, 333506992), + (35418422053373702000, 251663095), + (29253515624999997000, 207370091), + (56667600000000000000, 400448918), + (52937470094285680000, 374413060), + (42829920000000000000, 302733680), + (11770953664263412000, 83189668), + (57029882812500000000, 401988306), + (16681054560223597000, 118023145), + (58175700000000000000, 410492320), + (113752148423825750000, 808659323), + (46470258964153540000, 330834740), + (95416000000000000000, 681189587), + (37385569888072016000, 267200039), + (48009427551617150000, 342062753), + (3854332828319253500, 27409872), + (12999621356211108000, 92389355), + (32232593731288146000, 228702838), + (30423046875000000000, 215372053), + (57251500000000000000, 406099050), + (57656600000000000000, 408558490), + (84806250000000010000, 597842336), + (48843164062500000000, 342656513), + (58712200000000000000, 412023321), + (33432888386333225000, 235405884), + (48258398336552255000, 340803575), + (78958593750000010000, 556434137), + (37334108834822110000, 261992386), + (52059375000000000000, 364147645), + (12940751275434631000, 90481129), + (58812300000000000000, 412281603), + (59344400000000000000, 417796269), + (115312488369906910000, 809372920), + (66970898233603680000, 470998868), + (37770638814277500000, 264630843), + (59240600000000000000, 416333451), + (29253515624999997000, 204056476), + (59179500000000000000, 414125175), + (59652700000000000000, 414772733), + (21066796875000000000, 146054675), + (221327910450144600000, 1514183974), + (299707617187500000000, 2054135155), + (108196874934109900000, 749003424), + (37520013411079050000, 261101699), + (61194279141869100000, 427370877), + (45626952854357010000, 319884143), + (58173585350000000000, 407255112), + (114014824337568150000, 793237876), + (86393622846052420000, 601069871), + (65508984145117410000, 458274185), + (97531100000000000000, 686328129), + (58862600000000000000, 414384055), + (57999700000000000000, 408705175), + (16086903536520421000, 113418292), + (58192750952216820000, 411222166), + (3231445312500000000, 22766849), + (62877539062500000000, 443808783), + (35333740528111305000, 248508951), + (37181703564364620000, 259342758), + (129604604037799080000, 906113930), + (59681898802688246000, 417741426), + (3013503021578832400, 21283073), + (58311500000000000000, 409896398), + (85391015363249210000, 603388525), + (58591600000000000000, 414008512), + (49479129674697420000, 349853658), + (58179100000000000000, 412983231), + (58142500000000000000, 412312226), + (57866200000000000000, 410759396), + (3689305828148605000, 26213789), + (62585156227383640000, 446091643), + (1014555470704023800, 7181662), + (57641600000000000000, 410519285), + (46698250115593690000, 332781367), + (57780300000000000000, 411177398), + (57738900000000000000, 411293358), + (57573500000000000000, 411845754), + (57767600000000000000, 412819040), + (17001034775530350000, 121433331), + (23657494434941977000, 168768616), + (40000000000000000, 295669), + (57754700000000000000, 410791112), + (33738335919063294000, 240000000), + (29970000000000000000, 213010023), + (2640743810000000000, 18746639), + (31968000000000000000, 226655205), + (30854210222576746000, 218259059), + (58920200000000000000, 415438146), + (39013647658789400000, 275156045), + (20164376889198748000, 142521571), + (58827900000000000000, 414797392), + (58443700000000000000, 412495026), + (35685937500000000000, 251827422), + (59005600000000000000, 414961401), + (25082482091207475000, 176353879), + (40364062500000010000, 283357817), + (40948828125000000000, 286618308), + (32230782531892750000, 225751519), + (41533593750000000000, 290522331), + (19022999206928118000, 133088277), + (3571682465544433700, 25008549), + (17758015471143550000, 124151832), + (44165039062500000000, 308081999), + (55275585731021930000, 386126728), + (17649089339652050000, 123331764), + (38486501755044720000, 269415613), + (610095676671159400, 4261442), + (27054204778510725000, 189275594), + (51766992187500000000, 361140757), + (25215370829116883000, 175916577), + (52644140519619125000, 368309745), + (45211921455062745000, 317463035), + (60246093488476980000, 423220205), + (59354800000000000000, 417400724), + (4907359114402499000, 34543636), + (6835570007088979000, 48096120), + (29211090078327180000, 205265729), + (43001022330268410000, 302016143), + (14597692601299145000, 102178426), + (47381250000000000000, 332396012), + (59693000000000000000, 418930457), + (51182226562500000000, 358953213), + (46796484312783850000, 328471190), + (42466273042804210000, 298081029), + (44457421875000000000, 311767894), + (60122500000000000000, 421324125), + (6287369750772725000, 44018625), + (25822030310903950000, 180475025), + (38685979793701920000, 269754558), + (10248632812500000000, 71336885), + (75157617187500000000, 521537790), + (49295835939514920000, 342099608), + (60627600000000000000, 422409236), + (1675205626727783200, 11782473), + (31861937983554400000, 221999430), + (25495852071254974000, 177780365), + (15219140516872837000, 106277854), + (13781103327242973000, 96144624), + (60477500000000000000, 420796439), + (38858190496639100000, 270430943), + (28668750000000000000, 199108017), + (19790385436876878000, 137686867), + (24070963689865480000, 167315394), + (25452538806983470000, 177234757), + (20206338294677746000, 140589692), + (30562880941756270000, 212258814), + (9663867187500000000, 67018263), + (61788900000000000000, 427402660), + (17558203125000000000, 121106745), + (27614518171447950000, 190161206), + (38609765625000000000, 265247218), + (26032347667338056000, 178939242), + (38691149328165890000, 266570311), + (17850585927221733000, 123573362), + (38154702612982915000, 263600556), + (21296000000000000000, 147259240), + (29794723214806536000, 205649127), + (31007812500000000000, 213555617), + (62857100000000000000, 431453315), + (8252157312386701000, 56588980), + (122668639969232390000, 845156139), + (72000000000000000000, 496467956), + (39062172167031750000, 268278032), + (38773947500366600000, 265557633), + (25452539062500000000, 173921228), + (29650774342229754000, 202210172), + (9984078024873350000, 68108976), + (13455357325309989000, 91866058), + (39192861595011970000, 267075480), + (232431001061250100000, 1596477932), + (63899500000000000000, 436919549), + (133395687385805750000, 918577173), + (43872656250000000000, 298237773), + (27893604889311425000, 190101043), + (35799369830818337000, 242667637), + (33763324693734070000, 229078641), + (2547890631832612000, 17309389), + (63532200000000000000, 432631459), + (39748914225113694000, 271675486), + (48843163867097416000, 334892097), + (62043400000000000000, 427092571), + (42149386450000000000, 290063843), + (61890600000000000000, 426647543), + (6524660075154157000, 45022655), + (61551200000000000000, 423691427), + (61482500000000000000, 421357529), + (30214077928079147000, 207041179), + (38351383142939670000, 263447742), + (23207977466269524000, 159350065), + (27206835819220333000, 187417308), + (29544904977446070000, 203109666), + (60930800000000000000, 421059034), + (33729961322141123000, 233083939), + (6976407390291926000, 48210890), + (8312532529672330000, 57384095), + (9351656176641028000, 64516572), + (43287890625000006000, 298077554), + (43287890625000006000, 297154175), + (41107683683455240000, 282448248), + (38609765625000000000, 265044067), + (61211800000000000000, 420961569), + (34805401916675604000, 239348644), + (20406693628691540000, 140400000), + (39779296596829210000, 274276879), + (26994740910000000000, 186027218), + (40071679662880910000, 276549729), + (40364062355653575000, 279373825), + (2115037584175476000, 14707607), + (45919335715006680000, 318812184), + (45334570309966060000, 315789141), + (21599221220000002000, 150433130), + (54106054687500000000, 375808554), + (48237142203149380000, 335308727), + (38902148437500000000, 270239667), + (3954963008319788000, 27466635), + (36855468750000000000, 255397539), + (43580273413695040000, 302373905), + (46796484375000000000, 324327413), + (7863364876830612000, 54475929), + (60726600000000000000, 421742854), + (1477148437500000000, 10241805), + (38650409084066680000, 268370162), + (25977418165255300000, 179936625), + (700000000000000000, 4869252), + (46211718750000005000, 319263309), + (46504101562500000000, 320215878), + (28493236524732154000, 195670700), + (21066796875000000000, 144414867), + (1428907231332152000, 9798207), + (29508614771407180000, 202568710), + (62356000000000000000, 427127923), + (21088000000000000000, 144018790), + (43410318355059670000, 297000890), + (10287551373948998000, 70519750), + (62761600000000000000, 428987429), + (62501200000000000000, 427631091), + (47381250000000000000, 324032350), + (99355115894105010000, 681420007), + (33346874999999996000, 228369808), + (39659015955448310000, 272307940), + (62204000000000000000, 426859656), + (20286990000000000000, 139284248), + (44731893849024630000, 306401838), + (41820189697432910000, 286714203), + (71064257812500005000, 486213596), + (27747544715064963000, 189741277), + (62002900000000000000, 425347340), + (61376900000000000000, 422918687), + (61286200000000000000, 424158228), + (35337770346145100000, 244554423), + (33929611080873990000, 235032358), + (61092600000000000000, 424642383), + (28485708030000000000, 198033155), + (61460000000000000000, 425890036), + (35513071795929747000, 246105769), + (40199430899118400000, 280579641), + (61250700000000000000, 425949519), + (55407753635869270000, 386131252), + (31532845895633660000, 219061466), + (29680301787795677000, 205737754), + (63968000000000000000, 441923209), + (74450884559949380000, 515053220), + (39138263541405900000, 270832664), + (46796484375000000000, 322828680), + (62342400000000000000, 430744254), + (62737000000000000000, 433032154), + (33346629651246645000, 229377496), + (52059375000000000000, 357001141), + (365512760020642960000, 2463111162), + (419880000000000000000, 2832148354), + (55860351486996020000, 382107207), + (3231445302888325600, 22143318), + (35640000000000000000, 243724496), + (4956250000000000000, 33844220), + (33346874863714505000, 228547492), + (23013074512536007000, 157405755), + (23221490323502350000, 159474339), + (23836965532839490000, 163977388), + (63278400000000000000, 434251775), + (27992000000000000000, 191470326), + (33411399738379858000, 228039258), + (18435351562500000000, 125592188), + (69980000000000000000, 475244738), + (6601592573805241000, 44776056), + (21421749653443260000, 145440494), + (26094774692853320000, 176961053), + (56000000000000000000, 378655827), + (30715429586407895000, 207963387), + (17157933905731830000, 115972813), + (29000000000000000000, 196164681), + (69980000000000000000, 471705412), + (47363334156215190000, 319318950), + (64587751039751030000, 437179533), + (37753978464863610000, 255536390), + (37147851292798550000, 252410084), + (40682371644753100000, 275661403), + (40424698310421740000, 275436072), + (46807333607337930000, 318533726), + (55984000000000000000, 379590638), + (63777300000000000000, 432984865), + (64203500000000010000, 435436963), + (30906732891524305000, 209574772), + (31848820369910706000, 216446088), + (50378400000000000000, 341806730), + (469510011667536700, 3210656), + (58774800000000000000, 397229651), + (66970898163274470000, 453208114), + (47965559430000000000, 324489518), + (25947323683516590000, 175573101), + (60246093471462680000, 408908717), + (19100411015932936000, 129700683), + (25526746211834114000, 173063353), + (74520000000000000000, 503429400), + (62292773264238010000, 421064778), + (64457800000000010000, 435231116), + (50092000000000000000, 336858604), + (26168554666499228000, 176004969), + (23367841570812092000, 157444185), + (64011799999999990000, 432629011), + (63566400000000000000, 431572744), + (126616992042249390000, 865497935), + (80712890363167620000, 555826296), + (33239784613908220000, 229065489), + (68212593213545820000, 468368159), + (62031000000000000000, 426255228), + (2529153148446092300, 17487016), + (62388700000000000000, 428280082), + (63285100000000000000, 432485238), + (30827866050185273000, 210641373), + (29440962633305330000, 201598720), + (21001797267834270000, 144070811), + (28015653470578213000, 192523012), + (61400800000000000000, 423300284), + (61693100000000000000, 424886692), + (9138721178548833000, 62883606), + (102393200000000000000, 707395710), + (48285153761188910000, 333898803), + (61690500000000000000, 424917878), + (40948828038042020000, 282123448), + (61489500000000000000, 422907600), + (13381305539766770000, 91966197), + (44749804571759780000, 308195289), + (60970200000000000000, 421503239), + (61574800000000000000, 425249131), + (14437922775062230000, 99439662), + (32000000000000000000, 220030076), + (21943945312500000000, 150239209), + (32956216699866490000, 226078403), + (38400000000000000000, 262339302), + (40184021220837910000, 274819558), + (62814500000000000000, 428814798), + (35423025134927307000, 241826982), + (21091008060587164000, 143914515), + (25160156250000000000, 171397253), + (13913283500856180000, 94837533), + (19050145422951050000, 130004941), + (25744921735536095000, 175973785), + (62467900000000000000, 428334959), + (62658600000000000000, 429211064), + (20717110770704605000, 141841035), + (27791601492901835000, 190607493), + (61975600000000000000, 426426178), + (13756422788857717000, 94720754), + (53813671875000000000, 369641799), + (47088867084784760000, 323695285), + (39779296807736090000, 274301391), + (4931983252323875000, 34017420), + (4348054393620364300, 29979895), + (39486913918115545000, 272879493), + (27811906683902824000, 192086398), + (37440234155551710000, 258934031), + (32748469670322140000, 226296258), + (37744068790191950000, 261124426), + (2280519693939057700, 15781635), + (5590206384800323000, 38674361), + (61859000000000000000, 426920101), + (62589600000000000000, 430038744), + (39194531018494360000, 269340067), + (21772491366059590000, 149561766), + (62806000000000000000, 430129780), + (21850613539973520000, 149575294), + (1394138475826851000, 9551316), + (49714492327669280000, 341220261), + (35680772779051475000, 245648901), + (53228906101898715000, 367636027), + (34929071249903590000, 241162931), + (38317382653661560000, 264854240), + (8561068510187867000, 59179546), + (49312780408988650000, 340170155), + (40948828062596600000, 282671091), + (41533593714284920000, 287563298), + (20179055343798477000, 140024527), + (4019736552660433000, 27881784), + (5808898143055960000, 40277481), + (22690636166573523000, 157169290), + (21604880846424424000, 149792559), + (46504101454649800000, 323221684), + (21411000000000000000, 148801321), + (40656445063749850000, 283032734), + (39779296824120780000, 277735625), + (4253780003037443000, 29708132), + (45334570040392140000, 317404240), + (25000000000000000000, 174988778), + (6986290937024550000, 48844078), + (13985299938146920000, 97702636), + (60085700000000000000, 418638261), + (45626952933614800000, 318050219), + (45334570231760020000, 317057377), + (60248800000000000000, 420715166), + (39522357832355360000, 276051367), + (25480283196661510000, 178392616), + (46504101339401590000, 326438393), + (11820611200900086000, 82997307), + (37147851357168650000, 261332234), + (11080068196911140000, 77943525), + (38902148396487475000, 274211914), + (38609765625000000000, 271882175), + (18082143359475340000, 127362822), + (59080800000000000000, 417313271), + (22532928161357517000, 159213132), + (8183635238218377000, 57759092), + (3810000000000000000, 26878742), + (1893063388033666800, 13352381), + (59578600000000000000, 419286675), + (19861525888156410000, 139372229), + (38609765625000000000, 270356827), + (13645614878516617000, 95559383), + (5375045906754797000, 37667154), + (60294900000000000000, 421270464), + (24909089055379407000, 173985959), + (17265820312500000000, 120329773), + (20842754657830904000, 145459306), + (30000000000000000000, 208719525), + (39430514891895300000, 274699101), + (60041300000000000000, 417558276), + (16033641060395741000, 111439906), + (18296297117128930000, 127324499), + (56737499755679000000, 395914187), + (23408172308873420000, 163376492), + (19478573350569492000, 135738611), + (60242400000000000000, 418595327), + (60764200000000000000, 420376837), + (38837124213442240000, 268737342), + (61238700000000000000, 422982278), + (15026901710670627000, 103722990), + (38970202152796004000, 268490721), + (26269339468395890000, 181084436), + (62240500000000000000, 428063891), + (57428699958017900000, 395297003), + (28828118542362894000, 198437833), + (61409400000000000000, 423631422), + (61619800000000000000, 424655606), + (34164739472828293000, 235449992), + (880061012027938800, 6079872), + (17854263898183807000, 123275306), + (34693816239553712000, 240000000), + (23813772709999997000, 164635771), + (39486914062499996000, 272367957), + (14578925636101513000, 100364583), + (20000000000000000000, 137512878), + (22953688388445737000, 157996166), + (22528710826412925000, 155325693), + (25000000000000000000, 172176633), + (45626952875181695000, 314784752), + (32400000000000000000, 223414182), + (1450391815107876000, 10000000), + (2900328004153023500, 20000000), + (20485073047326003000, 141379744), + (23400000000000000000, 161319093), + (31680000000000000000, 217967612), + (21059596586171994000, 144985570), + (19800000000000000000, 136183836), + (26033939499999502000, 179280219), + (29371829871203600000, 202670907), + (21091137485285536000, 145430741), + (19372569549899090000, 133385656), + (10309622799144212000, 70908714), + (62893900000000000000, 431439977), + (14574102623899417000, 99901483), + (63203400000000000000, 432053458), + (47701120123502715000, 326225353), + (1000000098528361200, 6850937), + (52351757599204890000, 359348370), + (43209698178731200000, 296397731), + (32787536969710780000, 225047242), + (61457800000000000000, 423270443), + (51668541286803240000, 355620551), + (55007430299755750000, 379025811), + (39629646176819960000, 272944776), + (82704266570907630000, 571075021), + (23251760820968680000, 161170192), + (74572851446714170000, 518739759), + (7617187282336560000, 52960401), + (82957044960896570000, 576311218), + (63968676545402660000, 443408552), + (35101171642853730000, 243672152), + (15429291357902911000, 106869437), + (77629280775166030000, 535949014), + (26944347941061915000, 185867780), + (10438173175570480000, 72102021), + (34726845310634566000, 240268859), + (9377656348064463000, 64985950), + (32934429534574924000, 228581339), + (46048467641470710000, 319128752), + (42238782686574750000, 292979070), + (44165038850526110000, 307300898), + (55275585800065380000, 385999296), + (33175954367025340000, 231628145), + (42995507627546214000, 300594129), + (12388823693662015000, 86623667), + (7008701054265117000, 48970861), + (885850658127725400, 6181671), + (83929101562499990000, 584493649), + (48097240956232655000, 334854759), + (60364300000000000000, 419652582), + (24035454462428025000, 166584117), + (56060534770650060000, 387418784), + (81590038835911500000, 564932359), + (4400976431927275500, 30567506), + (120101948976114140000, 829871917), + (51682402244622430000, 356584799), + (79543359297588530000, 551423544), + (70447989522825680000, 488044635), + (17265820264208187000, 119765163), + (30355476439135355000, 210199523), + (39629646176819960000, 274396227), + (60914600000000000000, 420243730), + (29466684630610096000, 203259979), + (24285625000000000000, 167385220), + (836683747958801800, 5781635), + (42410741986072895000, 292794252), + (40364062416114740000, 279499663), + (2150000000000000000, 14893306), + (34929071249903590000, 241633661), + (25762339102576900000, 178338871), + (60246093536095764000, 418352435), + (27825437113433100000, 193255334), + (60989800000000000000, 424525464), + (27462848829999997000, 191199274), + (38651746080599880000, 268453329), + (49720312449740660000, 345813804), + (61080900000000000000, 424230313), + (2310395288433550000, 16028460), + (75450000000000000000, 521533714), + (32132787810238185000, 221985853), + (7032421750526151000, 48651553), + (7223609496634584000, 50000000), + (23687571008410644000, 164142885), + (29509225064029370000, 204878319), + (32762109375000003000, 227208721), + (27216727283575575000, 188901834), + (61343200000000000000, 424812054), + (32838509978558657000, 227404957), + (18940319518709694000, 131095583), + (31007812500000000000, 214233635), + (34224023437500002000, 235898038), + (42584696142182430000, 292936551), + (45919335937500004000, 315597434), + (20030033764385935000, 137759265), + (5516356059873595000, 37957575), + (24867773437500000000, 170822858), + (24000000000000000000, 164571948), + (1477148437500000000, 10119760), + (62759600000000000000, 428966715), + (31336243185558440000, 214157740), + (8633558172952267000, 59088210), + (746869670320054400, 5129302), + (34808789062499996000, 237770130), + (34897841026399916000, 237782392), + (37440234188168675000, 255384045), + (1801589948956599000, 12306183), + (36855468582983766000, 252100042), + (62990000000000000000, 430032575), + (31348608436018740000, 213987457), + (61896500000000000000, 423928332), + (23605297195826553000, 161733542), + (62467300000000000000, 426677382), + (37284654757149794000, 254693601), + (23674197488578978000, 161637278), + (62979700000000000000, 428663415), + (31411471243347325000, 213769776), + (63238800000000000000, 429450237), + (21794878508041626000, 147935613), + (20314113163751743000, 137754278), + (19578390591859216000, 132575747), + (33346874999999996000, 225382585), + (65228300000000010000, 439311762), + (34765451789068480000, 234124331), + (65611300000000000000, 440926657), + (20124563531462670000, 135158700), + (65985400000000000000, 444528269), + (43328218309589710000, 291836506), + (136000000000000000000, 910197332), + (83643396542711820000, 559309861), + (64341143326592190000, 430155008), + (76760000000000000000, 512895320), + (153974299999999980000, 1037442937), + (41956127140314540000, 283539183), + (50385351650826084000, 339382797), + (22000000000000000000, 147804175), + (34908331438926710000, 234052280), + (29077067358937084000, 194774536), + (41916570365935030000, 281491517), + (24148155029233580000, 161567846), + (41803496381512140000, 280453051), + (64000000000000000000, 427752944), + (42235811330488205000, 282352701), + (74306122448979590000, 495687328), + (142990429594016970000, 957165180), + (66400650181050180000, 445247071), + (65508984279165930000, 439693658), + (44606250000000000000, 299319174), + (22434991417552978000, 150185505), + (49720312500000000000, 331987886), + (372710331534235650, 2509039), + (915722935977041200, 6133914), + (30595000000000000000, 203704275), + (366909925135730000, 2442743), + (32085875885882580000, 213861346), + (76327148404357190000, 510705936), + (39776462758176750000, 266224830), + (7324804687500000000, 48943019), + (44000000000000000000, 293464726), + (26606994348169245000, 177527251), + (26037304631882530000, 174051446), + (28800000000000000000, 192308064), + (178664786251738430, 1192990), + (26016941937138352000, 173388897), + (1511198934082535700, 10133007), + (9663867187500000000, 64121357), + (44279213112123695000, 294362298), + (36337184745873330000, 241572835), + (21159069162898612000, 140602474), + (30400000000000000000, 201640046), + (36535858254692585000, 241765201), + (13090729775317553000, 86638800), + (28209818524853498000, 186415784), + (67882400000000000000, 447060639), + (13639818576653812000, 89747136), + (30742480976285434000, 201955223), + (51474609375000000000, 337172469), + (2373376348456366600, 15676810), + (2395049869437686000, 15676810), + (27027184802635630000, 177089811), + (34808788772885135000, 228574308), + (29938883897972654000, 197045001), + (27499218668897250000, 181355416), + (68140429568677050000, 450903174), + (43313333211752050000, 286581047), + (24867773437500000000, 164140550), + (35840000000000004000, 235283824), + (46504101562500000000, 306179611), + (30655077119931576000, 201410216), + (14049609111551791000, 92454450), + (29329956782054710000, 193303530), + (27499218713281590000, 181601880), + (36137355091158660000, 238336191), + (36799999999999996000, 242082643), + (55275585773443630000, 364222613), + (8276783460539893000, 54659999), + (13122253190123651000, 86558132), + (48258398158540150000, 319040807), + (45923927548634145000, 303329381), + (21592521066542793000, 142279704), + (24000000000000000000, 157889149), + (24800000000000000000, 162871699), + (45919335937500004000, 300821095), + (6384150002172783000, 41664051), + (26394109178994016000, 172470533), + (22236328125000000000, 145053739), + (58491796839211610000, 382599020), + (67798500000000010000, 445451037), + (42161256914744820000, 276982221), + (67393199999999990000, 443583689), + (2939062500000000000, 19311388), + (42696821109308360000, 280995547), + (67908600000000010000, 445088702), + (21818399933131570000, 142913760), + (27206835778181920000, 178516664), + (15511523437500000000, 101465652), + (35363465562887995000, 231737845), + (21820757936896213000, 142910868), + (23405859077353530000, 153536428), + (32867918310781440000, 215318069), + (69017600000000000000, 450518849), + (27206835649351897000, 177956775), + (35621037070344643000, 232479209), + (25961000000000000000, 169645726), + (11418163887515600000, 74812057), + (30815032463446057000, 201601006), + (89558298150502940000, 584595314), + (88314843520624980000, 577030276), + (62000390573800145000, 407245482), + (25000394263226974000, 164717937), + (15650000000000000000, 103042771), + (41241210870433700000, 272057999), + (59368945258827980000, 393037534), + (4423453125000000000, 29312044), + (3760253548409929000, 24910132), + (26796630529070960000, 177324918), + (60830859267776890000, 403433008), + (35832145582026670000, 237613284), + (23620966886011953000, 156726373), + (65508984322665650000, 436031282), + (31815996507608560000, 211810408), + (29640588354487497000, 196898407), + (54106054687500000000, 358355179), + (26301288604736328000, 173703930), + (67059600000000000000, 441430904), + (34743817523549290000, 228674740), + (24575390625000000000, 161309328), + (29507820368604357000, 194054639), + (42351913191952245000, 277337774), + (66922500000000000000, 436556472), + (31099690587830514000, 202820557), + (67154100000000000000, 436964103), + (32750424317724447000, 213059103), + (42018265438076600000, 272989808), + (39300129789572480000, 255561420), + (24979565792396677000, 162804153), + (65414900000000000000, 427697501), + (25519111300190530000, 167384327), + (36470631608913002000, 239740334), + (30878345010065460000, 203462098), + (30838182810940838000, 203640795), + (272559777917717200, 1799999), + (67830476718899150000, 449477762), + (26650982808197444000, 176683265), + (57029882812500000000, 376963675), + (63021100000000000000, 417195758), + (62831700000000000000, 415280955), + (34698135086524408000, 228545596), + (14064797583565720000, 92481097), + (15166082866195677000, 99886073), + (37587947534377574000, 248021283), + (34294119976621814000, 226862787), + (9956249886315084000, 65965865), + (497671401914615550, 3266108), + (58784179670150504000, 390428296), + (53521289062500000000, 354972329), + (49720312323124370000, 330246640), + (36801574704639590000, 245190376), + (61744600000000000000, 410353547), + (45921868927793130000, 304034327), + (50305077991283780000, 333639511), + (42079501877415215000, 280000000), + (31070399885815340000, 206494956), + (36801403740172767000, 245025032), + (32695458524888910000, 217371403), + (21483185302945358000, 143000000), + (61714100000000000000, 412007037), + (15046702886729232000, 100458549), + (62421700000000000000, 415611457), + (62799500000000000000, 416275524), + (1734396482841120000, 11490239), + (13418913906176920000, 88946916), + (63030800000000000000, 416399871), + (24050788099148923000, 158921804), + (33791615266141584, 233759), + (4514807202535223000, 29862902), + (47127305156508270000, 312290568), + (2069878788330025000, 13608936), + (2069878788330025000, 13716044), + (41825976333833650000, 277995025), + (39138263541405900000, 259740495), + (30673702089009290000, 203063069), + (26120067493447970000, 173166619), + (41533593750000000000, 274757476), + (40071679687500005000, 264323129), + (2883103339438214, 19023), + (7547313291044604000, 49700381), + (27588186704351340000, 182092896), + (15495502471527960000, 102474013), + (32469726401259864000, 215091718), + (41825976562500000000, 276537006), + (19688986949690230000, 129893098), + (40199435240724900000, 265823141), + (24003919178661460000, 158565662), + (37732616925864360000, 249775607), + (35393554486316175000, 234899252), + (18012989703056906000, 119774761), + (12385006763342242000, 82441149), + (41806927325577050000, 278824859), + (32748469670322140000, 218132108), + (3077377359302470700, 20509117), + (24960728382877060000, 166515930), + (17479681019683176000, 116453548), + (35059490508691567000, 233139327), + (39486913835849230000, 263042875), + (707352728969050900, 4707339), + (60895948078176330000, 404704764), + (29838280979990598000, 198399357), + (62292773386339410000, 415498456), + (61974600000000000000, 412720840), + (14036604535476353000, 93476470), + (53521288883771195000, 357231633), + (61486700000000000000, 409632981), + (61766200000000000000, 409801657), + (49135546875000005000, 324795562), + (38957646534935020000, 256762405), + (63265600000000000000, 415555621), + (468326566392309800, 3088434), + (23466495258596160000, 154180573), + (38609765354601260000, 254200115), + (50889843702744840000, 336050733), + (24283007658896896000, 160975123), + (20455224110955745000, 135397816), + (27937096290198290000, 184880043), + (417563511136198000, 2758411), + (61598800000000000000, 408756672), + (24687397954152560000, 163760501), + (61457100000000000000, 406496785), + (12001713896583952000, 79379122), + (500000001321574400, 3297741), + (61166600000000000000, 403247367), + (44896132143599804000, 296295863), + (97671093529147360000, 647663890), + (4300000000000000000, 28556988), + (59997900000000000000, 399839003), + (60083600000000000000, 402025584), + (38651746080599880000, 258395498), + (60682600000000000000, 404328420), + (28786921124120125000, 191233650), + (26622070312500000000, 176525110), + (38902148437500000000, 257387899), + (62280700000000000000, 410679511), + (38701138281793855000, 255403517), + (14052337612972544000, 92900000), + (61434000000000000000, 407165072), + (61044700000000000000, 406245305), + (29086628244887593000, 193465636), + (34523860319442244000, 230040369), + (61175200000000000000, 406610826), + (13430890408362723000, 89270800), + (42118359374999994000, 279232036), + (21066796807351185000, 140063533), + (29033023413546820000, 192704201), + (26095845407556952000, 173193264), + (30246922876807100000, 201092695), + (15598106833645900000, 103586957), + (27399975400676782000, 182326604), + (3341988609368654300, 22010229), + (19027674212737000000, 126812112), + (61321900000000000000, 407457206), + (60603800000000000000, 401048563), + (26160043630207476000, 173193264), + (60257600000000000000, 397847385), + (4487100080699324400, 29618132), + (1172763911831087400, 7657517), + (54578531360391455000, 359083137), + (7452483238876540000, 49032925), + (36000000000000000000, 236255764), + (40364062361010550000, 265358496), + (35978320051877610000, 237127947), + (21012571788556677000, 138754135), + (15760216107057742000, 104198522), + (3519908018952245000, 23554881), + (5278125000000000000, 34796134), + (23811813597766740000, 157132117), + (27214345096368860000, 179829948), + (785766642491301000, 5197129), + (60395200000000000000, 398029450), + (23021759008282726000, 151776789), + (45042187246143760000, 297626601), + (19220770727450034000, 127278304), + (34516406055399555000, 228975356), + (45042187458202900000, 299603530), + (22605960727531373000, 150238684), + (18119087089093476000, 120593823), + (25275431769722348000, 167914719), + (39486913974150046000, 262872461), + (1131933875379431300, 7497870), + (26146147066424790000, 174443205), + (10833398327730373000, 72368461), + (37440234320881820000, 250510724), + (21016626767333430000, 140897400), + (45334570163345890000, 304605580), + (58664100000000000000, 395549453), + (41974414845674310000, 282724154), + (42703124707933430000, 288100316), + (1810266807288562700, 12126317), + (1797799285339294500, 12126317), + (30783855658295710000, 208243914), + (4845184996668261000, 32736922), + (72233788894139700000, 490343781), + (30144937618024510000, 205342243), + (48258398435502440000, 329602411), + (2327880185645828600, 15898620), + (46211718541295670000, 316586869), + (59661327846007005000, 410200552), + (1018465657467575200, 6959162), + (2903982914457032700, 19972892), + (57230700000000000000, 392815618), + (47088866948007080000, 323610354), + (15992729255593865000, 109847791), + (24175845249493262000, 166478173), + (47507394981062205000, 327942535), + (40071679687500005000, 276242155), + (47389482418772790000, 325717595), + (42703124723676490000, 293930556), + (50012695208833155000, 345332463), + (52351757812500000000, 360877562), + (28530838902398255000, 196827377), + (57395700000000000000, 394938506), + (57703800000000000000, 395507349), + (40180235937136640000, 275675983), + (57520000000000000000, 393781855), + (13051736258321396000, 89360195), + (26382147628771844000, 180870476), + (33966000000000000000, 232431880), + (57807500000000000000, 394351863), + (56737499944954180000, 387658474), + (58784179682664600000, 403220951), + (65962404624321210000, 454383437), + (69830952810964300000, 483264649), + (34874892287560100000, 242216365), + (47119143090571890000, 328175952), + (57531833260888785000, 399916216), + (48416000000000000000, 335333272), + (3523828125000000000, 24255619), + (64834867349844980000, 447320230), + (58070000000000000000, 398877866), + (58331100000000000000, 399089791), + (60538476337681270000, 414886856), + (54983203125000000000, 376284469), + (16102988036287290000, 109350089), + (79067009290373600000, 538651596), + (40257561581688970000, 274037768), + (63462304687500000000, 430918028), + (60288000000000000000, 407569108), + (42551960293576520000, 287946352), + (52059374921795530000, 353468212), + (51182226562500000000, 346968649), + (60485700000000000000, 408416376), + (32438739428578623000, 219168106), + (60646900000000000000, 408690209), + (61259500000000000000, 411042037), + (61536300000000000000, 411113501), + (4612389636210812000, 30802034), + (62021500000000000000, 412689771), + (3600000000000000000, 24117374), + (61706700000000000000, 411248280), + (32829817940795417000, 219526600), + (20333715384384150000, 136222941), + (61116100000000000000, 408197689), + (25914690607748088000, 173147671), + (49427929418895600000, 331475357), + (14785187475501337000, 98928395), + (60107400000000000000, 404658817), + (47381250000000000000, 318617138), + (27561481475443843000, 184847789), + (60761100000000000000, 406241113), + (47088867187500000000, 313635804), + (48860399048367300000, 325976786), + (52059375000000000000, 346725521), + (69894726389375340000, 466571853), + (32963000000000000000, 219974147), + (18227499825926120000, 121419609), + (63037100000000000000, 418713703), + (51182226562500000000, 338608492), + (20244297587882193000, 134000000), + (9518187666127802000, 63066942), + (62403500000000000000, 414528112), + (32325217495368450000, 214610647), + (34929071249903590000, 231350792), + (24756582260582600000, 164177858), + (12733023574896185000, 84552709), + (32325217495368450000, 214162811), + (57567719831914300000, 382350972), + (27103152674409700000, 179917551), + (24575390625000000000, 162841748), + (52059374777187934000, 345843053), + (18825348081272570000, 125373552), + (27333208201851190000, 182492182), + (62585156219481660000, 418003444), + (27592804010156573000, 183869293), + (39779296875000000000, 264448479), + (32469726562500000000, 215307783), + (40656445018738840000, 270103783), + (40071679568069400000, 266976011), + (34516406250000003000, 229641767), + (46211718508828030000, 308071475), + (17543435779120323000, 117216727), + (25738460799561340000, 171647514), + (19954386595438940000, 132860099), + (16542235375017409000, 110000000), + (35702484429354620000, 237949639), + (5862890489613469000, 39132201), + (41139127215324870000, 275040828), + (18727734375000003000, 124853856), + (28556560090115994000, 190698040), + (61166700000000000000, 409050538), + (25681409915054854000, 171683993), + (37147851483706400000, 248837365), + (40656445217395550000, 273089466), + (901299005129700700, 6046070), + (4942651976031942000, 33253388), + (47381249919254330000, 319364558), + (59938500000000000000, 405544192), + (22220207260385755000, 150389411), + (60456400000000000000, 407979734), + (60001800000000000000, 405554038), + (49135546610994280000, 333397989), + (31194518360000000000, 211459866), + (21623966724434133000, 146308804), + (32338422754193273000, 218384988), + (31942649883166720000, 216097330), + (41857474565664600000, 282621130), + (27215671544775496000, 183958646), + (60294900000000000000, 408818847), + (60583600000000000000, 410036373), + (24717356611370844000, 167344429), + (61398200000000000000, 414482519), + (35422759820542595000, 239291848), + (61635500000000000000, 415316779), + (38818669078358060000, 261777969), + (12858590318226823000, 86654358), + (34866782413509255000, 234571674), + (60565648205207040000, 406092925), + (1698037396780729600, 11379890), + (40911203413125700000, 274591285), + (61932100000000000000, 414709778), + (12834256180725070000, 85929287), + (62319700000000000000, 415857200), + (30098322572842574000, 200938324), + (43027724183552320000, 286666490), + (48258398437500000000, 320483595), + (4305069197187279400, 28591481), + (2816106488421773300, 18832782), + (9687558923350667000, 64370156), + (62527100000000000000, 414036161), + (37601200000000000000, 248110803), + (42439066755229890000, 280529587), + (63180100000000000000, 416661872), + (33925221186984694000, 223859558), + (25894066761385234000, 170640040), + (54106054687500000000, 355558341), + (64281800000000000000, 420684644), + (25160156250000000000, 163810362), + (29250560250604900000, 190803088), + (12850027054315944000, 83760831), + (11049241316468685000, 72082703), + (46410719012869190000, 303380103), + (37693114479560720000, 246075644), + (79543359375000000000, 517175734), + (7066285978106251000, 45901286), + (50305077927223650000, 327425470), + (67263281070282630000, 439600436), + (41644808826480020000, 271978626), + (61612300000000000000, 403310299), + (37693114479560720000, 246548426), + (1013839735093127400, 6607783), + (62653500000000000000, 408381947), + (42966000000000000000, 279028946), + (16354194305302286000, 106278763), + (42361407419452660000, 274600195), + (2646679687499999700, 17129811), + (20671576794422910000, 133682170), + (24575390625000000000, 158678749), + (37415176094731895000, 242077723), + (72682344310191210000, 472060185), + (24555430424073413000, 159495428), + (20961262242062512000, 136351194), + (43172207360559800000, 281459340), + (61123242149798620000, 399942382), + (29848871882700206000, 195929060), + (34484228960300590000, 225957507), + (24726749315563520000, 162225940), + (41241210666468024000, 271198071), + (60687100000000000000, 400499527), + (26663031503026676000, 175888953), + (2396529022082009600, 15793170), + (40656445312500000000, 267523410), + (29573430240775995000, 194118541), + (42915585020664360000, 282278826), + (30002260220735717000, 197114715), + (22900000000000000000, 150174880), + (62173200000000000000, 406514158), + (19986927962969260000, 130308799), + (62746500000000000000, 407912485), + (13037050098512480000, 84742338), + (36336888346628334000, 236600207), + (62671700000000000000, 409484488), + (47673632796955570000, 312692258), + (30270992167335928000, 198351366), + (33346874999999996000, 218021464), + (25761351364304794000, 168652534), + (26119628853416473000, 171308224), + (8291537247638005000, 54327778), + (48843164062500000000, 319392722), + (12000000000000000000, 78303372), + (36855468499053224000, 241086528), + (35101171846758072000, 230188631), + (16973437500000000000, 110998802), + (26190915773029510000, 171535348), + (38317382737867750000, 251167395), + (16780334944767609000, 109900607), + (28440715978123215000, 185975022), + (23022510745733345000, 150757790), + (49427929565069840000, 324488203), + (47381249953852960000, 312107422), + (48550781250000000000, 319287603), + (4343787067617422000, 28567841), + (2709369267662273500, 17823144), + (23333907635194065000, 153142422), + (26821408589215320000, 175722992), + (43724876310155510000, 285763328), + (40404000000000000000, 263286552), + (46467931279198480000, 303350449), + (404531659674152640, 2645172), + (61333600000000000000, 401916521), + (2939062303310467000, 19385508), + (61030000000000000000, 401641807), + (7909570059810601000, 52412558), + (60671400000000000000, 401070893), + (60526800000000000000, 402045222), + (3499859603520661000, 23203142), + (43287890509908240000, 288589431), + (60590900000000000000, 405426723), + (39138263541405900000, 261662246), + (60912200000000000000, 405797532), + (33647992462620144000, 224306719), + (61217400000000000000, 407045639), + (78958593750000010000, 522432515), + (40182187530267990000, 265930533), + (2354296729989555000, 15640952), + (33402066818347647000, 221630577), + (21708446171485240000, 144343764), + (59516000000000000000, 396866456), + (23675058174441878000, 158334157), + (14049609266398753000, 94086158), + (55275585651825230000, 371071843), + (37220905425307640000, 249628571), + (51182226542709730000, 343982281), + (57322265525023050000, 386729813), + (36855468577664380000, 249480099), + (62877538973863440000, 427137459), + (37147851562500000000, 252178823), + (58727900000000000000, 397321234), + (57614648398264630000, 390398552), + (37732617187500000000, 255449107), + (100000000000000000, 676089), + (59127100000000000000, 398914882), + (31526282400597170000, 212831851), + (59392200000000000000, 399918144), + (31114358549775073000, 209634499), + (59275400000000000000, 398336513), + (30433903311645745000, 204637521), + (19915029331603243000, 134147330), + (34224023437500002000, 230047737), + (30286917351969310000, 203119696), + (24171054239253004000, 162328151), + (19312499903159116000, 129898551), + (35101171594658240000, 236550315), + (40656445066342440000, 274724080), + (58363800000000000000, 395764297), + (14724611778458841000, 99842430), + (20186693049816904000, 136709396), + (16388671875000000000, 110844319), + (39194531249999995000, 264569564), + (26119757672792596000, 176513273), + (38609765571905510000, 261518517), + (37732617142050505000, 256271064), + (63169921698617850000, 430577932), + (15939724886362425000, 108657016), + (3723788297742505000, 25366343), + (2917116797823841300, 19866623), + (29477494527336470000, 200521349), + (41825976543672690000, 285103290), + (57963900000000000000, 394249068), + (58250100000000000000, 394563423), + (6187889715315924000, 41818590), + (52644140579464570000, 356932231), + (53521288981503270000, 364251086), + (51182226307139540000, 349633044), + (2815248735461300700, 19233744), + (22583944415454540000, 154153721), + (22528710937500000000, 153529871), + (23305342543722360000, 159081326), + (57586169979961120000, 394216219), + (3981543709305692000, 27264877), + (57982700000000000000, 396179139), + (23480215945516122000, 159968545), + (22528710937500000000, 153235005), + (500000058648616400, 3405487), + (28344742837694820000, 193253482), + (36290467037846938000, 246962102), + (19000000000000000000, 129043950), + (18656169409384720000, 126540221), + (24024552153926600000, 163244818), + (23353368686309753000, 158951668), + (16702326366540927000, 113844331), + (38317382611036720000, 261686378), + (37440234311398425000, 256810847), + (23120688274348940000, 158247570), + (40795920901849874000, 280096138), + (37440234123743580000, 257498769), + (35101171875000000000, 240345146), + (9724565113640774000, 66632443), + (15820582622131420000, 108501055), + (19897265352845054000, 136634010), + (872765863459610000, 5987745), + (32469726391017160000, 223372531), + (2247816002065252400, 15455613), + (33607713910695610000, 230785424), + (31300195280596600000, 215266163), + (100000000000000000, 687413), + (7225452117930805000, 49760989), + (21106703055126176000, 145507248), + (35101171808398455000, 242471109), + (10974663816926800000, 75754809), + (19600000000000000000, 135144918), + (9009999999999986000, 62061703), + (28961132812500000000, 199216313), + (14497956454467780000, 99572966), + (23919194463731630000, 164053492), + (7937999670510335000, 54500000), + (58963852352070950000, 405797947), + (57630900000000000000, 396010194), + (40364062252018230000, 277634047), + (26743509451378470000, 183744025), + (58380700000000000000, 399893893), + (27937096290198290000, 190903326), + (58895400000000000000, 401209286), + (37628708455466270000, 256478619), + (44165039062500000000, 300511905), + (58604400000000000000, 397308273), + (10972371685967660000, 74380349), + (46211718486096030000, 313900465), + (46502738959473490000, 316921293), + (30538925164648735000, 208698025), + (26059345396185375000, 178445116), + (57215400000000000000, 392957526), + (25080858930000003000, 172178613), + (17833516813623738000, 122238537), + (38317382772963610000, 263257072), + (3547679545054426600, 24365390), + (42703124886421650000, 294165776), + (59274100000000000000, 407423809), + (87145312500000000000, 595876212), + (20469978509712314000, 139432258), + (59733600000000000000, 405720182), + (37440234161675620000, 254505528), + (41825976562500000000, 283819969), + (15120000000000000000, 102393011), + (15219140625000000000, 102789478), + (28315317605819950000, 191536029), + (37147851562500000000, 250430288), + (11646122778786415000, 78566475), + (42995507540410540000, 290616319), + (24088629182950360000, 163208411), + (17850585682799931000, 121302555), + (20741128995716944000, 140751891), + (23510598463818555000, 160000000), + (36855468636649680000, 251357279), + (25971840144839172000, 177527051), + (18612858000619905000, 127055699), + (22478612100597354000, 153711230), + (70187109156676120000, 481537538), + (66386132812499990000, 454794891), + (41241210738840690000, 282731713), + (54106054642315125000, 372193624), + (29477494527336470000, 202629065), + (25773067716881670000, 177425022), + (26738971375308538000, 184420780), + (21066796849100640000, 146053683), + (48293858863625250000, 333983512), + (30002580349999997000, 207605512), + (57006700000000000000, 395478282), + (2680740999527415300, 18500487), + (22033230042227167000, 152800890), + (25012627679806630000, 173759554), + (47673632696103000000, 332049712), + (21767304630000000000, 151509494), + (76911913817612760000, 537155771), + (40125942638588160000, 280276605), + (47088867119390950000, 329389893), + (55501400000000000000, 387653770), + (55989900000000000000, 389499047), + (55989900000000000000, 389966868), + (61708007675363934000, 431619687), + (51774807710114460000, 361837329), + (55419600000000000000, 387825815), + (55564100000000000000, 390398553), + (35703369470929040000, 250734540), + (22467302831992205000, 157895344), + (25767697831631820000, 180851188), + (59046016343736975000, 415413426), + (47088867132654890000, 333897674), + (55106400000000000000, 389302360), + (54590500000000000000, 388523571), + (20000000000000000000, 142349473), + (406854819400338560, 2875747), + (648246525713124600, 4601009), + (34762230487442860000, 247849635), + (6499945131940920000, 46335748), + (5725666596023682000, 40798034), + (54762200000000000000, 389348920), + (26833414466708370000, 190815625), + (30708237349398344000, 218827633), + (3523827849931453400, 25142204), + (1964757464097104100, 14002352), + (54751700000000000000, 389398306), + (43993628573322674000, 313139200), + (54755100000000000000, 389118637), + (76957262417786080000, 547998679), + (30673702089009290000, 218527782), + (6286978017859600000, 44729915), + (40472419494502015000, 288653760), + (17890530816125313000, 127549121), + (54904500000000000000, 390402275), + (20522469000841560000, 145919039), + (80605334235989690000, 575234938), + (73448402497245680000, 523669194), + (58803238789206860000, 419532211), + (55073600000000000000, 392505930), + (54742300000000000000, 390608657), + (6010000000000000000, 42908210), + (61021375325017100000, 437060037), + (54720500000000000000, 391551329), + (63491016000430660000, 455000000), + (49720312500000000000, 356066259), + (853143090040212600, 6091235), + (48024350400000000000, 342697159), + (33216090529001312000, 237183415), + (45766029600000000000, 326257171), + (30044686424185184000, 214317177), + (39486914052553110000, 282386024), + (38902148301438850000, 279001231), + (28376367187500003000, 203345930), + (28668750000000000000, 205013956), + (1547646254300090600, 11069754), + (31884960932303466000, 228339959), + (5334809848598406000, 38195718), + (2027973457493195000, 14515811), + (17175489083796680000, 123154319), + (36446599809885510, 252930), + (1574637737052027000, 11283593), + (15062949132641251000, 108265899), + (49720312256616260000, 357343768), + (2808556067234558000, 20201864), + (23743531481302204000, 170952524), + (28316467253100265000, 203599093), + (70187109347960870000, 506036093), + (31459135620000002000, 226864203), + (8016565406784068000, 57727083), + (39500000000000000000, 283944738), + (3995522053964769000, 28718883), + (25364955024040650000, 182513271), + (33346874999999996000, 239589642), + (36802682999566750000, 264769898), + (4693359140172505000, 33816790), + (74280468750000000000, 533209805), + (26224926418342310000, 188146386), + (25404780547252978000, 182606625), + (28000000000000000000, 201000498), + (21600000000000000000, 154776850), + (26914452922448835000, 193447335), + (22658328867390910000, 162561701), + (41533593500046850000, 299270816), + (31000000000000000000, 223189246), + (40947255737442165000, 294031483), + (54736500000000000000, 391677804), + (8099434102138480000, 57928018), + (29117494042672783000, 208534408), + (32655336255031493000, 234400003), + (21219014258390850000, 152610342), + (24420080043553260000, 175926435), + (42410742187499995000, 304967469), + (28026979358955390000, 201018339), + (22396096342263235000, 160336419), + (25174816742352250000, 180464404), + (78958593680012800000, 568169788), + (1006000000000000000, 7250940), + (23333907635194065000, 168033342), + (26459357670936190000, 190193765), + (546664738187368800, 3930828), + (5739979750967373000, 41211269), + (6456307892599592000, 46333630), + (364786629713093700, 2617235), + (23534061871017680000, 169195919), + (42703124779634310000, 307755114), + (32748469670322140000, 235816494), + (22135158010834030000, 159072024), + (16785753263297337000, 120457602), + (29838281164773204000, 214484426), + (34224023437500002000, 245676007), + (24368901529441124000, 175078349), + (27264904104157225000, 195629211), + (47088867183945770000, 338519862), + (23333907635194065000, 167690982), + (54253200000000000000, 388791768), + (30595761105171650000, 219330415), + (14040000000000000000, 100588009), + (1635096347703123700, 11733035), + (11452228567842690000, 82138994), + (39486914046963960000, 283774210), + (20575859063577313000, 148194404), + (64339452865869520000, 464838726), + (20278973818354250000, 146572120), + (25738460799561340000, 185718686), + (5540986780598894000, 40000000), + (6352751131889166000, 45880064), + (63169921785927926000, 457383073), + (18254872130678663000, 132234071), + (24343958370448077000, 176066630), + (41511148266971850000, 299503934), + (10000000000000000, 72040), + (27375372024599430000, 197016258), + (37336141295456190000, 267774743), + (68725195312500010000, 492870928), + (32748469670322140000, 234629842), + (25200000000000000000, 180166687), + (45334570312499995000, 323286416), + (29905222111604974000, 213393928), + (26999134164490390000, 192446506), + (30248958023910232000, 215162158), + (20777543607549133000, 147918084), + (48550781129048736000, 346513142), + (32155262027271533000, 230172461), + (20161171327958180000, 144206948), + (25426858695512500000, 182124310), + (27207171763558355000, 195251023), + (31236786846479507000, 224648784), + (34946214303815850000, 251935697), + (74179600000000000000, 533372859), + (29509529207016215000, 212089902), + (29904974092595073000, 215399675), + (67555664026764590000, 488330993), + (26101650982893680000, 188738140), + (73168700000000000000, 530626799), + (29188070735980098000, 211762856), + (74092600000000000000, 535517977), + (32711250000000000000, 235503070), + (34973881795424903000, 252116095), + (27142701082193965000, 195485032), + (19199335842989806000, 138041696), + (43626772533034830000, 312953875), + (28242371465033417000, 202724147), + (22002733728586035000, 157782586), + (61123242187499995000, 436990578), + (24044255248170586000, 171874208), + (17558202993119953000, 125700921), + (27207154766361680000, 195097283), + (18142968512330078000, 130315469), + (29833581614252910000, 213937419), + (28476644425907986000, 203772624), + (31787609957997072000, 227765906), + (18142968632277110000, 130236016), + (30464688871434527000, 219074175), + (45215831402414630000, 326052745), + (62585156069444230000, 453090609), + (35378361962402636000, 256073250), + (29509434200933310000, 213803639), + (48843163800687150000, 354901734), + (41109259809999995000, 299921026), + (67555663874614220000, 492976954), + (29455909734100310000, 215070471), + (45919335705915430000, 335475802), + (37220905425307640000, 271099663), + (3630645846091194400, 26375752), + (46737985600000000000, 339368273), + (24787727460000000000, 179513401), + (32762109186469970000, 237618659), + (45919335781392300000, 334010614), + (74692200000000000000, 542076943), + (37440234197977370000, 271675577), + (36270702988671218000, 263903277), + (39194531065564990000, 285970174), + (4893728795858807000, 35707775), + (42998200000089830000, 313189920), + (28961132811931600000, 211091040), + (39779296619909200000, 290677383), + (4336011664512147500, 31687715), + (35101171734673960000, 257120348), + (38317382676896680000, 281441634), + (20679459243829514000, 151807720), + (33175954367025340000, 243060557), + (56152734197847230000, 412241883), + (73941400000000000000, 541830976), + (21228426302294670000, 155442429), + (20247468125305184000, 148087122), + (16813668410267836000, 122804874), + (17850585937500000000, 129959676), + (26342351971721548000, 192095546), + (74655100000000000000, 541676067), + (19895551129676145000, 144239191), + (3445405887008798000, 25000000), + (22154029564653360000, 160447525), + (17095195301299085000, 123631448), + (29086628244887593000, 209997042), + (23916094424436036000, 172332400), + (24575390625000000000, 176769173), + (554181268117712830, 4008380), + (37147851562500000000, 266599979), + (35101171740841935000, 252197893), + (15219140377268455000, 109722221), + (21562655261425705000, 155246570), + (28961132790151266000, 209133143), + (31884960937500000000, 229946068), + (14731190013949667000, 106056343), + (22695863239832023000, 163641516), + (24033999766210250000, 173073554), + (23390007932245330000, 168144109), + (25962127226671428000, 186298043), + (19800000000000000000, 141842850), + (39779296875000000000, 284351640), + (39779296875000000000, 283528629), + (7251326161197078000, 51684943), + (6170106646207576000, 44000000), + (7848858731976701000, 56000000), + (27275276751386640000, 194852477), + (13164700000000000000, 93983110), + (44457421875000000000, 316718284), + (683234469364873100, 4877703), + (15108861978593335000, 107403916), + (23508202458084610000, 167363861), + (23543262275561210000, 167900493), + (30270992167335928000, 215568341), + (14967015122320402000, 106653000), + (30130663937657946000, 215059746), + (28068377490000000000, 200114955), + (23023336451284824000, 164313049), + (42546774819138224000, 304373961), + (23419255624960130000, 167941614), + (37220905425307640000, 266460592), + (33607713910695610000, 239973987), + (23432085014386160000, 166968585), + (75876000000000000000, 542349384), + (33607713910695610000, 240304190), + (33175954367025340000, 236640990), + (33015540912859955000, 234930702), + (31942902986908670000, 227562194), + (33136255336950436000, 236623226), + (22010961588657820000, 157494420), + (19312499933930148000, 138394497), + (75161600000000000000, 540473336), + (33694480859999998000, 242367272), + (28546605142278360000, 205546100), + (6564831655957375000, 47329936), + (33175954367025340000, 238667061), + (36802571966630870000, 265110021), + (19944547819390520000, 143590557), + (19000000000000000000, 136595788), + (39779296822946726000, 286544493), + (1968982765511115800, 14204958), + (35685937392461120000, 257806410), + (50012695104017950000, 362443841), + (68140429625041210000, 495963012), + (29019360803927433000, 211268987), + (70850709808630470000, 517228231), + (26089608253785465000, 190546117), + (43181497176322700000, 315954913), + (1640249188176797000, 11873593), + (24283007559474450000, 178118923), + (36000000000000000000, 263634231), + (647152969172882300, 4728156), + (25452538954877653000, 186544623), + (21651562396333200000, 158962832), + (22723994761412840000, 166629913), + (26622070246139980000, 195476214), + (39486913882835500000, 290646941), + (40948827867793620000, 302305471), + (721975353442609500, 5304170), + (1999320521115813600, 14763588), + (13297899714807700000, 98140156), + (10239600000000000000, 75503740), + (13567044811581110000, 99951290), + (34224023437500002000, 251690835), + (30130664014991320000, 221819961), + (33931640494952583000, 250394443), + (10999075745881250000, 81301459), + (22065409147977850000, 163299968), + (129540820045807710000, 964108742), + (94224940141949650000, 701350159), + (31884960909957886000, 237065942), + (70480300000000000000, 526022412), + (32622297910000000000, 243524149), + (1380817225378688800, 10231655), + (45919335921487870000, 343367802), + (16901069870000000000, 126364943), + (33840000000000004000, 252535578), + (39194531167575110000, 292904217), + (24003919178661460000, 179269781), + (23952000000000000000, 178563117), + (37732616992033340000, 281780561), + (20000000000000000000, 149275944), + (15400000000000000000, 114791189), + (37440234257049985000, 279643056), + (37147851525520510000, 278231271), + (19280000168262595000, 144327006), + (5294579305784715000, 39598089), + (3876531475300548600, 28982625), + (3600000000000000000, 26908711), + (33931640625000000000, 253272933), + (40364062500000010000, 300454660), + (31007812500000000000, 230199242), + (29825189880444064000, 220920481), + (41860000000000000000, 309242224), + (8778363407485760000, 64848849), + (50012695103976006000, 370266936), + (52936523381003166000, 393413080), + (3977949040430810000, 29581561), + (28699631925631275000, 213162817), + (24674927484949290000, 183462533), + (19312499832395174000, 143826801), + (8400488711857861000, 62511642), + (4506438241080677400, 33569760), + (13149373551084694000, 98017805), + (33175954367025340000, 246819412), + (14926757812500000000, 110642475), + (25551658097970938000, 189682728), + (17468846895110242000, 129074753), + (26657935072229433000, 197293845), + (46796484375000000000, 344951408), + (42118359374999994000, 309449048), + (13608754430580680000, 99999999), + (49135546875000005000, 360153537), + (19779245447208428000, 144994805), + (28961132812500000000, 211658734), + (20448485884795460000, 149717388), + (4350693443558254600, 31805829), + (555587894529490750, 4089606), + (1167361471917182200, 8535754), + (2003537195952450300, 14651586), + (29904816246036693000, 218946981), + (10702877915054445000, 78478124), + (16096289062499998000, 117642724), + (25041492819863486000, 183298021), + (812544337596417900, 5947941), + (5958658475707065000, 43514607), + (69682500000000010000, 507461310), + (2815386798099185700, 20477209), + (11755857539876864000, 85549893), + (16858024554017145000, 122808545), + (13823096180838350000, 100813164), + (18418214401838367000, 134485255), + (24980381047771820000, 182137969), + (25291922419876827000, 184633101), + (68002600000000000000, 495052459), + (17180639127940889000, 124989823), + (67564600000000000000, 490039812), + (30961901134880310000, 224531584), + (2713675157783604000, 19703543), + (42118359284598030000, 306318263), + (51182226562500000000, 371668523), + (38581588068459495000, 280373490), + (30693034559231590000, 223615581), + (37732617187500000000, 274502443), + (67718500000000010000, 490745470), + (12121136148051690000, 87766296), + (25403070143158223000, 183627800), + (32183729703903250000, 232152447), + (33607713910695610000, 241841719), + (23263659559574815000, 167058328), + (33624467619323793000, 241841719), + (54832000000000000000, 393598470), + (3667990456383318000, 26312228), + (48708609403805900000, 350078569), + (66972300000000010000, 480447116), + (66978399999999990000, 481068093), + (31511365749960045000, 227144131), + (6000000000000000000, 43238399), + (37500026990509195000, 270876899), + (54690820298411565000, 396389325), + (28316467253100265000, 205185069), + (40125942638588160000, 290029994), + (1477148222138477600, 10693859), + (24709925485383380000, 178716665), + (36563085685533893000, 265068978), + (41241210678711850000, 299838665), + (22230434667341853000, 162000000), + (13764459565256552000, 100216763), + (17875669508850422000, 129998598), + (11580492633624955000, 84126642), + (42703125000000000000, 309600389), + (6836937032413301000, 49562500), + (8871706424375187000, 64350069), + (43580273332437475000, 316714512), + (32762109108280290000, 238763593), + (26821371900248842000, 195277091), + (63754687253319340000, 465365444), + (5672583256626734000, 41370706), + (24314575841909076000, 177524424), + (13172460937500000000, 95872715), + (18259095093889403000, 133048251), + (23698242187500000000, 172248766), + (46211718662248690000, 336568049), + (2094849868373879800, 15263595), + (24687397954152560000, 179701601), + (1080000000000000100, 7853966), + (21943945294454706000, 159894809), + (22821093731400270000, 166779757), + (17906350480184720000, 130666080), + (20567863790472130000, 150145107), + (44457421875000000000, 323763503), + (18727734375000003000, 135859472), + (21030004242272830000, 152783969), + (7126186320869464000, 51736641), + (40071679687500005000, 290223732), + (654600398430076800, 4739856), + (24024923216826740000, 174118074), + (18614857978831766000, 135120420), + (14645483122723934000, 106437655), + (38024999887274810000, 276886243), + (2515491763977417700, 18318961), + (3150438435604856000, 22938156), + (17968258800000000000, 130724362), + (31884960937500000000, 231548187), + (22920000000000000000, 166117391), + (13664666834171030000, 99125000), + (516506061763966400, 3748746), + (19011537602327716000, 138076014), + (37732617187500000000, 273538724), + (215969310874418430, 1567319), + (19890649750625210000, 144274907), + (25452539062500000000, 184363019), + (55078345795719150, 399106), + (15984000000000000000, 115623784), + (652631803274694100, 4717652), + (2335320852478199300, 16712402), + (250000000000000000, 1810117), + (632669356124904800, 4495816), + (600000000000000000, 4242560), + (1651632144534695700, 11846518), + (559611931919544060, 4050062), + (28863975413548668, 206611), + (16097886192174070, 121816), + (202648734474869400, 1493882), + (594000000000000, 4372), + (100000000000000000, 727210), + (83862422561687580, 596577), + (78862436335849490, 550298), + (50000000000000000, 349628), + (20000000000000000, 140697), + (173194126012671520, 1212440), + (146743612879306140, 1020430), + (71110399874819290, 493843), + (64486571483668090, 440009), + (97181739595442290, 649955), + (66889141151028230, 457082), + (59225351445740100, 423022), + (75700000000000000, 529755), + (40000000000000000, 274616), + (43615000000000000, 295365), + (266279558784512320, 1876928), + (93973108489938830, 625692), + (20000000000000000, 135821), + (6524136836738217, 43637), + (27764398197116750, 188787), + (68617964672204530, 459040), + (200000000000000000, 1356446), + (82070352690414380, 541959), + (11000000000000000, 72714), + (61070756068106580, 405805), + (20282049458423940, 134415), + (26677595258616612, 177451), + (373012714487591300, 2641242), + (94998913274022300, 623006), + (46956832549435560, 320643), + (9317000000000000, 65693), + (9970000000000000, 69105), + (131082856123304370, 915331), + (50152517827015350, 351597), + (14238310793650076, 99146), + (21919764830406684, 152959), + (33226051976274056, 234300), + (60000000000000000, 433771), + (72906062373372960, 518818), + (83928067559834960, 614985), + (14732098553909066, 105266), + (14565041648391778, 106861), + (32056722820579544, 240047), + (19940000000000000, 148171), + (61099890606508990, 467962), + (49850000000000000, 373604), + (23155379749558220, 174377), + (67556584242080740, 499327), + (29700000000000000, 225466), + (333257404869070, 2515), + (26535157631287384, 199209), + (34895000000000004, 258858), + (11579111145934350, 86369), + (78106448212145310, 586102), + (39880000000000000, 292365), + (231802500000000000, 1718846), + (96220686304011950, 700835), + (51861341971144220, 389257), + (10000000000000000, 74950), + (28585287367900690, 212570), + (30000000000000000, 220452), + (18696272620197536, 138454), + (437616341296499, 3353), + (11000000000000000, 83721), + (48458861363602984, 344714), + (19940000000000000, 138826), + (529668862583052500, 4138378), + (114419453433725920, 764855), + (24070784019234584, 163013), + (50899654956674370, 340407), + (34402238362907150, 229507), + (48503678650387080, 329459), + (57692307692307700, 387237), + (12010627638740398, 80962), + (139580000000000020, 898272), + (54985871349477860, 350123), + (30446438808812068, 189984), + (10000000000000000, 63422), + (20000000000000000, 124734), + (49850000000000000, 306077), + (19940000000000000, 123333), + (51377486844404320, 308953), + (219340000000000000, 1328202), + (10278429834101520, 60132), + (56379164675629384, 334469), + (10967000000000000, 66114), + (47395443275550344, 278919), + (84468900617457800, 483702), + (69790000000000010, 394387), + (28913000000000000, 156607), + (164381682327615420, 859055), + (50000000000000000, 263493), + (42372241265866936, 232019), + (59906818665837360, 317088), + (148069669102250050, 814456), + (50374751804262470, 280435), + (35964257635622470, 204747), + (89212500000000000, 503931), + (60000000000000000, 331288), + (142770810236228180, 772209), + (86713580953747940, 449589), + (122966145375891200, 648292), + (169490000000000000, 877508), + (176911881732458080, 926435), + (47480209628809190, 259102), + (50993561799663096, 279752), + (23824750759686600, 133391), + (104688974729497390, 587879), + (43428766827433490, 244269), + (32215401055385680, 181736), + (12130582776704084, 68509), + (20950581382376230, 119150), + (5713634283171313, 32126), + (118297596098466750, 684984), + (58230698944339540, 337709), + (53893954986437820, 315444), + (4319288637827566, 24481), + (7178549769519046, 41975), + (49579465613443710, 286769), + (49850000000000, 285), + (12851329209728612, 73445), + (40047792386730930, 224811), + (68225455287229780, 375427), + (40872509705408840, 224922), + (14646449539434462, 79008), + (25780643468578876, 142200), + (52012210680940344, 291175), + (49951555689811336, 283644), + (104221669021363900, 618667), + (40864978791288740, 242208), + (43188150515033280, 264540), + (100129809346290780, 629488), + (85825732316106000, 559695), + (35275904578729664, 230841), + (9446000306031732, 63388), + (384397852123056, 2589), + (907390000000000, 6106), + (20000000000000000, 132190), + (108120708475001150, 724074), + (10998521234558514, 72188), + (6381749521312865, 42519), + (3010330997613533, 20221), + (21677061047177556, 148791), + (42057957699818984, 290614), + (31445391682251224, 220683), + (12909240396050000, 90049), + (1230601684706867, 8592), + (43303959502679, 302), + (65814644870748744, 451577), + (24938644746680720, 170179), + (76851823459737400, 511884), + (66704297581634720, 447823), + (37430913583230940, 258491), + (81539884556576780, 578966), + (33113825934479604, 235118), + (9448320328222728, 67679), + (15120601666667246, 106394), + (60839260615360030, 432506), + (28117203593783810, 200337), + (16753377244459328, 120484), + (4985000000000000, 35632), + (50000000000000000, 353396), + (16758551890555768, 118827), + (77263686993896770, 568298), + (32335772546270124, 236069), + (10800512367386018, 80332), + (25896533816540316, 195481), + (25091908022883200, 189397), + (14736629955458578, 108715), + (16980529793606768, 125621), + (104721280770255150, 782280), + (53342805703904380, 412098), + (34230270562041710, 269489), + (22131972167658316, 178665), + (11935605028019088, 95642), + (2492500000000000, 21290), + (9970000000000000, 81160), + (1000000000000000, 8332), + (100000000000000, 826), + (997000000000000, 8180), + (9970000000000000, 80800), + (25700000000000000, 206636), + (24925000000000000, 198168), + (26192254183504750, 206668), + (1524480138136947, 12290), + (24000000000000000, 189695), + (60559458942335890, 460657), + (4985000000000000, 38445), + (9371800000000000, 70187), + (27882803373282060, 207118), + (61665090943018904, 466155), + (5982000000000000, 45327), + (6181400000000000, 46711), + (3791956574376494, 28929), + (47950947655644220, 370069), + (18222557019270010, 142742), + (61470088171883490, 472163), + (4472990970304615, 33854), + (35913568196284976, 269408), + (19940000000000000, 147750), + (19940000000000000, 146466), + (103141277299929950, 779477), + (15983007104875646, 124033), + (26064959969415116, 204194), + (4121298995654257, 31621), + (63270053437400270, 505815), + (73425836704090990, 605736), + (8300000000000000, 68821), + (650000000000000, 5378), + (7700000000000000, 63590), + (70000000000000010, 567890), + (113677171732830980, 941059), + (10000000000000000, 83956), + (129610000000000000, 1053836), + (54425638413660890, 439263), + (28213000000000000, 229984), + (10059592423412448, 80021), + (38147214000000000, 300114), + (34895000000000004, 269985), + (36296844802398380, 283752), + (27487350000000000, 219762), + (20956940000000000, 168329), + (132994973628250580, 1030570), + (75030816806468240, 572015), + (31995678315914480, 237888), + (18558672346501348, 136378), + (3613307491574892, 27796), + (30421701023623160, 221052), + (6000000000000000, 43302), + (66497233475863990, 472658), + (106784040000000000, 769501), + (749395507452270, 5230), + (105769297290485000, 729367), + (48593776133389176, 331656), + (37354586315049480, 261246), + (72781000000000000, 499888), + (12145546617844230, 83084), + (22398881857140172, 154452), + (9970000000000000, 68474), + (736085100000000, 5132), + (15325884000000000, 104432), + (993053893018270, 6847), + (11964000000000000, 81018), + (997000000000000, 6787), + (26660465129041580, 180834), + (10264081662316798, 69407), + (49850000000000000, 339331), + (16103544000000000, 109706), + (64805000000000000, 431763), + (4985000000000000, 33582), + (56850029984611490, 380784), + (69093142405910970, 497984), + (6832666038111659, 48363), + (62390679035020390, 480228), + (24925000000000000, 192070), + (3872513164883904, 29411), + (24909306237890504, 189661), + (29970703125000000, 231673), + (127413941116536370, 997938), + (102686077821543440, 802252), + (94715000000000000, 698608), + (24864291557399052, 176604), + (13363435898526386, 95961), + (46586312002211624, 340369), + (23636616699481788, 176258), + (19990191832874204, 151383), + (2613422948070288, 20000), + (27553504525486860, 200375), + (133117508334815, 1000), + (20995233477529908, 153979), + (40000000000000000, 289148), + (22008892091629852, 156777), + (35975531748167708, 252807), + (5483500000000000, 39700), + (42409341942364664, 301480), + (41682401584126650, 302261), + (40944271598795260, 302823), + (12147208666839200, 89577), + (8973000000000000, 65835), + (1366334647727839, 10000), + (875722464067428, 6156), + (866715649908032, 6162), + (41223233448539980, 302371), + (49530477505811630, 371409), + ] +} diff --git a/math/src/lib.rs b/math/src/lib.rs new file mode 100644 index 00000000000..d9f18726358 --- /dev/null +++ b/math/src/lib.rs @@ -0,0 +1,14 @@ +//! # Basilisk Math +//! +//! A collection of utilities to make performing liquidity pool +//! calculations more convenient. +#![allow(clippy::bool_to_int_with_if)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(not(feature = "std"), test))] +extern crate std; + +pub mod ema; +pub mod ratio; +#[cfg(test)] +pub mod test_utils; diff --git a/math/src/ratio.rs b/math/src/ratio.rs new file mode 100644 index 00000000000..d5b7f4848a1 --- /dev/null +++ b/math/src/ratio.rs @@ -0,0 +1,136 @@ +use codec::{Decode, Encode, MaxEncodedLen}; +use core::cmp::{Ord, Ordering, PartialOrd}; +use num_traits::Zero; +use scale_info::TypeInfo; +use serde::{Deserialize, Serialize}; +use sp_arithmetic::helpers_128bit; + +/// A rational number represented by a `n`umerator and `d`enominator. +#[derive(Clone, Copy, Default, PartialEq, Eq, Encode, Decode, Serialize, Deserialize, TypeInfo, MaxEncodedLen)] +pub struct Ratio { + pub n: u128, + pub d: u128, +} + +impl Ratio { + /// Build from a raw `n/d`. Ensures that `d > 0`. + pub const fn new(n: u128, d: u128) -> Self { + // reimplement `.max(1)` so this can be `const` + let d = if d > 0 { d } else { 1 }; + Self { n, d } + } + + /// Build from a raw `n/d`. This could lead to / 0 if not properly handled. + pub const fn new_unchecked(n: u128, d: u128) -> Self { + Self { n, d } + } + + /// Return a representation of one. + /// + /// Note that more than one combination of `n` and `d` can be one. + pub const fn one() -> Self { + Self::new_unchecked(1, 1) + } + + /// Return whether `self` is one. + /// + /// Should a denominator of 0 happen, this function will return `false`. + /// + /// Note that more than one combination of `n` and `d` can be one. + pub const fn is_one(&self) -> bool { + self.d > 0 && self.n == self.d + } + + /// Return a representation of zero. + /// + /// Note that any combination of `n == 0` and `d` represents zero. + pub const fn zero() -> Self { + Self::new_unchecked(0, 1) + } + + /// Return whether `self` is zero. + /// + /// Note that any combination of `n == 0` and `d` represents zero. + pub const fn is_zero(&self) -> bool { + self.n == 0 + } + + /// Invert `n/d` to `d/n`. + /// + /// NOTE: Zero inverts to zero. + pub const fn inverted(self) -> Self { + if self.is_zero() { + self + } else { + Self { n: self.d, d: self.n } + } + } +} + +impl From for (u128, u128) { + fn from(ratio: Ratio) -> (u128, u128) { + (ratio.n, ratio.d) + } +} + +#[cfg(test)] +impl From for rug::Rational { + fn from(ratio: Ratio) -> rug::Rational { + rug::Rational::from((ratio.n, ratio.d)) + } +} + +impl From for Ratio { + fn from(n: u128) -> Self { + Self::new(n, 1) + } +} + +impl From<(u128, u128)> for Ratio { + fn from((n, d): (u128, u128)) -> Self { + Self::new(n, d) + } +} + +impl PartialOrd for Ratio { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +// Taken from Substrate's `Rational128`. +impl Ord for Ratio { + fn cmp(&self, other: &Self) -> Ordering { + if self.d == other.d { + self.n.cmp(&other.n) + } else if self.d.is_zero() { + Ordering::Greater + } else if other.d.is_zero() { + Ordering::Less + } else { + let self_n = helpers_128bit::to_big_uint(self.n) * helpers_128bit::to_big_uint(other.d); + let other_n = helpers_128bit::to_big_uint(other.n) * helpers_128bit::to_big_uint(self.d); + self_n.cmp(&other_n) + } + } +} + +#[cfg(feature = "std")] +impl sp_std::fmt::Debug for Ratio { + fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + write!( + f, + "Ratio({} / {} ≈ {:.8})", + self.n, + self.d, + self.n as f64 / self.d as f64 + ) + } +} + +#[cfg(not(feature = "std"))] +impl sp_std::fmt::Debug for Ratio { + fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + write!(f, "Ratio({} / {})", self.n, self.d) + } +} diff --git a/math/src/test_utils.rs b/math/src/test_utils.rs new file mode 100644 index 00000000000..c023bbf9d7e --- /dev/null +++ b/math/src/test_utils.rs @@ -0,0 +1,221 @@ +use hydra_dx_math::fraction; +use hydra_dx_math::types::{Balance, Fraction}; + +use proptest::prelude::Rng; +use proptest::prelude::*; +use rug::{Integer, Rational}; +use sp_arithmetic::{FixedPointNumber, FixedU128}; + +// ----- Macros + +/// Asserts that two expressions `$x` and `$y` are approximately equal to each other up to a delta `$z`. +#[macro_export] +macro_rules! assert_approx_eq { + ($x:expr, $y:expr, $z:expr) => {{ + assert_approx_eq!($x, $y, $z, "values are not approximately equal"); + }}; + ($x:expr, $y:expr, $z:expr, $r:expr) => {{ + let diff = if $x >= $y { + $x.clone() - $y.clone() + } else { + $y.clone() - $x.clone() + }; + assert!( + diff <= $z, + "\n{}\n left: {:?}\n right: {:?}\n diff: {:?}\nmax_diff: {:?}\n", + $r, + $x, + $y, + diff, + $z + ); + }}; +} +pub(crate) use assert_approx_eq; + +/// Asserts that two expressions `$x` and `$y` are approximately equal to each other up to a delta `$z`. +macro_rules! prop_assert_approx_eq { + ($x:expr, $y:expr, $z:expr) => {{ + prop_assert_approx_eq!($x, $y, $z, "values are not approximately equal"); + }}; + ($x:expr, $y:expr, $z:expr, $r:expr) => {{ + let diff = if $x >= $y { + $x.clone() - $y.clone() + } else { + $y.clone() - $x.clone() + }; + prop_assert!( + diff <= $z, + "\n{}\n left: {:?}\n right: {:?}\n diff: {:?}\nmax_diff: {:?}\n", + $r, + $x, + $y, + diff, + $z + ); + }}; +} +pub(crate) use prop_assert_approx_eq; + +/// Asserts that two `Rational` numbers `$x` and `$y` are approximately equal to each other up to a delta `$z`. +/// Converts the `Rational` numbers to `f64` for display. +macro_rules! assert_rational_approx_eq { + ($x:expr, $y:expr, $z:expr) => {{ + assert_rational_approx_eq!($x, $y, $z, "values are not approximately equal"); + }}; + ($x:expr, $y:expr, $z:expr, $r:expr) => {{ + let diff = if $x >= $y { + $x.clone() - $y.clone() + } else { + $y.clone() - $x.clone() + }; + assert!( + diff <= $z, + "\n{}\n left: {:?}\n right: {:?}\n diff: {:?}\nmax_diff: {:?}\n", + $r, + $x.to_f64(), + $y.to_f64(), + diff.to_f64(), + $z.to_f64() + ); + }}; +} +pub(crate) use assert_rational_approx_eq; + +/// Asserts that two `Rational` numbers `$x` and `$y` are approximately equal to each other up to a delta `$z`. +/// Converts the `Rational` numbers to `f64` for display. +macro_rules! prop_assert_rational_approx_eq { + ($x:expr, $y:expr, $z:expr) => {{ + prop_assert_rational_approx_eq!($x, $y, $z, "values are not approximately equal"); + }}; + ($x:expr, $y:expr, $z:expr, $r:expr) => {{ + let diff = if $x >= $y { + $x.clone() - $y.clone() + } else { + $y.clone() - $x.clone() + }; + prop_assert!( + diff <= $z, + "\n{}\n left: {:?}\n right: {:?}\n diff: {:?}\nmax_diff: {:?}\n", + $r, + $x.to_f64(), + $y.to_f64(), + diff.to_f64(), + $z.to_f64() + ); + }}; +} +pub(crate) use prop_assert_rational_approx_eq; + +/// Asserts that two `Rational` numbers `$x` and `$y` are approximately equal to each other up to a +/// relative error `$z`. +/// `$y` is used as the reference value to determine the error. +/// Converts the `Rational` numbers to `f64` for display. +macro_rules! assert_rational_relative_approx_eq { + ($x:expr, $y:expr, $z:expr) => {{ + assert_rational_relative_approx_eq!($x, $y, $z, "values are not approximately equal"); + }}; + ($x:expr, $y:expr, $z:expr, $r:expr) => {{ + let diff = if $x >= $y { + $x.clone() - $y.clone() + } else { + $y.clone() - $x.clone() + }; + assert!( + diff.clone() / $y.clone() <= $z.clone(), + "\n{}\n left: {:?}\n right: {:?}\n diff: {:?}\nmax_diff: {:?}\n", + $r, + $x.to_f64(), + $y.to_f64(), + diff.to_f64(), + ($y * $z).to_f64() + ); + }}; +} +pub(crate) use assert_rational_relative_approx_eq; + +/// Asserts that two `Rational` numbers `$x` and `$y` are approximately equal to each other up to a +/// relative error `$z`. +/// `$y` is used as the reference value to determine the error. +/// Converts the `Rational` numbers to `f64` for display. +macro_rules! prop_assert_rational_relative_approx_eq { + ($x:expr, $y:expr, $z:expr) => {{ + prop_assert_rational_relative_approx_eq!($x, $y, $z, "values are not approximately equal"); + }}; + ($x:expr, $y:expr, $z:expr, $r:expr) => {{ + let diff = if $x >= $y { + $x.clone() - $y.clone() + } else { + $y.clone() - $x.clone() + }; + prop_assert!( + diff.clone() / $y.clone() <= $z.clone(), + "\n{}\n left: {:?}\n right: {:?}\n diff: {:?}\nmax_diff: {:?}\n", + $r, + $x.clone().to_f64(), + $y.to_f64(), + diff.to_f64(), + ($y * $z).to_f64() + ); + }}; +} +pub(crate) use prop_assert_rational_relative_approx_eq; + +// ----- Constants + +/// Smallest balance expected to show up in prices. +/// Existential deposit for BTC will likely be 100 satoshis. +pub const MIN_BALANCE: Balance = 50; +/// Biggest balance expected to show up in prices. +/// Total issuance of BSX is about 1e22, total issuance of FRAX is about 1e27. +pub const MAX_BALANCE: Balance = 1e22 as Balance; + +// ----- High Precision Test Util Functions + +/// Convert a fixed point number to an arbitrary precision rational number. +pub fn fixed_to_high_precision(f: FixedU128) -> Rational { + Rational::from((f.into_inner(), FixedU128::DIV)) +} + +#[test] +fn fixed_to_high_precision_works() { + assert_eq!( + fixed_to_high_precision(FixedU128::from_float(0.25)), + Rational::from((1, 4)) + ); +} + +/// Convert a fixed point fraction to an arbitrary precision rational number. +pub fn fraction_to_high_precision(f: Fraction) -> Rational { + Rational::from((f.to_bits(), fraction::DIV)) +} + +#[test] +fn fraction_to_high_precision_works() { + assert_eq!(fraction_to_high_precision(fraction::frac(1, 4)), Rational::from((1, 4))); +} + +/// Convert a `Rational` number into its rounded `Integer` equivalent. +pub(crate) fn into_rounded_integer(r: Rational) -> Integer { + let (num, den) = r.into_numer_denom(); + num.div_rem_round(den).0 +} + +// ----- Property Test Strategies + +/// Generates an arbitrary `FixedU128` number. +pub fn any_fixed() -> impl Strategy { + any::().prop_map(FixedU128::from_inner) +} + +/// Generates an arbitrary tuple representing a rational number, ensuring that the denominator is greater 0. +pub fn any_rational() -> impl Strategy { + (any::(), 1..u128::MAX) +} + +/// Generates two tuples representing two rational numbers with the first being bigger than the second. +/// `min` determines the minimum value a numerator or denominator can have, `max` the maximum. +pub fn bigger_and_smaller_rational(min: u128, max: u128) -> impl Strategy { + ((min + 1)..max, (min.max(1))..(max - 1)) + .prop_perturb(move |(a, b), mut rng| ((a, b), (rng.gen_range(min..a), rng.gen_range(b..max)))) +} diff --git a/node/Cargo.toml b/node/Cargo.toml index 51173f123ee..61e80e6f4e0 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "basilisk" -version = "18.0.0" +version = "19.0.0" description = "Basilisk node" authors = ["GalacticCouncil"] edition = "2021" diff --git a/node/src/chain_spec/mod.rs b/node/src/chain_spec/mod.rs index 859cc20aced..4144188261a 100644 --- a/node/src/chain_spec/mod.rs +++ b/node/src/chain_spec/mod.rs @@ -127,9 +127,7 @@ pub fn parachain_genesis( "desiredCandidates": 0u32, }, "duster": { - "accountBlacklist": vec![get_account_id_from_seed::("Duster")], - "rewardAccount": Some(get_account_id_from_seed::("Duster")), - "dustAccount": Some(get_account_id_from_seed::("Duster")) + "accountWhitelist": vec![get_account_id_from_seed::("Duster")] }, "emaOracle": { }, diff --git a/node/src/service.rs b/node/src/service.rs index 7ccd4be30af..975824e51b1 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -79,7 +79,7 @@ pub fn new_partial( ParachainBackend, (), sc_consensus::DefaultImportQueue, - sc_transaction_pool::FullPool, + sc_transaction_pool::TransactionPoolHandle, (ParachainBlockImport, Option, Option), >, sc_service::Error, @@ -116,6 +116,7 @@ pub fn new_partial( telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, true, + None, )?; let client = Arc::new(client); @@ -126,12 +127,15 @@ pub fn new_partial( telemetry }); - let transaction_pool = sc_transaction_pool::BasicPool::new_full( - config.transaction_pool.clone(), - config.role.is_authority().into(), - config.prometheus_registry(), - task_manager.spawn_essential_handle(), - client.clone(), + let transaction_pool = Arc::from( + sc_transaction_pool::Builder::new( + task_manager.spawn_essential_handle(), + client.clone(), + config.role.is_authority().into(), + ) + .with_options(config.transaction_pool.clone()) + .with_prometheus(config.prometheus_registry()) + .build(), ); let block_import = ParachainBlockImport::new(client.clone(), backend.clone()); @@ -198,19 +202,18 @@ async fn start_node_impl( let transaction_pool = params.transaction_pool.clone(); let import_queue_service = params.import_queue.service(); - let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) = - build_network(BuildNetworkParams { - parachain_config: ¶chain_config, - net_config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - para_id, - spawn_handle: task_manager.spawn_handle(), - relay_chain_interface: relay_chain_interface.clone(), - import_queue: params.import_queue, - sybil_resistance_level: CollatorSybilResistance::Resistant, // because of Aura - }) - .await?; + let (network, system_rpc_tx, tx_handler_controller, sync_service) = build_network(BuildNetworkParams { + parachain_config: ¶chain_config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + para_id, + spawn_handle: task_manager.spawn_handle(), + relay_chain_interface: relay_chain_interface.clone(), + import_queue: params.import_queue, + net_config, + sybil_resistance_level: CollatorSybilResistance::Resistant, // because of Aura + }) + .await?; if parachain_config.offchain_worker.enabled { use futures::FutureExt; @@ -228,6 +231,7 @@ async fn start_node_impl( enable_http_requests: false, custom_extensions: move |_| vec![], }) + .expect("Failed to create offchain workers") .run(client.clone(), task_manager.spawn_handle()) .boxed(), ); @@ -337,8 +341,6 @@ async fn start_node_impl( )?; } - start_network.start_network(); - Ok((task_manager, client)) } @@ -379,7 +381,7 @@ fn start_consensus( telemetry: Option, task_manager: &TaskManager, relay_chain_interface: Arc, - transaction_pool: Arc>, + transaction_pool: Arc>, keystore: KeystorePtr, relay_chain_slot_duration: Duration, para_id: ParaId, @@ -425,6 +427,7 @@ fn start_consensus( collator_service, authoring_duration: Duration::from_millis(1500), reinitialize: false, + max_pov_percentage: None, // Defaults to 85% of max PoV size (safe default) }; let fut = aura::run::(params); diff --git a/pallets/asset-registry/Cargo.toml b/pallets/asset-registry/Cargo.toml index 7c955f02120..3e44f8974e0 100644 --- a/pallets/asset-registry/Cargo.toml +++ b/pallets/asset-registry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-asset-registry" -version = "2.3.6" +version = "2.4.0" description = "Pallet for asset registry management" authors = ["GalacticCouncil"] edition = "2021" diff --git a/pallets/asset-registry/src/mock.rs b/pallets/asset-registry/src/mock.rs index 6b914c501f2..f790b1fdf59 100644 --- a/pallets/asset-registry/src/mock.rs +++ b/pallets/asset-registry/src/mock.rs @@ -25,7 +25,7 @@ use sp_runtime::{ use frame_support::traits::Everything; -use polkadot_xcm::v3::MultiLocation; +use polkadot_xcm::v5::Location; use crate::{self as asset_registry, Config}; @@ -83,13 +83,14 @@ impl system::Config for Test { type PreInherents = (); type PostInherents = (); type PostTransactions = (); + type ExtensionsWeightInfo = (); } -use codec::{Decode, Encode, MaxEncodedLen}; +use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen}; use scale_info::TypeInfo; -#[derive(Debug, Default, Encode, Decode, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)] -pub struct AssetLocation(pub MultiLocation); +#[derive(Debug, Default, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +pub struct AssetLocation(pub Location); impl Config for Test { type RuntimeEvent = RuntimeEvent; diff --git a/pallets/asset-registry/src/tests.rs b/pallets/asset-registry/src/tests.rs index ed4f60fcb21..a8c0ff86f71 100644 --- a/pallets/asset-registry/src/tests.rs +++ b/pallets/asset-registry/src/tests.rs @@ -23,8 +23,10 @@ use crate::{mock::*, XcmRateLimitsInRegistry}; use codec::Encode; use frame_support::{assert_noop, assert_ok, BoundedVec}; use orml_traits::GetByKey; -use polkadot_xcm::v3::prelude::*; +use polkadot_xcm::v5::prelude::*; +use polkadot_xcm::v5::Junctions::X2; use sp_std::convert::TryInto; +use sp_std::sync::Arc; #[test] fn register_asset_works() { @@ -171,7 +173,7 @@ fn location_mapping_works() { ); let key = Junction::from(BoundedVec::try_from(asset_id.encode()).unwrap()); - let asset_location = AssetLocation(MultiLocation::new(0, X2(Parachain(200), key))); + let asset_location = AssetLocation(Location::new(0, X2(Arc::new([Parachain(200), key])))); assert_ok!(AssetRegistryPallet::set_location( RuntimeOrigin::root(), @@ -692,7 +694,7 @@ fn register_asset_should_work_when_location_is_provided() { let asset_id: RegistryAssetId = 10; let key = Junction::from(BoundedVec::try_from(asset_id.encode()).unwrap()); - let asset_location = AssetLocation(MultiLocation::new(0, X2(Parachain(200), key))); + let asset_location = AssetLocation(Location::new(0, X2(Arc::new([Parachain(200), key])))); assert_ok!(AssetRegistryPallet::register( RuntimeOrigin::root(), @@ -731,7 +733,7 @@ fn register_asset_should_fail_when_location_is_already_registered() { // Arrange let asset_id: RegistryAssetId = 10; let key = Junction::from(BoundedVec::try_from(asset_id.encode()).unwrap()); - let asset_location = AssetLocation(MultiLocation::new(0, X2(Parachain(2021), key))); + let asset_location = AssetLocation(Location::new(0, X2(Arc::new([Parachain(2021), key])))); assert_ok!(AssetRegistryPallet::register( RuntimeOrigin::root(), b"asset_id".to_vec(), @@ -766,7 +768,7 @@ fn set_location_should_fail_when_location_is_already_registered() { // Arrange let asset_id: RegistryAssetId = 10; let key = Junction::from(BoundedVec::try_from(asset_id.encode()).unwrap()); - let asset_location = AssetLocation(MultiLocation::new(0, X2(Parachain(2021), key))); + let asset_location = AssetLocation(Location::new(0, X2(Arc::new([Parachain(2021), key])))); assert_ok!(AssetRegistryPallet::register( RuntimeOrigin::root(), b"asset_id".to_vec(), @@ -792,7 +794,7 @@ fn set_location_should_remove_old_location() { // Arrange let asset_id: RegistryAssetId = 10; let key = Junction::from(BoundedVec::try_from(asset_id.encode()).unwrap()); - let old_asset_location = AssetLocation(MultiLocation::new(0, X2(Parachain(2021), key))); + let old_asset_location = AssetLocation(Location::new(0, X2(Arc::new([Parachain(2021), key])))); assert_ok!(AssetRegistryPallet::register( RuntimeOrigin::root(), b"asset_id".to_vec(), @@ -808,7 +810,7 @@ fn set_location_should_remove_old_location() { assert_ok!(AssetRegistryPallet::set_location( RuntimeOrigin::root(), asset_id, - AssetLocation(MultiLocation::new(0, X2(Parachain(2022), key))) + AssetLocation(Location::new(0, X2(Arc::new([Parachain(2022), key])))) )); // Assert @@ -822,7 +824,7 @@ fn register_asset_should_work_when_all_optional_are_provided() { let asset_id: RegistryAssetId = 10; let key = Junction::from(BoundedVec::try_from(asset_id.encode()).unwrap()); - let asset_location = AssetLocation(MultiLocation::new(0, X2(Parachain(200), key))); + let asset_location = AssetLocation(Location::new(0, X2(Arc::new([Parachain(200), key])))); assert_ok!(AssetRegistryPallet::register( RuntimeOrigin::root(), diff --git a/pallets/asset-registry/src/types.rs b/pallets/asset-registry/src/types.rs index 81747db0946..9c1453ea2cf 100644 --- a/pallets/asset-registry/src/types.rs +++ b/pallets/asset-registry/src/types.rs @@ -15,6 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use codec::DecodeWithMemTracking; use frame_support::pallet_prelude::*; use scale_info::TypeInfo; use sp_std::vec::Vec; @@ -26,7 +27,7 @@ use serde::{Deserialize, Serialize}; pub type Name = BoundedVec; pub type Symbol = BoundedVec; -#[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[derive(Encode, Decode, DecodeWithMemTracking, Eq, PartialEq, Copy, Clone, RuntimeDebug, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum AssetType { Token, @@ -86,7 +87,7 @@ pub struct AssetMetadata { pub(super) decimals: u8, } -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)] +#[derive(Clone, Encode, Decode, DecodeWithMemTracking, Eq, PartialEq, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct Metadata { pub(super) symbol: Vec, diff --git a/pallets/ema-oracle/Cargo.toml b/pallets/ema-oracle/Cargo.toml new file mode 100644 index 00000000000..ece6faf59dd --- /dev/null +++ b/pallets/ema-oracle/Cargo.toml @@ -0,0 +1,62 @@ +[package] +name = "pallet-ema-oracle" +version = "1.4.0" +description = "Exponential moving average oracle for AMM pools" +authors = ["GalacticCouncil"] +edition = "2021" +license = "Apache 2.0" +repository = "https://github.com/galacticcouncil/warehouse" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +serde = { workspace = true, optional = true } +scale-info = {workspace = true } +codec = { workspace = true, features = ["derive", "max-encoded-len"] } + +# HydraDX dependencies +basilisk-traits = { workspace = true } +basilisk-math = { workspace = true } +hydra-dx-math = { workspace = true } + +# Substrate dependencies +frame-benchmarking = { workspace = true, optional = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +sp-arithmetic = { workspace = true } +sp-core = { workspace = true } +sp-std = { workspace = true } +sp-runtime = { workspace = true } + +log = { workspace = true } + +[dev-dependencies] +pretty_assertions = { workspace = true } +proptest = { workspace = true } +rug = { workspace = true } +sp-io = { workspace = true } +test-utils = { workspace = true } + +[features] +default = ["std"] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "frame-support/runtime-benchmarks", +] +std = [ + "serde", + "codec/std", + "frame-support/std", + "frame-system/std", + "frame-benchmarking/std", + "log/std", + "sp-arithmetic/std", + "sp-core/std", + "sp-std/std", + "basilisk-traits/std", + "hydra-dx-math/std", + "scale-info/std", +] +try-runtime = ["frame-support/try-runtime"] diff --git a/pallets/ema-oracle/README.md b/pallets/ema-oracle/README.md new file mode 100644 index 00000000000..8ad7411a947 --- /dev/null +++ b/pallets/ema-oracle/README.md @@ -0,0 +1,53 @@ +# pallet-ema-oracle + +## EMA Oracle Pallet + +### Overview + +This pallet provides exponential moving average (EMA) oracles of different periods for price, +volume and liquidity for a combination of source and asset pair based on data coming in from +different sources. + +#### Integration + +Data is ingested by plugging the provided `OnActivityHandler` into callbacks provided by other +pallets (e.g. xyk pallet). + +It is meant to be used by other pallets via the `AggregatedOracle` and `AggregatedPriceOracle` +traits. + +When integrating with this pallet take care to use the `on_trade_weight`, +`on_liquidity_changed_weight` and `get_entry_weight` into account when calculating the weight +for your extrinsics (that either feed data into or take data from this pallet). + +#### Concepts + +- *EMA*: Averaging via exponential decay with a smoothing factor; meaning each new value to + integrate into the average is multiplied with a smoothing factor between 0 and 1. +- *Smoothing Factor*: A factor applied to each value aggregated into the averaging oracle. + Implicitly determines the oracle period. +- *Period*: The window over which an oracle is averaged. Certain smoothing factors correspond to + an oracle period. E.g. ten minutes oracle period ≈ 0.0198 +- *Source*: The source of the data. E.g. xyk pallet. + +#### Implementation + +This pallet aggregates data in the following way: `on_trade` or `on_liquidity_changed` a new +entry is created for the incoming data. This then updates any existing entries already present +in storage for this block (for this combination of source and assets) or inserts it. Note that +this aggregation is NOT based on EMA, yet, it just sums the volume and replaces price and +liquidity with the most recent value. + +At the end of the block, all the entries are merged into +permanent storage via the exponential moving average logic defined in the math package this +pallet depens on. There is one oracle entry for each combination of `(source, asset_pair, +period)` in storage. + +Oracle values are accessed lazily. This means that the storage does not contain the most recent +value, but the value calculated the last time it was updated via trade or liquidity change. On a +read the values are read from storage and then fast-forwarded (assuming the volume to be zero +and the price and liquidity to be constant) to the last block. Note: The most recent oracle +values are always from the last block. This avoids e.g. sandwiching risks. If you want current +prices you should use a spot price or similar. + +License: Apache 2.0 diff --git a/pallets/ema-oracle/proptest-regressions/tests.txt b/pallets/ema-oracle/proptest-regressions/tests.txt new file mode 100644 index 00000000000..424e0806b52 --- /dev/null +++ b/pallets/ema-oracle/proptest-regressions/tests.txt @@ -0,0 +1,7 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 4a6f85944ada54b619d9671c9eeebe28a4094e9c2b89bb0428003d5dc375c96c # shrinks to (asset_a, asset_b) = (0, 1), (amount_a, amount_b) = (1, 340282366920938463464) diff --git a/pallets/ema-oracle/src/benchmarking.rs b/pallets/ema-oracle/src/benchmarking.rs new file mode 100644 index 00000000000..baccedeef19 --- /dev/null +++ b/pallets/ema-oracle/src/benchmarking.rs @@ -0,0 +1,383 @@ +// This file is part of pallet-ema-oracle. + +// Copyright (C) 2022-2023 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; + +pub const HDX: AssetId = 1_000; +pub const DOT: AssetId = 2_000; + +use frame_benchmarking::benchmarks; +use frame_support::{assert_ok, dispatch::RawOrigin, traits::Hooks}; + +#[cfg(test)] +use pretty_assertions::assert_eq; + +use crate::Pallet as EmaOracle; + +/// Default oracle source. +const SOURCE: Source = *b"dummysrc"; + +fn fill_whitelist_storage(n: u32) { + for i in 0..n { + assert_ok!(EmaOracle::::add_oracle(RawOrigin::Root.into(), SOURCE, (HDX, i))); + } +} +benchmarks! { + add_oracle { + let max_entries = <::MaxUniqueEntries as Get>::get(); + fill_whitelist_storage::(max_entries - 1); + + assert_eq!(WhitelistedAssets::::get().len(), (max_entries - 1) as usize); + + }: _(RawOrigin::Root, SOURCE, (HDX, DOT)) + verify { + assert!(WhitelistedAssets::::get().contains(&(SOURCE, (HDX, DOT)))); + } + + remove_oracle { + let max_entries = <::MaxUniqueEntries as Get>::get(); + fill_whitelist_storage::(max_entries - 1); + + assert_ok!(EmaOracle::::add_oracle(RawOrigin::Root.into(), SOURCE, (HDX, DOT))); + + assert_eq!(WhitelistedAssets::::get().len(), max_entries as usize); + + }: _(RawOrigin::Root, SOURCE, (HDX, DOT)) + verify { + assert!(!WhitelistedAssets::::get().contains(&(SOURCE, (HDX, DOT)))); + } + + on_finalize_no_entry { + let block_num: u32 = 5; + }: { EmaOracle::::on_finalize(block_num.into()); } + verify { + } + + #[extra] + on_finalize_insert_one_token { + let max_entries = <::MaxUniqueEntries as Get>::get(); + fill_whitelist_storage::(max_entries); + + let block_num: BlockNumberFor = 5u32.into(); + let prev_block = block_num.saturating_sub(One::one()); + + frame_system::Pallet::::set_block_number(prev_block); + EmaOracle::::on_initialize(prev_block); + EmaOracle::::on_finalize(prev_block); + + frame_system::Pallet::::set_block_number(block_num); + EmaOracle::::on_initialize(block_num); + + let (amount_in, amount_out) = (1_000_000_000_000, 2_000_000_000_000); + let (liquidity_asset_in, liquidity_asset_out) = (1_000_000_000_000_000, 2_000_000_000_000_000); + + T::BenchmarkHelper::register_asset(HDX)?; + T::BenchmarkHelper::register_asset(DOT)?; + + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, HDX, DOT, amount_in, amount_out, liquidity_asset_in, liquidity_asset_out, + Price::new(liquidity_asset_in, liquidity_asset_out))); + let entry = OracleEntry { + price: Price::from((liquidity_asset_in, liquidity_asset_out)), + volume: Volume::from_a_in_b_out(amount_in, amount_out), + liquidity: Liquidity::new(liquidity_asset_in, liquidity_asset_out), + updated_at: block_num, + }; + + assert_eq!(Accumulator::::get().into_inner(), [((SOURCE, ordered_pair(HDX, DOT)), entry.clone())].into_iter().collect()); + + }: { EmaOracle::::on_finalize(block_num); } + verify { + assert!(Accumulator::::get().is_empty()); + assert_eq!(Oracles::::get((SOURCE, ordered_pair(HDX, DOT), OraclePeriod::LastBlock)).unwrap(), (entry, block_num)); + } + + #[extra] + on_finalize_update_one_token { + let max_entries = <::MaxUniqueEntries as Get>::get(); + fill_whitelist_storage::(max_entries); + + let initial_data_block: BlockNumberFor = 5u32.into(); + // higher update time difference might make exponentiation more expensive + let block_num = initial_data_block.saturating_add(1_000_000u32.into()); + + frame_system::Pallet::::set_block_number(initial_data_block); + EmaOracle::::on_initialize(initial_data_block); + let (amount_in, amount_out) = (1_000_000_000_000, 2_000_000_000_000); + let (liquidity_asset_in, liquidity_asset_out) = (1_000_000_000_000_000, 2_000_000_000_000_000); + + T::BenchmarkHelper::register_asset(HDX)?; + T::BenchmarkHelper::register_asset(DOT)?; + + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, HDX, DOT, amount_in, amount_out, liquidity_asset_in, liquidity_asset_out, + Price::new(liquidity_asset_in, liquidity_asset_out))); + EmaOracle::::on_finalize(initial_data_block); + + frame_system::Pallet::::set_block_number(block_num); + EmaOracle::::on_initialize(block_num); + + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, HDX, DOT, amount_in, amount_out, liquidity_asset_in, liquidity_asset_out, + Price::new(liquidity_asset_in, liquidity_asset_out))); + let entry = OracleEntry { + price: Price::from((liquidity_asset_in, liquidity_asset_out)), + volume: Volume::from_a_in_b_out(amount_in, amount_out), + liquidity: Liquidity::new(liquidity_asset_in, liquidity_asset_out), + updated_at: block_num, + }; + + assert_eq!(Accumulator::::get().into_inner(), [((SOURCE, ordered_pair(HDX, DOT)), entry.clone())].into_iter().collect()); + + }: { EmaOracle::::on_finalize(block_num); } + verify { + assert!(Accumulator::::get().is_empty()); + assert_eq!(Oracles::::get((SOURCE, ordered_pair(HDX, DOT), OraclePeriod::LastBlock)).unwrap(), (entry, initial_data_block)); + } + + on_finalize_multiple_tokens { + let b in 1 .. (T::MaxUniqueEntries::get() - 1); + + let max_entries = <::MaxUniqueEntries as Get>::get(); + fill_whitelist_storage::(max_entries); + + let initial_data_block: BlockNumberFor = 5u32.into(); + let block_num = initial_data_block.saturating_add(1_000_000u32.into()); + + frame_system::Pallet::::set_block_number(initial_data_block); + EmaOracle::::on_initialize(initial_data_block); + let (amount_in, amount_out) = (1_000_000_000_000, 2_000_000_000_000); + let (liquidity_asset_in, liquidity_asset_out) = (1_000_000_000_000_000, 2_000_000_000_000_000); + for i in 0 .. b { + let asset_a = i * 1_000; + let asset_b = asset_a + 500; + + T::BenchmarkHelper::register_asset(asset_a)?; + T::BenchmarkHelper::register_asset(asset_b)?; + + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, asset_a, asset_b, amount_in, amount_out, liquidity_asset_in, liquidity_asset_out, + Price::new(liquidity_asset_in, liquidity_asset_out))); + } + EmaOracle::::on_finalize(initial_data_block); + + frame_system::Pallet::::set_block_number(block_num); + EmaOracle::::on_initialize(block_num); + for i in 0 .. b { + let asset_a = i * 1_000; + let asset_b = asset_a + 500; + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, asset_a, asset_b, amount_in, amount_out, liquidity_asset_in, liquidity_asset_out, + Price::new(liquidity_asset_in, liquidity_asset_out))); + } + }: { EmaOracle::::on_finalize(block_num); } + verify { + let entry = OracleEntry { + price: Price::from((liquidity_asset_in, liquidity_asset_out)), + volume: Volume::from_a_in_b_out(amount_in, amount_out), + liquidity: Liquidity::new(liquidity_asset_in, liquidity_asset_out), + updated_at: block_num, + }; + + for i in 0 .. b { + let asset_a = i * 1_000; + let asset_b = asset_a + 500; + assert_eq!(Oracles::::get((SOURCE, ordered_pair(asset_a, asset_b), OraclePeriod::LastBlock)).unwrap(), (entry.clone(), initial_data_block)); + } + } + + on_trade_multiple_tokens { + let b in 1 .. (T::MaxUniqueEntries::get() - 1); + + let max_entries = <::MaxUniqueEntries as Get>::get(); + fill_whitelist_storage::(max_entries); + + let initial_data_block: BlockNumberFor = 5u32.into(); + let block_num = initial_data_block.saturating_add(1_000_000u32.into()); + + let mut entries = Vec::new(); + + frame_system::Pallet::::set_block_number(initial_data_block); + EmaOracle::::on_initialize(initial_data_block); + let (amount_in, amount_out) = (1_000_000_000_000, 2_000_000_000_000); + let (liquidity_asset_in, liquidity_asset_out) = (1_000_000_000_000_000, 2_000_000_000_000_000); + for i in 0 .. b { + let asset_a = i * 1_000; + let asset_b = asset_a + 500; + + T::BenchmarkHelper::register_asset(asset_a)?; + T::BenchmarkHelper::register_asset(asset_b)?; + + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, asset_a, asset_b, amount_in, amount_out, liquidity_asset_in, liquidity_asset_out, + Price::new(liquidity_asset_in, liquidity_asset_out))); + } + EmaOracle::::on_finalize(initial_data_block); + + frame_system::Pallet::::set_block_number(block_num); + EmaOracle::::on_initialize(block_num); + let entry = OracleEntry { + price: Price::from((liquidity_asset_in, liquidity_asset_out)), + volume: Volume::from_a_in_b_out(amount_in, amount_out), + liquidity: Liquidity::new(liquidity_asset_in, liquidity_asset_out), + updated_at: block_num, + }; + for i in 0 .. b { + let asset_a = i * 1_000; + let asset_b = asset_a + 500; + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, asset_a, asset_b, amount_in, amount_out, liquidity_asset_in, liquidity_asset_out, + Price::new(liquidity_asset_in, liquidity_asset_out))); + entries.push(((SOURCE, ordered_pair(asset_a, asset_b)), entry.clone())); + } + let asset_a = b * 1_000; + let asset_b = asset_a + 500; + T::BenchmarkHelper::register_asset(asset_a)?; + T::BenchmarkHelper::register_asset(asset_b)?; + + let res = core::cell::RefCell::new(Err(DispatchError::Other("Not initialized"))); + }: { + let _ = res.replace( + OnActivityHandler::::on_trade( + SOURCE, asset_a, asset_b, amount_in, amount_out, liquidity_asset_in, liquidity_asset_out, + Price::new(liquidity_asset_in, liquidity_asset_out)) + .map_err(|(_w, e)| e) + ); + } + verify { + assert_ok!(*res.borrow()); + entries.push(((SOURCE, ordered_pair(asset_a, asset_b)), entry.clone())); + + assert_eq!(Accumulator::::get().into_inner(), entries.into_iter().collect()); + } + + on_liquidity_changed_multiple_tokens { + let b in 1 .. (T::MaxUniqueEntries::get() - 1); + + let max_entries = <::MaxUniqueEntries as Get>::get(); + fill_whitelist_storage::(max_entries); + + let initial_data_block: BlockNumberFor = 5u32.into(); + let block_num = initial_data_block.saturating_add(1_000_000u32.into()); + + let mut entries = Vec::new(); + + frame_system::Pallet::::set_block_number(initial_data_block); + EmaOracle::::on_initialize(initial_data_block); + let (amount_a, amount_b) = (1_000_000_000_000, 2_000_000_000_000); + let (liquidity_asset_a, liquidity_asset_b) = (1_000_000_000_000_000, 2_000_000_000_000_000); + for i in 0 .. b { + let asset_a = i * 1_000; + let asset_b = asset_a + 500; + + T::BenchmarkHelper::register_asset(asset_a)?; + T::BenchmarkHelper::register_asset(asset_b)?; + + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, asset_a, asset_b, amount_a, amount_b, liquidity_asset_a, liquidity_asset_b, + Price::new(liquidity_asset_a, liquidity_asset_b))); + } + EmaOracle::::on_finalize(initial_data_block); + + frame_system::Pallet::::set_block_number(block_num); + EmaOracle::::on_initialize(block_num); + let entry = OracleEntry { + price: Price::from((liquidity_asset_a, liquidity_asset_b)), + volume: Volume::from_a_in_b_out(amount_a, amount_b), + liquidity: Liquidity::new(liquidity_asset_a, liquidity_asset_b), + updated_at: block_num, + }; + for i in 0 .. b { + let asset_a = i * 1_000; + let asset_b = asset_a + 500; + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, asset_a, asset_b, amount_a, amount_b, liquidity_asset_a, liquidity_asset_b, + Price::new(liquidity_asset_a, liquidity_asset_b))); + entries.push(((SOURCE, ordered_pair(asset_a, asset_b)), entry.clone())); + } + let asset_a = b * 1_000; + let asset_b = asset_a + 500; + T::BenchmarkHelper::register_asset(asset_a)?; + T::BenchmarkHelper::register_asset(asset_b)?; + + let res = core::cell::RefCell::new(Err(DispatchError::Other("Not initialized"))); + }: { + let _ = res.replace( + OnActivityHandler::::on_liquidity_changed( + SOURCE, asset_a, asset_b, amount_a, amount_b, liquidity_asset_a, liquidity_asset_b, + Price::new(liquidity_asset_a, liquidity_asset_b)) + .map_err(|(_w, e)| e) + ); + } + verify { + assert_ok!(*res.borrow()); + let liquidity_entry = OracleEntry { + price: Price::from((liquidity_asset_a, liquidity_asset_b)), + volume: Volume::default(), + liquidity: Liquidity::new(liquidity_asset_a, liquidity_asset_b), + updated_at: block_num, + }; + entries.push(((SOURCE, ordered_pair(asset_a, asset_b)), liquidity_entry)); + + assert_eq!(Accumulator::::get().into_inner(), entries.into_iter().collect()); + } + + get_entry { + let max_entries = <::MaxUniqueEntries as Get>::get(); + fill_whitelist_storage::(max_entries); + + let initial_data_block: BlockNumberFor = 5u32.into(); + let oracle_age: BlockNumberFor = 999_999u32.into(); + let block_num = initial_data_block.saturating_add(oracle_age.saturating_add(One::one())); + + frame_system::Pallet::::set_block_number(initial_data_block); + EmaOracle::::on_initialize(initial_data_block); + let (amount_in, amount_out) = (1_000_000_000_000, 2_000_000_000_000); + let (liquidity_asset_in, liquidity_asset_out) = (1_000_000_000_000_000, 2_000_000_000_000_000); + let asset_a = 1_000; + let asset_b = asset_a + 500; + + T::BenchmarkHelper::register_asset(asset_a)?; + T::BenchmarkHelper::register_asset(asset_b)?; + + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, asset_a, asset_b, amount_in, amount_out, liquidity_asset_in, liquidity_asset_out, + Price::new(liquidity_asset_in, liquidity_asset_out))); + EmaOracle::::on_finalize(initial_data_block); + + frame_system::Pallet::::set_block_number(block_num); + EmaOracle::::on_initialize(block_num); + + let res = core::cell::RefCell::new(Err(OracleError::NotPresent)); + + // aim to find a period that is not `LastBlock`, falling back to `LastBlock` if none is found. + let period = T::SupportedPeriods::get().into_iter().find(|p| p != &OraclePeriod::LastBlock).unwrap_or(OraclePeriod::LastBlock); + + }: { let _ = res.replace(EmaOracle::::get_entry(asset_a, asset_b, period, SOURCE)); } + verify { + assert_eq!(*res.borrow(), Ok(AggregatedEntry { + price: Price::from((liquidity_asset_in, liquidity_asset_out)), + volume: Volume::default(), + liquidity: Liquidity::new(liquidity_asset_in, liquidity_asset_out), + oracle_age, + })); + } + + impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test); +} diff --git a/pallets/ema-oracle/src/lib.rs b/pallets/ema-oracle/src/lib.rs new file mode 100644 index 00000000000..9891ca8e342 --- /dev/null +++ b/pallets/ema-oracle/src/lib.rs @@ -0,0 +1,662 @@ +// This file is part of pallet-ema-oracle. + +// Copyright (C) 2022-2023 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # EMA Oracle Pallet +//! +//! ## Overview +//! +//! This pallet provides exponential moving average (EMA) oracles of different periods for price, +//! volume and liquidity for a combination of source and asset pair based on data coming in from +//! different sources. +//! +//! ### Integration +//! +//! Data is ingested by plugging the provided `OnActivityHandler` into callbacks provided by other +//! pallets (e.g. xyk pallet). +//! +//! It is meant to be used by other pallets via the `AggregatedOracle` and `AggregatedPriceOracle` +//! traits. +//! +//! When integrating with this pallet take care to use the `on_trade_weight`, +//! `on_liquidity_changed_weight` and `get_entry_weight` into account when calculating the weight +//! for your extrinsics (that either feed data into or take data from this pallet). +//! +//! ### Concepts +//! +//! - *EMA*: Averaging via exponential decay with a smoothing factor; meaning each new value to +//! integrate into the average is multiplied with a smoothing factor between 0 and 1. +//! - *Smoothing Factor*: A factor applied to each value aggregated into the averaging oracle. +//! Implicitly determines the oracle period. +//! - *Period*: The window over which an oracle is averaged. Certain smoothing factors correspond to +//! an oracle period. E.g. ten minutes oracle period ≈ 0.0198 +//! - *Source*: The source of the data. E.g. xyk pallet. +//! +//! ### Implementation +//! +//! This pallet aggregates data in the following way: `on_trade` or `on_liquidity_changed` a new +//! entry is created for the incoming data. This then updates any existing entries already present +//! in storage for this block (for this combination of source and assets) or inserts it. Note that +//! this aggregation is NOT based on EMA, yet, it just sums the volume and replaces price and +//! liquidity with the most recent value. +//! +//! At the end of the block, all the entries are merged into permanent storage via the exponential +//! moving average logic defined in the math package this pallet depens on. There is one oracle +//! entry for each combination of `(source, asset_pair, period)` in storage. +//! +//! Oracle values are accessed lazily. This means that the storage does not contain the most recent +//! value, but the value calculated the last time it was updated via trade or liquidity change. On a +//! read the values are read from storage and then fast-forwarded (assuming the volume to be zero +//! and the price and liquidity to be constant) to the last block. Note: The most recent oracle +//! values are always from the last block. This avoids e.g. sandwiching risks. If you want current +//! prices you should use a spot price or similar. + +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::manual_inspect)] + +use basilisk_traits::oracle::{AggregatedEntry, AggregatedOracle, AggregatedPriceOracle, Liquidity, Volume}; +use basilisk_traits::{OnCreatePoolHandler, OnLiquidityChangedHandler, OnTradeHandler}; +use frame_support::pallet_prelude::*; +use frame_support::sp_runtime::traits::{BlockNumberProvider, One, Zero}; +use frame_support::traits::Contains; +use frame_system::pallet_prelude::BlockNumberFor; +use sp_arithmetic::traits::Saturating; +use sp_std::marker::PhantomData; +use sp_std::prelude::*; + +#[cfg(test)] +mod tests; + +mod types; +pub use types::*; + +#[allow(clippy::all)] +pub mod weights; +pub use weights::WeightInfo; + +mod benchmarking; + +/// The maximum number of periods that could have corresponding oracles. +pub const MAX_PERIODS: u32 = OraclePeriod::all_periods().len() as u32; + +const LOG_TARGET: &str = "runtime::ema-oracle"; + +// Re-export pallet items so that they can be accessed from the crate namespace. +pub use pallet::*; + +#[cfg(feature = "runtime-benchmarks")] +pub trait BenchmarkHelper { + fn register_asset(asset_id: AssetId) -> DispatchResult; +} +#[cfg(feature = "runtime-benchmarks")] +impl BenchmarkHelper for () { + fn register_asset(_asset_id: AssetId) -> DispatchResult { + Ok(()) + } +} + +#[allow(clippy::type_complexity)] +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::{BoundedBTreeMap, BoundedBTreeSet}; + use frame_system::pallet_prelude::{BlockNumberFor, OriginFor}; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// Weight information for the extrinsics. + type WeightInfo: WeightInfo; + + /// Origin that can enable oracle for assets that would be rejected by `OracleWhitelist` otherwise. + type AuthorityOrigin: EnsureOrigin; + + /// Provider for the current block number. + type BlockNumberProvider: BlockNumberProvider>; + + /// The periods supported by the pallet. I.e. which oracles to track. + type SupportedPeriods: Get>>; + + /// Whitelist determining what oracles are tracked by the pallet. + type OracleWhitelist: Contains<(Source, AssetId, AssetId)>; + + /// Maximum number of unique oracle entries expected in one block. + #[pallet::constant] + type MaxUniqueEntries: Get; + + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper: BenchmarkHelper; + } + + #[pallet::error] + pub enum Error { + TooManyUniqueEntries, + OnTradeValueZero, + OracleNotFound, + } + + #[pallet::event] + #[pallet::generate_deposit(pub(crate) fn deposit_event)] + pub enum Event { + /// Oracle was added to the whitelist. + AddedToWhitelist { source: Source, assets: (AssetId, AssetId) }, + /// Oracle was removed from the whitelist. + RemovedFromWhitelist { source: Source, assets: (AssetId, AssetId) }, + } + + /// Accumulator for oracle data in current block that will be recorded at the end of the block. + #[pallet::storage] + #[pallet::getter(fn accumulator)] + pub type Accumulator = StorageValue< + _, + BoundedBTreeMap<(Source, (AssetId, AssetId)), OracleEntry>, T::MaxUniqueEntries>, + ValueQuery, + >; + + /// Oracle storage keyed by data source, involved asset ids and the period length of the oracle. + /// + /// Stores the data entry as well as the block number when the oracle was first initialized. + #[pallet::storage] + #[pallet::getter(fn oracle)] + pub type Oracles = StorageNMap< + _, + ( + NMapKey, + NMapKey, + NMapKey, + ), + (OracleEntry>, BlockNumberFor), + OptionQuery, + >; + + /// Assets that are whitelisted and tracked by the pallet. + #[pallet::storage] + pub type WhitelistedAssets = + StorageValue<_, BoundedBTreeSet<(Source, (AssetId, AssetId)), T::MaxUniqueEntries>, ValueQuery>; + + #[pallet::genesis_config] + #[derive(frame_support::DefaultNoBound)] + pub struct GenesisConfig { + pub initial_data: Vec<(Source, (AssetId, AssetId), Price, Liquidity)>, + #[serde(skip)] + pub _marker: PhantomData, + } + + #[pallet::genesis_build] + impl BuildGenesisConfig for GenesisConfig { + fn build(&self) { + for &(source, (asset_a, asset_b), price, liquidity) in self.initial_data.iter() { + let entry: OracleEntry> = { + let e = OracleEntry { + price, + volume: Volume::default(), + liquidity, + updated_at: BlockNumberFor::::zero(), + }; + if ordered_pair(asset_a, asset_b) == (asset_a, asset_b) { + e + } else { + e.inverted() + } + }; + + for period in T::SupportedPeriods::get() { + Pallet::::update_oracle(source, ordered_pair(asset_a, asset_b), period, entry.clone()); + } + } + } + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(_n: BlockNumberFor) -> Weight { + T::WeightInfo::on_finalize_no_entry() + } + + fn on_finalize(_n: BlockNumberFor) { + // update oracles based on data accumulated during the block + Self::update_oracles_from_accumulator(); + } + + fn integrity_test() { + assert!( + T::MaxUniqueEntries::get() > 0, + "At least one trade should be possible per block." + ); + } + } + + #[pallet::call] + impl Pallet { + #[pallet::call_index(0)] + #[pallet::weight(::WeightInfo::add_oracle())] + pub fn add_oracle(origin: OriginFor, source: Source, assets: (AssetId, AssetId)) -> DispatchResult { + T::AuthorityOrigin::ensure_origin(origin)?; + + let assets = ordered_pair(assets.0, assets.1); + + WhitelistedAssets::::mutate(|list| { + list.try_insert((source, (assets))) + .map_err(|_| Error::::TooManyUniqueEntries) + })?; + + Self::deposit_event(Event::AddedToWhitelist { source, assets }); + + Ok(()) + } + + #[pallet::call_index(1)] + #[pallet::weight(::WeightInfo::remove_oracle())] + pub fn remove_oracle(origin: OriginFor, source: Source, assets: (AssetId, AssetId)) -> DispatchResult { + T::AuthorityOrigin::ensure_origin(origin)?; + + let assets = ordered_pair(assets.0, assets.1); + + WhitelistedAssets::::mutate(|list| { + ensure!(list.remove(&(source, (assets))), Error::::OracleNotFound); + + Ok::<(), DispatchError>(()) + })?; + + // remove oracle from the storage + for period in T::SupportedPeriods::get().into_iter() { + let _ = Accumulator::::mutate(|accumulator| { + accumulator.remove(&(source, assets)); + Ok::<(), ()>(()) + }); + Oracles::::remove((source, assets, period)); + } + + Self::deposit_event(Event::RemovedFromWhitelist { source, assets }); + + Ok(()) + } + } +} + +impl Pallet { + /// Insert or update data in the accumulator from received entry. Aggregates volume and + /// takes the most recent data for the rest. + pub(crate) fn on_entry( + src: Source, + assets: (AssetId, AssetId), + oracle_entry: OracleEntry>, + ) -> Result<(), ()> { + if !T::OracleWhitelist::contains(&(src, assets.0, assets.1)) { + // if we don't track oracle for given asset pair, don't throw error + return Ok(()); + } + + Accumulator::::mutate(|accumulator| { + if let Some(entry) = accumulator.get_mut(&(src, assets)) { + entry.accumulate_volume_and_update_from(&oracle_entry); + Ok(()) + } else { + accumulator + .try_insert((src, assets), oracle_entry) + .map(|_| ()) + .map_err(|_| ()) + } + }) + } + + /// Insert or update data in the accumulator from received entry. Aggregates volume and + /// takes the most recent data for the rest. + pub(crate) fn on_trade( + src: Source, + assets: (AssetId, AssetId), + oracle_entry: OracleEntry>, + ) -> Result { + let weight = OnActivityHandler::::on_trade_weight(); + Self::on_entry(src, assets, oracle_entry) + .map(|_| weight) + .map_err(|_| (weight, Error::::TooManyUniqueEntries.into())) + } + + /// Insert or update data in the accumulator from received entry. Aggregates volume and + /// takes the most recent data for the rest. + pub(crate) fn on_liquidity_changed( + src: Source, + assets: (AssetId, AssetId), + oracle_entry: OracleEntry>, + ) -> Result { + let weight = OnActivityHandler::::on_liquidity_changed_weight(); + Self::on_entry(src, assets, oracle_entry) + .map(|_| weight) + .map_err(|_| (weight, Error::::TooManyUniqueEntries.into())) + } + + /// Return the current value of the `LastBlock` oracle for the given `source` and `assets`. + pub(crate) fn last_block_oracle( + source: Source, + assets: (AssetId, AssetId), + block: BlockNumberFor, + ) -> Option<(OracleEntry>, BlockNumberFor)> { + Self::oracle((source, assets, OraclePeriod::LastBlock)).map(|(mut last_block, init)| { + // update the `LastBlock` oracle to the last block if it hasn't been updated for a while + // price and liquidity stay constant, volume becomes zero + if last_block.updated_at != block { + last_block.fast_forward_to(block); + } + (last_block, init) + }) + } + + /// Update oracles based on data accumulated during the block. + fn update_oracles_from_accumulator() { + for ((src, assets), oracle_entry) in Accumulator::::take().into_iter() { + // First we update the non-immediate oracles with the value of the `LastBlock` oracle. + for period in T::SupportedPeriods::get() + .into_iter() + .filter(|p| *p != OraclePeriod::LastBlock) + { + Self::update_oracle(src, assets, period, oracle_entry.clone()); + } + // As we use (the old value of) the `LastBlock` entry to update the other oracles it + // gets updated last. + Self::update_oracle(src, assets, OraclePeriod::LastBlock, oracle_entry.clone()); + } + } + + /// Update the oracle of the given source, assets and period with `oracle_entry`. + fn update_oracle( + src: Source, + assets: (AssetId, AssetId), + period: OraclePeriod, + incoming_entry: OracleEntry>, + ) { + Oracles::::mutate((src, assets, period), |oracle| { + // initialize the oracle entry if it doesn't exist + if oracle.is_none() { + *oracle = Some((incoming_entry.clone(), T::BlockNumberProvider::current_block_number())); + return; + } + if let Some((prev_entry, _)) = oracle.as_mut() { + let parent = T::BlockNumberProvider::current_block_number().saturating_sub(One::one()); + // update the entry to the parent block if it hasn't been updated for a while + if parent > prev_entry.updated_at { + Self::last_block_oracle(src, assets, parent) + .and_then(|(last_block, _)| { + prev_entry.update_outdated_to_current(period, &last_block).map(|_| ()) + }) + .unwrap_or_else(|| { + log::warn!( + target: LOG_TARGET, + "Updating EMA oracle ({src:?}, {assets:?}, {period:?}) to parent block failed. Defaulting to previous value." + ); + debug_assert!(false, "Updating to parent block should not fail."); + }) + } + // calculate the actual update with the new value + prev_entry + .update_to_new_by_integrating_incoming(period, &incoming_entry) + .map(|_| ()) + .unwrap_or_else(|| { + log::warn!( + target: LOG_TARGET, + "Updating EMA oracle ({src:?}, {assets:?}, {period:?}) to new value failed. Defaulting to previous value." + ); + debug_assert!(false, "Updating to new value should not fail."); + }); + }; + }); + } + + /// Return the updated oracle entry for the given source, assets and period. + /// + /// The value will be up to date until the parent block, thus excluding trading data from the + /// current block. Note: It does not update the values in storage. + fn get_updated_entry( + src: Source, + assets: (AssetId, AssetId), + period: OraclePeriod, + ) -> Option<(OracleEntry>, BlockNumberFor)> { + let parent = T::BlockNumberProvider::current_block_number().saturating_sub(One::one()); + // First get the `LastBlock` oracle to calculate the updated values for the others. + let (last_block, last_block_init) = Self::last_block_oracle(src, assets, parent)?; + // If it was requested return it directly. + if period == OraclePeriod::LastBlock { + return Some((last_block, last_block_init)); + } + + let (entry, init) = Self::oracle((src, assets, period))?; + if entry.updated_at < parent { + entry.calculate_current_from_outdated(period, &last_block) + } else { + Some(entry) + } + .map(|return_entry| (return_entry, init)) + } +} + +/// A callback handler for trading and liquidity activity that schedules oracle updates. +pub struct OnActivityHandler(PhantomData); + +impl OnCreatePoolHandler for OnActivityHandler { + // Nothing to do on pool creation. Oracles are created lazily. + fn on_create_pool(_asset_a: AssetId, _asset_b: AssetId) -> DispatchResult { + Ok(()) + } +} + +/// Calculate the weight contribution of one `on_trade`/`on_liquidity_changed` call towards +/// `on_finalize`. +pub(crate) fn fractional_on_finalize_weight(max_entries: u32) -> Weight { + T::WeightInfo::on_finalize_multiple_tokens(max_entries) + .saturating_sub(T::WeightInfo::on_finalize_no_entry()) + .saturating_div(max_entries.into()) +} + +impl OnTradeHandler for OnActivityHandler { + fn on_trade( + source: Source, + asset_a: AssetId, + asset_b: AssetId, + amount_a: Balance, + amount_b: Balance, + liquidity_a: Balance, + liquidity_b: Balance, + price: Price, + ) -> Result { + // We assume that zero liquidity values are not valid and can be ignored. + if liquidity_a.is_zero() || liquidity_b.is_zero() { + log::warn!( + target: LOG_TARGET, + "Liquidity amounts should not be zero. Source: {source:?}, liquidity: ({liquidity_a},{liquidity_b})" + ); + return Err((Self::on_trade_weight(), Error::::OnTradeValueZero.into())); + } + + let price = determine_normalized_price(asset_a, asset_b, price); + let volume = determine_normalized_volume(asset_a, asset_b, amount_a, amount_b); + let liquidity = determine_normalized_liquidity(asset_a, asset_b, liquidity_a, liquidity_b); + + let updated_at = T::BlockNumberProvider::current_block_number(); + let entry = OracleEntry { + price, + volume, + liquidity, + updated_at, + }; + Pallet::::on_trade(source, ordered_pair(asset_a, asset_b), entry) + } + + fn on_trade_weight() -> Weight { + let max_entries = T::MaxUniqueEntries::get(); + // on_trade + on_finalize / max_entries + T::WeightInfo::on_trade_multiple_tokens(max_entries) + .saturating_add(fractional_on_finalize_weight::(max_entries)) + } +} + +impl OnLiquidityChangedHandler for OnActivityHandler { + fn on_liquidity_changed( + source: Source, + asset_a: AssetId, + asset_b: AssetId, + _amount_a: Balance, + _amount_b: Balance, + liquidity_a: Balance, + liquidity_b: Balance, + price: Price, + ) -> Result { + if liquidity_a.is_zero() || liquidity_b.is_zero() { + log::trace!( + target: LOG_TARGET, + "Liquidity is zero. Source: {source:?}, liquidity: ({liquidity_a},{liquidity_a})" + ); + } + + let price = determine_normalized_price(asset_a, asset_b, price); + let liquidity = determine_normalized_liquidity(asset_a, asset_b, liquidity_a, liquidity_b); + let updated_at = T::BlockNumberProvider::current_block_number(); + let entry = OracleEntry { + price, + // liquidity provision does not count as trade volume + volume: Volume::default(), + liquidity, + updated_at, + }; + Pallet::::on_liquidity_changed(source, ordered_pair(asset_a, asset_b), entry) + } + + fn on_liquidity_changed_weight() -> Weight { + let max_entries = T::MaxUniqueEntries::get(); + // on_liquidity + on_finalize / max_entries + T::WeightInfo::on_liquidity_changed_multiple_tokens(max_entries) + .saturating_add(fractional_on_finalize_weight::(max_entries)) + } +} + +/// Calculate price from ordered assets +pub fn determine_normalized_price(asset_in: AssetId, asset_out: AssetId, price: Price) -> Price { + if ordered_pair(asset_in, asset_out) == (asset_in, asset_out) { + price + } else { + price.inverted() + } +} + +/// Construct `Volume` based on unordered assets. +pub fn determine_normalized_volume( + asset_in: AssetId, + asset_out: AssetId, + amount_in: Balance, + amount_out: Balance, +) -> Volume { + if ordered_pair(asset_in, asset_out) == (asset_in, asset_out) { + Volume::from_a_in_b_out(amount_in, amount_out) + } else { + Volume::from_a_out_b_in(amount_out, amount_in) + } +} + +/// Construct `Liquidity` based on unordered assets. +pub fn determine_normalized_liquidity( + asset_in: AssetId, + asset_out: AssetId, + liquidity_asset_in: Balance, + liquidity_asset_out: Balance, +) -> Liquidity { + if ordered_pair(asset_in, asset_out) == (asset_in, asset_out) { + Liquidity::new(liquidity_asset_in, liquidity_asset_out) + } else { + Liquidity::new(liquidity_asset_out, liquidity_asset_in) + } +} + +/// Return ordered asset tuple (A,B) where A < B +/// Used in storage +/// The implementation is the same as for AssetPair +pub fn ordered_pair(asset_a: AssetId, asset_b: AssetId) -> (AssetId, AssetId) { + match asset_a <= asset_b { + true => (asset_a, asset_b), + false => (asset_b, asset_a), + } +} + +/// Possible errors when requesting an oracle value. +#[derive(RuntimeDebug, Encode, Decode, Copy, Clone, PartialEq, Eq, TypeInfo)] +pub enum OracleError { + /// The oracle could not be found + NotPresent, + /// The oracle is not defined if the asset ids are the same. + SameAsset, +} + +impl AggregatedOracle, Price> for Pallet { + type Error = OracleError; + + /// Returns the entry corresponding to the given assets and period. + /// The entry is updated to the state of the parent block (but not trading data in the current + /// block). It is also adjusted to make sense for the asset order given as parameters. So + /// calling `get_entry(HDX, DOT, LastBlock, Omnipool)` will return the price `HDX/DOT`, while + /// `get_entry(DOT, HDX, LastBlock, Omnipool)` will return `DOT/HDX`. + fn get_entry( + asset_a: AssetId, + asset_b: AssetId, + period: OraclePeriod, + source: Source, + ) -> Result, Price>, OracleError> { + if asset_a == asset_b { + return Err(OracleError::SameAsset); + }; + Self::get_updated_entry(source, ordered_pair(asset_a, asset_b), period) + .ok_or(OracleError::NotPresent) + .map(|(entry, initialized)| { + let entry = if (asset_a, asset_b) != ordered_pair(asset_a, asset_b) { + entry.inverted() + } else { + entry + }; + entry.into_aggregated(initialized) + }) + } + + fn get_entry_weight() -> Weight { + T::WeightInfo::get_entry() + } +} + +impl AggregatedPriceOracle, Price> for Pallet { + type Error = OracleError; + + fn get_price( + asset_a: AssetId, + asset_b: AssetId, + period: OraclePeriod, + source: Source, + ) -> Result<(Price, BlockNumberFor), Self::Error> { + Self::get_entry(asset_a, asset_b, period, source) + .map(|AggregatedEntry { price, oracle_age, .. }| (price, oracle_age)) + } + + fn get_price_weight() -> Weight { + Self::get_entry_weight() + } +} + +/// Oracle whitelist based on the pallet's storage. +pub struct OracleWhitelist(PhantomData); +impl Contains<(Source, AssetId, AssetId)> for OracleWhitelist { + fn contains(t: &(Source, AssetId, AssetId)) -> bool { + WhitelistedAssets::::get().contains(&(t.0, (t.1, t.2))) + } +} diff --git a/pallets/ema-oracle/src/tests/add_and_remove_oracle.rs b/pallets/ema-oracle/src/tests/add_and_remove_oracle.rs new file mode 100644 index 00000000000..17773c034b3 --- /dev/null +++ b/pallets/ema-oracle/src/tests/add_and_remove_oracle.rs @@ -0,0 +1,182 @@ +// This file is part of pallet-ema-oracle. + +// Copyright (C) 2022-2023 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::*; +pub use mock::{expect_events, EmaOracle, RuntimeOrigin, Test, DOT, HDX, ORACLE_ENTRY_1}; + +use frame_support::{assert_noop, assert_ok}; +use pretty_assertions::assert_eq; + +pub fn new_test_ext() -> sp_io::TestExternalities { + ExtBuilder::default().build() +} + +#[test] +fn add_oracle_should_add_entry_to_storage() { + new_test_ext().execute_with(|| { + assert_ok!(EmaOracle::add_oracle(RuntimeOrigin::root(), SOURCE, (HDX, DOT))); + + expect_events(vec![Event::AddedToWhitelist { + source: SOURCE, + assets: (HDX, DOT), + } + .into()]); + }); +} + +#[test] +fn add_oracle_should_store_assets_in_correct_order() { + new_test_ext().execute_with(|| { + assert_ok!(EmaOracle::add_oracle(RuntimeOrigin::root(), SOURCE, (DOT, HDX))); + + expect_events(vec![Event::AddedToWhitelist { + source: SOURCE, + assets: (HDX, DOT), + } + .into()]); + + assert!(WhitelistedAssets::::get().contains(&(SOURCE, (HDX, DOT)))); + }); +} + +#[test] +fn add_oracle_should_not_fail_when_storage_entry_already_added() { + new_test_ext().execute_with(|| { + assert_ok!(EmaOracle::add_oracle(RuntimeOrigin::root(), SOURCE, (HDX, DOT))); + assert_ok!(EmaOracle::add_oracle(RuntimeOrigin::root(), SOURCE, (HDX, DOT))); + }); +} + +#[test] +fn add_oracle_should_fail_when_storage_is_full() { + new_test_ext().execute_with(|| { + let max_entries = <::MaxUniqueEntries as Get>::get(); + + for i in 0..max_entries { + assert_ok!(EmaOracle::add_oracle(RuntimeOrigin::root(), SOURCE, (HDX, i))); + } + + assert_eq!(WhitelistedAssets::::get().len(), max_entries as usize); + + assert_noop!( + EmaOracle::add_oracle(RuntimeOrigin::root(), SOURCE, (HDX, DOT)), + Error::::TooManyUniqueEntries + ); + }); +} + +#[test] +fn remove_oracle_should_remove_entry_from_storage() { + new_test_ext().execute_with(|| { + assert_ok!(EmaOracle::add_oracle(RuntimeOrigin::root(), SOURCE, (HDX, DOT))); + assert!(WhitelistedAssets::::get().contains(&(SOURCE, (HDX, DOT)))); + + System::set_block_number(5); + EmaOracle::on_initialize(5); + + assert_ok!(EmaOracle::on_trade(SOURCE, ordered_pair(HDX, DOT), ORACLE_ENTRY_1)); + + EmaOracle::on_finalize(5); + System::set_block_number(6); + EmaOracle::on_initialize(6); + + for period in ::SupportedPeriods::get() { + assert_eq!(get_oracle_entry(HDX, DOT, period), Some(ORACLE_ENTRY_1),); + } + + assert_ok!(EmaOracle::remove_oracle(RuntimeOrigin::root(), SOURCE, (HDX, DOT))); + assert!(!WhitelistedAssets::::get().contains(&(SOURCE, (HDX, DOT)))); + + for period in ::SupportedPeriods::get() { + assert!(get_oracle_entry(HDX, DOT, period).is_none()); + } + + EmaOracle::on_finalize(6); + System::set_block_number(7); + EmaOracle::on_initialize(7); + + expect_events(vec![Event::RemovedFromWhitelist { + source: SOURCE, + assets: (HDX, DOT), + } + .into()]); + }); +} + +#[test] +fn remove_oracle_should_fail_when_oracle_not_tracked() { + new_test_ext().execute_with(|| { + assert_noop!( + EmaOracle::remove_oracle(RuntimeOrigin::root(), SOURCE, (HDX, DOT)), + Error::::OracleNotFound + ); + }); +} + +#[test] +fn on_trade_should_include_whitelisted_oracle_for_correct_source() { + new_test_ext().execute_with(|| { + assert_ok!(EmaOracle::add_oracle( + RuntimeOrigin::root(), + SOURCE, + (HDX, INSUFFICIENT_ASSET) + )); + + assert!(get_accumulator_entry(SOURCE, (HDX, INSUFFICIENT_ASSET)).is_none()); + + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, + HDX, + INSUFFICIENT_ASSET, + 1_000, + 500, + 2_000, + 1_000, + Price::new(2_000, 1_000) + )); + + assert!(get_accumulator_entry(SOURCE, (HDX, INSUFFICIENT_ASSET)).is_some()); + assert!(get_accumulator_entry([0; 8], (HDX, INSUFFICIENT_ASSET)).is_none()); + }); +} + +#[test] +fn on_liquidity_changed_should_include_whitelisted_oracle_for_correct_source() { + new_test_ext().execute_with(|| { + assert_ok!(EmaOracle::add_oracle( + RuntimeOrigin::root(), + SOURCE, + (HDX, INSUFFICIENT_ASSET) + )); + + assert!(get_accumulator_entry(SOURCE, (HDX, INSUFFICIENT_ASSET)).is_none()); + + assert_ok!(OnActivityHandler::::on_liquidity_changed( + SOURCE, + HDX, + INSUFFICIENT_ASSET, + 1_000, + 500, + 2_000, + 1_000, + Price::new(2_000, 1_000), + )); + + assert!(get_accumulator_entry(SOURCE, (HDX, INSUFFICIENT_ASSET)).is_some()); + assert!(get_accumulator_entry([0; 8], (HDX, INSUFFICIENT_ASSET)).is_none()); + }); +} diff --git a/pallets/ema-oracle/src/tests/invariants.rs b/pallets/ema-oracle/src/tests/invariants.rs new file mode 100644 index 00000000000..9bf88844645 --- /dev/null +++ b/pallets/ema-oracle/src/tests/invariants.rs @@ -0,0 +1,182 @@ +// This file is part of pallet-ema-oracle. + +// Copyright (C) 2022-2023 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::mock::{DOT, HDX}; +use super::*; + +use pretty_assertions::assert_eq; +use proptest::prelude::*; + +use frame_support::assert_ok; + +// Strategies +fn valid_asset_ids() -> impl Strategy { + (any::(), any::()).prop_filter("asset ids should not be equal", |(a, b)| a != b) +} + +fn non_zero_amount() -> impl Strategy { + 1..Balance::MAX +} + +fn any_volume() -> impl Strategy> { + (any::(), any::(), any::(), any::()).prop_map(|(a_in, b_out, a_out, b_in)| { + Volume { + a_in, + b_out, + a_out, + b_in, + } + }) +} + +fn any_price() -> impl Strategy { + (any::(), non_zero_amount()).prop_map(|(a, b)| Price::new(a, b)) +} + +fn any_liquidity() -> impl Strategy> { + (any::(), any::()).prop_map(|l| l.into()) +} + +fn oracle_entry_with_updated_at(updated_at: BlockNumber) -> impl Strategy> { + (any_price(), any_volume(), any_liquidity(), Just(updated_at)).prop_map(|(price, volume, liquidity, updated_at)| { + OracleEntry { + price, + volume, + liquidity, + updated_at, + } + }) +} + +fn oracle_entry_within_updated_at_range( + (updated_at_min, updated_at_max): (BlockNumber, BlockNumber), +) -> impl Strategy> { + ( + any_price(), + any_volume(), + any_liquidity(), + updated_at_min..updated_at_max, + ) + .prop_map(|(price, volume, liquidity, updated_at)| OracleEntry { + price, + volume, + liquidity, + updated_at, + }) +} + +// Tests +proptest! { + #[test] + fn price_normalization_should_be_independent_of_asset_order( + (asset_a, asset_b) in valid_asset_ids(), + (amount_a, amount_b) in (non_zero_amount(), non_zero_amount()) + ) { + let a_then_b = determine_normalized_price(asset_a, asset_b, Price::new(amount_a, amount_b)); + let b_then_a = determine_normalized_price(asset_b, asset_a, Price::new(amount_b, amount_a)); + prop_assert_eq!(a_then_b, b_then_a); + } +} + +proptest! { + #[test] + fn on_liquidity_changed_should_not_change_volume( + (asset_a, asset_b) in valid_asset_ids(), + (amount_a, amount_b) in (non_zero_amount(), non_zero_amount()), + (liquidity_a, liquidity_b) in (non_zero_amount(), non_zero_amount()), + (second_amount_a, second_amount_b) in (non_zero_amount(), non_zero_amount()), + (second_liquidity_a, second_liquidity_b) in (non_zero_amount(), non_zero_amount()), + ) { + new_test_ext().execute_with(|| { + let updated_at = 5; + System::set_block_number(updated_at); + assert_ok!(OnActivityHandler::::on_trade(SOURCE, asset_a, asset_b, amount_a, amount_b, liquidity_a, liquidity_b, Price::new(liquidity_a, liquidity_b))); + let volume_before = get_accumulator_entry(SOURCE, (asset_a, asset_b)).unwrap().volume; + assert_ok!(OnActivityHandler::::on_liquidity_changed(SOURCE, asset_a, asset_b, second_amount_a, second_amount_b, second_liquidity_a, second_liquidity_b, Price::new(second_liquidity_a, second_liquidity_b))); + let volume_after = get_accumulator_entry(SOURCE, (asset_a, asset_b)).unwrap().volume; + assert_eq!(volume_before, volume_after); + }); + } +} + +proptest! { + #[test] + fn update_outdated_to_current_equals_calculate_current_from_outdated( + start_oracle in oracle_entry_within_updated_at_range((0, 1_000)), + incoming_value in oracle_entry_within_updated_at_range((1_001, 100_000)), + ) { + let next_oracle = start_oracle.calculate_current_from_outdated(TenMinutes, &incoming_value); + + let mut start_oracle = start_oracle; + start_oracle.update_outdated_to_current(TenMinutes, &incoming_value); + prop_assert_eq!(next_oracle, Some(start_oracle)); + } +} + +proptest! { + #[test] + fn update_to_new_by_integrating_incoming_equals_calculate_new_by_integrating_incoming( + start_oracle in oracle_entry_with_updated_at(10_000), + incoming_value in oracle_entry_with_updated_at(10_001), + ) { + let next_oracle = start_oracle.calculate_new_by_integrating_incoming(TenMinutes, &incoming_value); + + let mut start_oracle = start_oracle; + start_oracle.update_to_new_by_integrating_incoming(TenMinutes, &incoming_value); + prop_assert_eq!(next_oracle, Some(start_oracle)); + } +} + +use basilisk_math::ema::{iterated_balance_ema, iterated_price_ema, iterated_volume_ema}; + +proptest! { + #[test] + fn get_entry_equals_iterated_ema( + (amount_hdx, amount_dot) in (non_zero_amount(), non_zero_amount()), + (liquidity_hdx, liquidity_dot) in (non_zero_amount(), non_zero_amount()), + ) { + new_test_ext().execute_with(|| -> Result<(), TestCaseError> { + System::set_block_number(1); + assert_ok!(OnActivityHandler::::on_trade(SOURCE, HDX, DOT, amount_hdx, amount_dot, liquidity_hdx, liquidity_dot, Price::new(liquidity_hdx, liquidity_dot))); + EmaOracle::on_finalize(1); + let oracle_age: u32 = 98; + System::set_block_number(u64::from(oracle_age) + 2); + let smoothing = into_smoothing(LastBlock); + let price = Price::new(liquidity_hdx, liquidity_dot); + let volume = (amount_hdx, amount_dot, 0, 0); + let expected = AggregatedEntry { + price: iterated_price_ema(oracle_age, price, price, smoothing), + volume: iterated_volume_ema(oracle_age, volume, smoothing).into(), + liquidity: (iterated_balance_ema(oracle_age, liquidity_hdx, liquidity_hdx, smoothing), + iterated_balance_ema(oracle_age, liquidity_dot, liquidity_dot, smoothing)).into(), + oracle_age: 98, + }; + prop_assert_eq!(EmaOracle::get_entry(HDX, DOT, LastBlock, SOURCE), Ok(expected)); + + let smoothing = into_smoothing(TenMinutes); + let expected_ten_min = AggregatedEntry { + price: iterated_price_ema(oracle_age, price, price, smoothing), + volume: iterated_volume_ema(oracle_age, volume, smoothing).into(), + liquidity: (iterated_balance_ema(oracle_age, liquidity_hdx, liquidity_hdx, smoothing), + iterated_balance_ema(oracle_age, liquidity_dot, liquidity_dot, smoothing)).into(), + oracle_age: 98, + }; + prop_assert_eq!(EmaOracle::get_entry(HDX, DOT, TenMinutes, SOURCE), Ok(expected_ten_min)); + Ok(()) + })?; + } +} diff --git a/pallets/ema-oracle/src/tests/mock.rs b/pallets/ema-oracle/src/tests/mock.rs new file mode 100644 index 00000000000..29a9b074846 --- /dev/null +++ b/pallets/ema-oracle/src/tests/mock.rs @@ -0,0 +1,177 @@ +// This file is part of pallet-ema-oracle. + +// Copyright (C) 2022-2023 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate as ema_oracle; +use crate::Config; +use basilisk_traits::oracle::{ + Liquidity, + OraclePeriod::{self, *}, + Volume, +}; +use basilisk_traits::Source; +use ema_oracle::OracleEntry; +use frame_support::pallet_prelude::ConstU32; +use frame_support::parameter_types; +use frame_support::sp_runtime::{ + bounded_vec, + traits::{BlakeTwo256, IdentityLookup}, + BuildStorage, +}; +use frame_support::traits::{Contains, Everything}; +use frame_support::BoundedVec; +use frame_system::EnsureRoot; +use sp_core::H256; + +use crate::types::{AssetId, Balance, Price}; +pub type BlockNumber = u64; +pub type AccountId = u64; + +type Block = frame_system::mocking::MockBlock; + +use crate::MAX_PERIODS; + +pub const HDX: AssetId = 1_000; +pub const DOT: AssetId = 2_000; +pub const ACA: AssetId = 3_000; +// ensure this asset id is not used in the benchmarks, otherwise the benchmarking tests fail +pub const INSUFFICIENT_ASSET: AssetId = 123_456; + +pub const ORACLE_ENTRY_1: OracleEntry = OracleEntry { + price: Price::new(2_000, 1_000), + volume: Volume { + a_in: 1_000, + b_out: 500, + a_out: 0, + b_in: 0, + }, + liquidity: Liquidity::new(2_000, 1_000), + updated_at: 5, +}; +pub const ORACLE_ENTRY_2: OracleEntry = OracleEntry { + price: Price::new(4_000, 4_000), + volume: Volume { + a_in: 0, + b_out: 0, + a_out: 2_000, + b_in: 2_000, + }, + liquidity: Liquidity::new(4_000, 4_000), + updated_at: 5, +}; + +frame_support::construct_runtime!( + pub enum Test + { + System: frame_system, + EmaOracle: ema_oracle, + } + +); + +parameter_types! { + pub const BlockHashCount: BlockNumber = 250; +} + +impl frame_system::Config for Test { + type BaseCallFilter = Everything; + type BlockWeights = (); + type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; + type Nonce = u64; + type Block = Block; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; + type SingleBlockMigrations = (); + type MultiBlockMigrator = (); + type PreInherents = (); + type PostInherents = (); + type PostTransactions = (); + type ExtensionsWeightInfo = (); +} + +parameter_types! { + pub SupportedPeriods: BoundedVec> = bounded_vec![LastBlock, TenMinutes, Day, Week]; +} + +pub struct OracleWhitelist; +impl Contains<(Source, AssetId, AssetId)> for OracleWhitelist { + fn contains(t: &(Source, AssetId, AssetId)) -> bool { + (t.1 != INSUFFICIENT_ASSET && t.2 != INSUFFICIENT_ASSET) || ema_oracle::OracleWhitelist::::contains(t) + } +} + +impl Config for Test { + type RuntimeEvent = RuntimeEvent; + type AuthorityOrigin = EnsureRoot; + type BlockNumberProvider = System; + type SupportedPeriods = SupportedPeriods; + type OracleWhitelist = OracleWhitelist; + type MaxUniqueEntries = ConstU32<45>; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + type WeightInfo = (); +} + +pub type InitialDataEntry = (Source, (AssetId, AssetId), Price, Liquidity); + +#[derive(Default)] +pub struct ExtBuilder { + pub initial_data: Vec, +} + +impl ExtBuilder { + pub fn with_initial_data(mut self, data: Vec) -> Self { + self.initial_data = data; + self + } + + pub fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + crate::GenesisConfig:: { + initial_data: self.initial_data, + ..Default::default() + } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext: sp_io::TestExternalities = t.into(); + ext.execute_with(|| { + System::set_block_number(1); + }); + ext + } +} + +pub fn expect_events(e: Vec) { + test_utils::expect_events::(e); +} diff --git a/pallets/ema-oracle/src/tests/mod.rs b/pallets/ema-oracle/src/tests/mod.rs new file mode 100644 index 00000000000..b1e74f6c359 --- /dev/null +++ b/pallets/ema-oracle/src/tests/mod.rs @@ -0,0 +1,900 @@ +// This file is part of pallet-ema-oracle. + +// Copyright (C) 2022-2023 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod add_and_remove_oracle; +mod invariants; +mod mock; + +use super::*; +use crate::OraclePeriod::*; +pub use mock::{ + BlockNumber, EmaOracle, ExtBuilder, System, Test, ACA, DOT, HDX, INSUFFICIENT_ASSET, ORACLE_ENTRY_1, ORACLE_ENTRY_2, +}; + +use frame_support::{assert_noop, assert_ok, assert_storage_noop}; +use pretty_assertions::assert_eq; +use rug::Rational; + +/// Default oracle source for tests. +pub(crate) const SOURCE: Source = *b"dummysrc"; + +fn supported_periods() -> BoundedVec> { + ::SupportedPeriods::get() +} + +macro_rules! assert_price_approx_eq { + ($x:expr, $y:expr, $z:expr) => {{ + assert_price_approx_eq!($x, $y, $z, "not approximately equal"); + }}; + ($x:expr, $y:expr, $z:expr, $r:expr) => {{ + let x = Rational::from(Into::<(u128, u128)>::into($x)); + let y = Rational::from(Into::<(u128, u128)>::into($y)); + let z = Rational::from(Into::<(u128, u128)>::into($z)); + let diff = if x >= y { + x.clone() - y.clone() + } else { + y.clone() - x.clone() + }; + assert!( + diff <= z, + "\n{}\n left: {:?}\n right: {:?}\n diff: {:?}\nmax_diff: {:?}\n", + $r, + x, + y, + diff, + z + ); + }}; +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + ExtBuilder::default().build() +} + +/// Return the entry of an asset pair in the accumulator. +fn get_accumulator_entry(src: Source, (a, b): (AssetId, AssetId)) -> Option> { + let acc = Accumulator::::get(); + acc.get(&(src, ordered_pair(a, b))).cloned() +} + +fn get_oracle_entry(a: AssetId, b: AssetId, period: OraclePeriod) -> Option> { + Oracles::::get((SOURCE, ordered_pair(a, b), period)).map(|(e, _)| e) +} + +#[test] +fn genesis_config_works() { + ExtBuilder::default() + .with_initial_data(vec![ + ( + SOURCE, + (HDX, DOT), + (1_000_000, 1).into(), + Liquidity::new(2_000_000, 2_000_000_000), + ), + ( + SOURCE, + (HDX, ACA), + (3_000_000, 1).into(), + Liquidity::new(4_000_000, 4_000_000_000), + ), + ]) + .build() + .execute_with(|| { + for period in supported_periods() { + assert_eq!( + get_oracle_entry(HDX, DOT, period), + Some(OracleEntry { + price: Price::new(1_000_000, 1), + volume: Volume::default(), + liquidity: Liquidity::new(2_000_000, 2_000_000_000), + updated_at: 0, + }) + ); + + assert_eq!( + get_oracle_entry(HDX, ACA, period), + Some(OracleEntry { + price: Price::new(3_000_000, 1), + volume: Volume::default(), + liquidity: Liquidity::new(4_000_000, 4_000_000_000), + updated_at: 0, + }) + ); + } + }); +} + +#[test] +fn on_trade_should_work() { + new_test_ext().execute_with(|| { + assert_eq!(get_accumulator_entry(SOURCE, (HDX, DOT)), None); + assert_ok!(EmaOracle::on_trade(SOURCE, ordered_pair(HDX, DOT), ORACLE_ENTRY_1)); + assert_ok!(EmaOracle::on_trade(SOURCE, ordered_pair(HDX, DOT), ORACLE_ENTRY_2)); + let price_entry = ORACLE_ENTRY_2.with_added_volume_from(&ORACLE_ENTRY_1); + assert_eq!(get_accumulator_entry(SOURCE, (HDX, DOT)).unwrap(), price_entry); + }); +} + +#[test] +fn on_trade_handler_should_work() { + new_test_ext().execute_with(|| { + System::set_block_number(5); + assert_eq!(get_accumulator_entry(SOURCE, (HDX, DOT)), None); + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, + HDX, + DOT, + 1_000, + 500, + 2_000, + 1_000, + Price::new(2_000, 1_000), + )); + let expected = OracleEntry { + price: Price::new(2_000, 1_000), + volume: Volume::from_a_in_b_out(1_000, 500), + liquidity: Liquidity::new(2_000, 1_000), + updated_at: 5, + }; + assert_eq!(get_accumulator_entry(SOURCE, (HDX, DOT)), Some(expected)); + }); +} + +#[test] +fn on_liquidity_changed_handler_should_work() { + new_test_ext().execute_with(|| { + let updated_at = 5; + System::set_block_number(updated_at); + let no_volume_entry = OracleEntry { + price: Price::new(2_000, 1_000), + volume: Volume::default(), + liquidity: Liquidity::new(2_000, 1_000), + updated_at, + }; + assert_eq!(get_accumulator_entry(SOURCE, (HDX, DOT)), None); + assert_ok!(OnActivityHandler::::on_liquidity_changed( + SOURCE, + HDX, + DOT, + 1_000, + 500, + 2_000, + 1_000, + Price::new(2_000, 1_000), + )); + assert_eq!(get_accumulator_entry(SOURCE, (HDX, DOT)), Some(no_volume_entry)); + }); +} + +#[test] +fn price_should_be_determined_from_liquidity() { + new_test_ext().execute_with(|| { + assert_eq!(get_accumulator_entry(SOURCE, (HDX, DOT)), None); + assert_ok!(OnActivityHandler::::on_liquidity_changed( + SOURCE, + HDX, + DOT, + 5, + 1, + 2_000_000, + 1_000_000, + Price::new(2_000_000, 1_000_000), + )); + let expected = Price::new(2_000_000, 1_000_000); + assert_eq!(get_accumulator_entry(SOURCE, (HDX, DOT)).unwrap().price, expected); + + assert_eq!(get_accumulator_entry(SOURCE, (DOT, ACA)), None); + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, + DOT, + ACA, + 1234, + 789, + 5_000_000, + 500, + Price::new(5_000_000, 500), + )); + let expected = Price::new(5_000_000, 500); + assert_eq!(get_accumulator_entry(SOURCE, (DOT, ACA)).unwrap().price, expected); + }); +} + +#[test] +fn on_liquidity_changed_should_allow_zero_values() { + let updated_at = 5; + let (liquidity_a, liquidity_b) = (2_000, 1_000); + let amount = 1_000; + + new_test_ext().execute_with(|| { + System::set_block_number(updated_at); + assert_ok!(OnActivityHandler::::on_liquidity_changed( + SOURCE, + HDX, + DOT, + Balance::zero(), + amount, + liquidity_a, + liquidity_b, + Price::new(liquidity_a, liquidity_b), + )); + let only_liquidity_entry = OracleEntry { + price: Price::new(liquidity_a, liquidity_b), + volume: Volume::default(), + liquidity: (liquidity_a, liquidity_b).into(), + updated_at, + }; + assert_eq!(get_accumulator_entry(SOURCE, (HDX, DOT)), Some(only_liquidity_entry)); + }); + + new_test_ext().execute_with(|| { + System::set_block_number(updated_at); + assert_ok!(OnActivityHandler::::on_liquidity_changed( + SOURCE, + HDX, + DOT, + amount, + Balance::zero(), + liquidity_a, + liquidity_b, + Price::new(liquidity_a, liquidity_b), + )); + let only_liquidity_entry = OracleEntry { + price: Price::new(liquidity_a, liquidity_b), + volume: Volume::default(), + liquidity: (liquidity_a, liquidity_b).into(), + updated_at, + }; + assert_eq!(get_accumulator_entry(SOURCE, (HDX, DOT)), Some(only_liquidity_entry)); + }); + + new_test_ext().execute_with(|| { + System::set_block_number(updated_at); + assert_ok!(OnActivityHandler::::on_liquidity_changed( + SOURCE, + HDX, + DOT, + amount, + amount, + Balance::zero(), + Balance::zero(), + Price::zero(), + )); + let only_price_entry = OracleEntry { + price: Price::zero(), + volume: Volume::default(), + liquidity: (Balance::zero(), Balance::zero()).into(), + updated_at, + }; + assert_eq!(get_accumulator_entry(SOURCE, (HDX, DOT)), Some(only_price_entry)); + }); +} + +#[test] +fn on_liquidity_changed_should_exclude_insufficient_assets() { + new_test_ext().execute_with(|| { + // first asset is insufficient + assert_storage_noop!(OnActivityHandler::::on_liquidity_changed( + SOURCE, + INSUFFICIENT_ASSET, + DOT, + 1_000, + 500, + 2_000, + 1_000, + Price::new(2_000, 1_000), + ) + .unwrap()); + }); + + // second asset is insufficient + new_test_ext().execute_with(|| { + assert_storage_noop!(OnActivityHandler::::on_liquidity_changed( + SOURCE, + HDX, + INSUFFICIENT_ASSET, + 1_000, + 500, + 2_000, + 1_000, + Price::new(2_000, 1_000), + ) + .unwrap()); + }); + + // both assets are insufficient + new_test_ext().execute_with(|| { + assert_storage_noop!(OnActivityHandler::::on_liquidity_changed( + SOURCE, + INSUFFICIENT_ASSET, + INSUFFICIENT_ASSET, + 1_000, + 500, + 2_000, + 1_000, + Price::new(2_000, 1_000), + ) + .unwrap()); + }); +} + +#[test] +fn on_trade_should_exclude_zero_values() { + new_test_ext().execute_with(|| { + assert_noop!( + OnActivityHandler::::on_trade(SOURCE, HDX, DOT, 1_000, 1_000, Balance::zero(), 1_000, Price::zero()) + .map_err(|(_w, e)| e), + Error::::OnTradeValueZero + ); + + assert_noop!( + OnActivityHandler::::on_trade(SOURCE, HDX, DOT, 1_000, 1_000, 2_000, Balance::zero(), Price::zero()) + .map_err(|(_w, e)| e), + Error::::OnTradeValueZero + ); + }); +} + +#[test] +fn on_trade_should_exclude_insufficient_assets() { + new_test_ext().execute_with(|| { + // first asset is insufficient + assert_storage_noop!(OnActivityHandler::::on_trade( + SOURCE, + INSUFFICIENT_ASSET, + DOT, + 1_000, + 500, + 2_000, + 1_000, + Price::new(2_000, 1_000) + ) + .unwrap()); + + // second asset is insufficient + assert_storage_noop!(OnActivityHandler::::on_trade( + SOURCE, + HDX, + INSUFFICIENT_ASSET, + 1_000, + 500, + 2_000, + 1_000, + Price::new(2_000, 1_000) + ) + .unwrap()); + + // both assets are insufficient + assert_storage_noop!(OnActivityHandler::::on_trade( + SOURCE, + INSUFFICIENT_ASSET, + INSUFFICIENT_ASSET, + 1_000, + 500, + 2_000, + 1_0000, + Price::new(2_000, 1_000) + ) + .unwrap()); + }); +} + +#[test] +fn on_entry_should_error_on_accumulator_overflow() { + new_test_ext().execute_with(|| { + let max_entries = <::MaxUniqueEntries as Get>::get(); + // let's fill the accumulator + for i in 0..max_entries { + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, + i, + i + 1, + 1_000, + 1_000, + 2_000, + 2_000, + Price::new(2_000, 2_000), + )); + } + // on_trade should fail once the accumulator is full + assert_noop!( + OnActivityHandler::::on_trade( + SOURCE, + 2 * max_entries, + 2 * max_entries + 1, + 1_000, + 1_000, + 2_000, + 2_000, + Price::new(2_000, 2_000), + ) + .map_err(|(_w, e)| e), + Error::::TooManyUniqueEntries + ); + }); +} + +#[test] +fn volume_normalization_should_factor_in_asset_order() { + assert_ne!( + determine_normalized_volume(HDX, DOT, 1_000, 500), + determine_normalized_volume(DOT, HDX, 500, 1_000) + ); +} + +#[test] +fn liquidity_normalization_should_factor_in_asset_order() { + assert_ne!( + determine_normalized_liquidity(HDX, DOT, 1_000, 500), + determine_normalized_liquidity(DOT, HDX, 1_000, 500) + ); +} + +#[test] +fn oracle_volume_should_factor_in_asset_order() { + new_test_ext().execute_with(|| { + assert_eq!(get_accumulator_entry(SOURCE, (HDX, DOT)), None); + + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, + HDX, + DOT, + 2_000_000, + 1_000, + 2_000, + 1, + Price::new(2_000, 1), + )); + // we reverse the order of the arguments + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, + DOT, + HDX, + 1_000, + 2_000_000, + 1, + 2_000, + Price::new(1, 2_000), + )); + + let price_entry = get_accumulator_entry(SOURCE, (HDX, DOT)).unwrap(); + let first_entry = OracleEntry { + price: Price::new(2_000, 1), + volume: Volume::from_a_in_b_out(2_000_000, 1_000), + liquidity: (2_000, 1).into(), + updated_at: 1, + }; + let second_entry = OracleEntry { + price: Price::new(2_000, 1), + volume: Volume::from_a_out_b_in(2_000_000, 1_000), + liquidity: (2_000, 1).into(), + updated_at: 1, + }; + + let result = second_entry.with_added_volume_from(&first_entry); + assert_eq!(price_entry, result); + }); +} + +#[test] +fn update_data_should_work() { + new_test_ext().execute_with(|| { + System::set_block_number(5); + EmaOracle::on_initialize(5); + + assert_ok!(EmaOracle::on_trade(SOURCE, ordered_pair(HDX, DOT), ORACLE_ENTRY_1)); + assert_ok!(EmaOracle::on_trade(SOURCE, ordered_pair(HDX, DOT), ORACLE_ENTRY_2)); + assert_ok!(EmaOracle::on_trade(SOURCE, ordered_pair(HDX, ACA), ORACLE_ENTRY_1)); + + EmaOracle::on_finalize(5); + System::set_block_number(6); + EmaOracle::on_initialize(6); + + for period in supported_periods() { + assert_eq!( + get_oracle_entry(HDX, DOT, period), + Some(ORACLE_ENTRY_2.with_added_volume_from(&ORACLE_ENTRY_1)), + ); + assert_eq!(get_oracle_entry(HDX, ACA, period), Some(ORACLE_ENTRY_1),); + } + }); +} + +#[test] +fn update_data_should_use_old_last_block_oracle_to_update_to_parent() { + new_test_ext().execute_with(|| { + System::set_block_number(5); + EmaOracle::on_initialize(5); + assert_ok!(EmaOracle::on_trade(SOURCE, ordered_pair(HDX, DOT), ORACLE_ENTRY_1)); + EmaOracle::on_finalize(5); + + System::set_block_number(6); + EmaOracle::on_initialize(6); + let second_entry = OracleEntry { + liquidity: Liquidity::new(3_000, 1_500), + updated_at: 6, + ..ORACLE_ENTRY_1 + }; + assert_ok!(EmaOracle::on_trade( + SOURCE, + ordered_pair(HDX, DOT), + second_entry.clone() + )); + EmaOracle::on_finalize(6); + + System::set_block_number(50); + EmaOracle::on_initialize(50); + let third_entry = OracleEntry { + liquidity: Liquidity::new(10, 5), + updated_at: 50, + ..ORACLE_ENTRY_1 + }; + assert_ok!(EmaOracle::on_trade(SOURCE, ordered_pair(HDX, DOT), third_entry.clone())); + EmaOracle::on_finalize(50); + + for period in supported_periods() { + let second_at_50 = OracleEntry { + updated_at: 49, + volume: Volume::default(), + ..second_entry.clone() + }; + let mut expected = ORACLE_ENTRY_1.clone(); + expected + .update_to_new_by_integrating_incoming(period, &second_entry) + .unwrap() + .update_outdated_to_current(period, &second_at_50) + .unwrap() + .update_to_new_by_integrating_incoming(period, &third_entry) + .unwrap(); + assert_eq!( + get_oracle_entry(HDX, DOT, period).unwrap(), + expected, + "Oracle entry should be updated correctly for {:?}", + period + ); + } + }); +} + +#[test] +fn calculate_new_by_integrating_incoming_only_updates_updated_at_on_stable_values() { + let period = TenMinutes; + let start_oracle = OracleEntry { + price: Price::new(4, 1), + volume: Volume::from_a_in_b_out(1, 4), + liquidity: Liquidity::new(4, 1), + updated_at: 5_u32, + }; + let next_value = OracleEntry { + updated_at: 6, + ..start_oracle.clone() + }; + let next_oracle = start_oracle.calculate_new_by_integrating_incoming(period, &next_value); + assert_eq!(next_oracle, Some(next_value)); +} + +#[test] +fn calculate_new_by_integrating_incoming_with_works() { + let start_oracle = OracleEntry { + price: Price::new(50, 1), + volume: Volume::from_a_in_b_out(1, 50), + liquidity: Liquidity::new(50, 1), + updated_at: 5_u32, + }; + + let next_value = OracleEntry { + price: Price::new(151, 1), + volume: Volume::from_a_in_b_out(1, 151), + liquidity: Liquidity::new(151, 1), + updated_at: 6, + }; + let next_oracle = start_oracle + .calculate_new_by_integrating_incoming(TenMinutes, &next_value) + .unwrap(); + // ten minutes corresponds to 100 blocks which corresponds to a smoothing factor of + // `2 / 101 ≈ 1 / 50` which means that for an update from 50 to 151 we expect an update of + // about 2 + let expected_oracle = OracleEntry { + price: Price::new(52, 1), + volume: Volume::from_a_in_b_out(1, 52), + liquidity: Liquidity::new(52, 1), + updated_at: 6, + }; + let tolerance = Price::new(1, 1e10 as u128); + assert_price_approx_eq!(next_oracle.price, expected_oracle.price, tolerance); + assert_eq!(next_oracle.volume, expected_oracle.volume); + assert_eq!(next_oracle.liquidity, expected_oracle.liquidity); + assert_eq!(next_oracle.updated_at, expected_oracle.updated_at); +} + +#[test] +fn calculate_new_by_integrating_incoming_last_block_period_returns_new_value() { + let start_oracle = OracleEntry { + price: Price::new(4, 1), + volume: Volume::from_a_in_b_out(1_u128, 4_u128), + liquidity: Liquidity::new(4_u128, 1_u128), + updated_at: 5_u32, + }; + + let next_value = OracleEntry { + price: Price::new(8, 1), + volume: Volume::from_a_in_b_out(1_u128, 8_u128), + liquidity: Liquidity::new(8_u128, 1_u128), + updated_at: 6, + }; + let next_oracle = start_oracle.calculate_new_by_integrating_incoming(LastBlock, &next_value); + let expected_oracle = next_value; + assert_eq!(next_oracle, Some(expected_oracle)); +} + +#[test] +fn calculate_current_from_outdated_should_incorporate_longer_time_deltas() { + let period = TenMinutes; + let start_oracle = OracleEntry { + price: Price::new(4_000, 1), + volume: Volume::from_a_in_b_out(1, 4_000), + liquidity: Liquidity::new(4_000, 1), + updated_at: 5_u32, + }; + let next_value = OracleEntry { + price: Price::new(8_000, 1), + volume: Volume::from_a_in_b_out(1, 8_000), + liquidity: Liquidity::new(8_000, 1), + updated_at: 1_000, + }; + let next_oracle = start_oracle + .calculate_current_from_outdated(period, &next_value) + .unwrap(); + assert_price_approx_eq!( + next_oracle.price, + next_value.price, + (1, 10_000), + "Oracle price deviates too much." + ); +} + +#[test] +fn get_price_works() { + ExtBuilder::default() + .with_initial_data(vec![( + SOURCE, + (HDX, DOT), + (1_000_000, 1).into(), + Liquidity::new(2_000_000, 2), + )]) + .build() + .execute_with(|| { + System::set_block_number(2); + let expected = ((1_000_000, 1).into(), 1); + assert_eq!(EmaOracle::get_price(HDX, DOT, LastBlock, SOURCE), Ok(expected)); + assert_eq!(EmaOracle::get_price(HDX, DOT, TenMinutes, SOURCE), Ok(expected)); + assert_eq!(EmaOracle::get_price(HDX, DOT, Day, SOURCE), Ok(expected)); + assert_eq!(EmaOracle::get_price(HDX, DOT, Week, SOURCE), Ok(expected)); + }); +} + +#[test] +fn trying_to_get_price_for_same_asset_should_error() { + ExtBuilder::default() + .with_initial_data(vec![( + SOURCE, + (HDX, DOT), + (1_000_000, 1).into(), + Liquidity::new(2_000_000, 2), + )]) + .build() + .execute_with(|| { + System::set_block_number(2); + assert_eq!( + EmaOracle::get_price(HDX, HDX, LastBlock, SOURCE), + Err(OracleError::SameAsset), + ); + }); +} + +#[test] +fn get_entry_works() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_ok!(OnActivityHandler::::on_trade( + SOURCE, + HDX, + DOT, + 1_000, + 500, + 2_000, + 1_000, + Price::new(2_000, 1_000), + )); + EmaOracle::on_finalize(1); + System::set_block_number(100); + let expected = AggregatedEntry { + price: Price::new(2_000, 1_000), + volume: Volume::default(), // volume for new blocks is zero by default + liquidity: Liquidity::new(2_000, 1_000), + oracle_age: 98, + }; + assert_eq!(EmaOracle::get_entry(HDX, DOT, LastBlock, SOURCE), Ok(expected)); + + let expected_ten_min = AggregatedEntry { + price: Price::new(2_000, 1_000), + volume: Volume::from_a_in_b_out(141, 70), // volume oracle gets updated towards zero + liquidity: Liquidity::new(2_000, 1_000), + oracle_age: 98, + }; + assert_eq!(EmaOracle::get_entry(HDX, DOT, TenMinutes, SOURCE), Ok(expected_ten_min)); + + let expected_day = AggregatedEntry { + price: Price::new(2_000, 1_000), + volume: Volume::from_a_in_b_out(986, 493), + liquidity: Liquidity::new(2_000, 1_000), + oracle_age: 98, + }; + assert_eq!(EmaOracle::get_entry(HDX, DOT, Day, SOURCE), Ok(expected_day)); + + let expected_week = AggregatedEntry { + price: Price::new(2_000, 1_000), + volume: Volume::from_a_in_b_out(998, 499), + liquidity: Liquidity::new(2_000, 1_000), + oracle_age: 98, + }; + assert_eq!(EmaOracle::get_entry(HDX, DOT, Week, SOURCE), Ok(expected_week)); + }); +} + +#[test] +fn get_price_returns_updated_price() { + ExtBuilder::default() + .with_initial_data(vec![( + SOURCE, + (HDX, DOT), + (1_000_000, 1).into(), + Liquidity::new(2_000_000, 2), + )]) + .build() + .execute_with(|| { + let on_trade_entry = OracleEntry { + price: Price::new(500_000, 1), + volume: Volume::default(), + liquidity: Liquidity::new(2_000_000, 2), + updated_at: 1, + }; + System::set_block_number(1); + assert_ok!(EmaOracle::on_trade(SOURCE, ordered_pair(HDX, DOT), on_trade_entry)); + EmaOracle::on_finalize(1); + + System::set_block_number(10_001); + + assert_eq!( + EmaOracle::get_price(HDX, DOT, LastBlock, SOURCE).unwrap().1, + 10_000, + "Oracle should be 10_000 blocks old." + ); + assert_eq!( + EmaOracle::get_price(HDX, DOT, Day, SOURCE).unwrap().1, + 10_000, + "Oracle should be 10_000 blocks old." + ); + + let tolerance = (1, 1_000); + assert_price_approx_eq!( + EmaOracle::get_price(HDX, DOT, LastBlock, SOURCE).unwrap().0, + Price::new(500_000, 1), + tolerance, + "LastBlock Oracle should have most recent value." + ); + assert_price_approx_eq!( + EmaOracle::get_price(HDX, DOT, TenMinutes, SOURCE).unwrap().0, + Price::new(500_000, 1), + tolerance, + "TenMinutes Oracle should converge within 1000 blocks." + ); + assert_price_approx_eq!( + EmaOracle::get_price(HDX, DOT, Day, SOURCE).unwrap().0, + Price::new(6_246_761_041_102_896_u128, 10_000_000_000), + tolerance, + "Day Oracle should converge somewhat." + ); + assert_price_approx_eq!( + EmaOracle::get_price(HDX, DOT, Week, SOURCE).unwrap().0, + Price::new(9_100_156_788_246_781_u128, 10_000_000_000), + tolerance, + "Week Oracle should converge a little." + ); + }); +} + +#[test] +fn ema_update_should_return_none_if_new_entry_is_older() { + let mut entry = OracleEntry { + updated_at: 10, + ..ORACLE_ENTRY_1 + }; + let original = entry.clone(); + // older than current + let outdated_entry = OracleEntry { + updated_at: 9, + ..ORACLE_ENTRY_2 + }; + assert_eq!(entry.calculate_current_from_outdated(TenMinutes, &outdated_entry), None); + assert_eq!(entry.calculate_current_from_outdated(LastBlock, &outdated_entry), None); + assert_eq!( + entry.calculate_new_by_integrating_incoming(TenMinutes, &outdated_entry), + None + ); + assert_eq!( + entry.calculate_new_by_integrating_incoming(LastBlock, &outdated_entry), + None + ); + // same updated_at as current + let outdated_entry = OracleEntry { + updated_at: 10, + ..ORACLE_ENTRY_2 + }; + assert_eq!(entry.calculate_current_from_outdated(TenMinutes, &outdated_entry), None); + assert_eq!(entry.calculate_current_from_outdated(LastBlock, &outdated_entry), None); + assert_eq!( + entry.calculate_new_by_integrating_incoming(TenMinutes, &outdated_entry), + None + ); + assert_eq!( + entry.calculate_new_by_integrating_incoming(LastBlock, &outdated_entry), + None + ); + + assert_eq!( + entry.update_to_new_by_integrating_incoming(TenMinutes, &outdated_entry), + None + ); + assert_eq!(entry, original); + assert_eq!(entry.update_outdated_to_current(TenMinutes, &outdated_entry), None); + assert_eq!(entry, original); +} + +#[test] +fn check_period_smoothing_factors() { + use hydra_dx_math::ema::smoothing_from_period; + + // We assume a 6 second block time. + let secs_per_block = 6; + let minutes = 60 / secs_per_block; + let hours = 60 * minutes; + let days = 24 * hours; + + let last_block = smoothing_from_period(1); + println!("Last Block: {} (bits: {})", last_block, last_block.to_bits()); + assert_eq!(into_smoothing(LastBlock), last_block); + + let short = smoothing_from_period(9); + println!("Short: {} (bits: {})", short, short.to_bits()); + assert_eq!(into_smoothing(Short), short); + + let ten_minutes = smoothing_from_period(10 * minutes); + println!("Ten Minutes: {} (bits: {})", ten_minutes, ten_minutes.to_bits()); + assert_eq!(into_smoothing(TenMinutes), ten_minutes); + + let hour = smoothing_from_period(hours); + println!("Hour: {} (bits: {})", hour, hour.to_bits()); + assert_eq!(into_smoothing(Hour), hour); + + let day = smoothing_from_period(days); + println!("Day: {} (bits: {})", day, day.to_bits()); + assert_eq!(into_smoothing(Day), day); + + let week = smoothing_from_period(7 * days); + println!("Week: {} (bits: {})", week, week.to_bits()); + assert_eq!(into_smoothing(Week), week); +} diff --git a/pallets/ema-oracle/src/types.rs b/pallets/ema-oracle/src/types.rs new file mode 100644 index 00000000000..a2c0be1decd --- /dev/null +++ b/pallets/ema-oracle/src/types.rs @@ -0,0 +1,229 @@ +// This file is part of pallet-ema-oracle. + +// Copyright (C) 2022-2023 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use basilisk_math::ema::{calculate_new_by_integrating_incoming, update_outdated_to_current, EmaPrice}; +use basilisk_traits::oracle::{AggregatedEntry, Liquidity, Volume}; +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::sp_runtime::RuntimeDebug; +use hydra_dx_math::types::Fraction; +use scale_info::TypeInfo; +use sp_arithmetic::traits::{AtLeast32BitUnsigned, SaturatedConversion, UniqueSaturatedInto}; + +pub use basilisk_traits::oracle::{OraclePeriod, Source}; + +use sp_std::prelude::*; + +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; + +pub type AssetId = u32; +pub type Balance = u128; +/// A price is a tuple of two `u128`s representing the numerator and denominator of a rational number. +pub type Price = EmaPrice; + +/// A type representing data produced by a trade or liquidity event. +/// Includes the block number where it was created/updated. +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq, Default, TypeInfo, MaxEncodedLen)] +pub struct OracleEntry { + pub price: Price, + pub volume: Volume, + pub liquidity: Liquidity, + pub updated_at: BlockNumber, +} + +impl OracleEntry { + /// Construct a new `OracleEntry`. + pub const fn new( + price: Price, + volume: Volume, + liquidity: Liquidity, + updated_at: BlockNumber, + ) -> Self { + Self { + price, + volume, + liquidity, + updated_at, + } + } +} + +impl OracleEntry +where + BlockNumber: AtLeast32BitUnsigned + Copy + UniqueSaturatedInto, +{ + /// Convert the `OracleEntry` into an `AggregatedEntry` for consumption. Determines the age by + /// subtracting `initialized` from `self.updated_at`. + pub fn into_aggregated(self, initialized: BlockNumber) -> AggregatedEntry { + AggregatedEntry { + price: self.price, + volume: self.volume, + liquidity: self.liquidity, + oracle_age: self.updated_at.saturating_sub(initialized), + } + } + + /// Return the raw data of the entry as a tuple of tuples, excluding the block number. + pub fn raw_data(&self) -> (Price, (Balance, Balance, Balance, Balance), (Balance, Balance)) { + (self.price, self.volume.clone().into(), self.liquidity.into()) + } + + /// Return an inverted version of the entry where the meaning of assets a and b are inverted. + /// So the price of a/b become the price b/a and the volume switches correspondingly. + pub fn inverted(self) -> Self { + let price = self.price.inverted(); + let volume = self.volume.inverted(); + let liquidity = self.liquidity.inverted(); + Self { + price, + volume, + liquidity, + updated_at: self.updated_at, + } + } + + /// Update the volume in `self` by adding in the volume of `incoming` and taking over the other + /// values from `incoming`. + pub fn accumulate_volume_and_update_from(&mut self, incoming: &Self) { + self.volume = incoming.volume.saturating_add(&self.volume); + self.price = incoming.price; + self.liquidity = incoming.liquidity; + self.updated_at = incoming.updated_at; + } + + /// Fast forward the oracle value to `new_updated_at`. Updates the block number and resets the volume. + pub fn fast_forward_to(&mut self, new_updated_at: BlockNumber) { + self.updated_at = new_updated_at; + self.volume = Volume::default(); + } + + /// Determine a new entry based on `self` and a previous entry. Adds the volumes together and + /// takes the values of `self` for the rest. + pub fn with_added_volume_from(&self, previous_entry: &Self) -> Self { + let volume = previous_entry.volume.saturating_add(&self.volume); + Self { + price: self.price, + volume, + liquidity: self.liquidity, + updated_at: self.updated_at, + } + } + + /// Determine the next oracle entry based on a previous (`self`) and an `incoming` entry as well as + /// a `period`. + /// + /// Returns `None` if any of the calculations fail (including the `incoming` entry not being + /// one iteration (block) more recent than `self`). + /// + /// The period is used to determine the smoothing factor alpha for an exponential moving average. + pub fn calculate_new_by_integrating_incoming(&self, period: OraclePeriod, incoming: &Self) -> Option { + // incoming should be one step ahead of the previous value + if !incoming.updated_at.checked_sub(&self.updated_at)?.is_one() { + return None; + } + if period == OraclePeriod::LastBlock { + return Some(incoming.clone()); + } + // determine smoothing factor + let smoothing = into_smoothing(period); + let (price, volume, liquidity) = + calculate_new_by_integrating_incoming(self.raw_data(), incoming.raw_data(), smoothing); + + Some(Self { + price, + volume: volume.into(), + liquidity: liquidity.into(), + updated_at: incoming.updated_at, + }) + } + + /// Update `self` based on a previous (`self`) and an `incoming` oracle entry as well as a `period`. + pub fn update_to_new_by_integrating_incoming( + &mut self, + period: OraclePeriod, + incoming: &Self, + ) -> Option<&mut Self> { + *self = self.calculate_new_by_integrating_incoming(period, incoming)?; + Some(self) + } + + /// Determine the current intended oracle entry based on a previous (`self`) and an `update_with` entry as well as + /// a `period`. + /// + /// Returns `None` if any of the calculations fail (including the `update_with` entry not being + /// more recent than `self`). + /// + /// The period is used to determine the smoothing factor alpha for an exponential moving average. + /// + /// Uses the difference between `updated_at` to determine the time (i.e. iterations) to cover. + pub fn calculate_current_from_outdated(&self, period: OraclePeriod, update_with: &Self) -> Option { + let iterations = update_with.updated_at.checked_sub(&self.updated_at)?; + if iterations.is_zero() { + return None; + } + if period == OraclePeriod::LastBlock { + return Some(update_with.clone()); + } + // determine smoothing factor + let smoothing = into_smoothing(period); + let (price, volume, liquidity) = update_outdated_to_current( + iterations.saturated_into(), + self.raw_data(), + (update_with.price, update_with.liquidity.into()), + smoothing, + ); + + Some(Self { + price, + volume: volume.into(), + liquidity: liquidity.into(), + updated_at: update_with.updated_at, + }) + } + + /// Update `self` based on a previous (`self`) and an `update_with` entry as well as a `period`. + /// See [`calculate_current_from_outdated`]. + pub fn update_outdated_to_current(&mut self, period: OraclePeriod, update_with: &Self) -> Option<&mut Self> { + *self = self.calculate_current_from_outdated(period, update_with)?; + Some(self) + } +} + +/// Convert a given `period` into the smoothing factor used in the weighted average. +/// See [`check_period_smoothing_factors`] for how the values are generated. +pub fn into_smoothing(period: OraclePeriod) -> Fraction { + match period { + OraclePeriod::LastBlock => Fraction::from_bits(170141183460469231731687303715884105728), + OraclePeriod::Short => Fraction::from_bits(34028236692093846346337460743176821146), + OraclePeriod::TenMinutes => Fraction::from_bits(3369132345751865974884897103284833777), + OraclePeriod::Hour => Fraction::from_bits(566193622164623067326746434994622648), + OraclePeriod::Day => Fraction::from_bits(23629079016800115510268356880200556), + OraclePeriod::Week => Fraction::from_bits(3375783642235081630771268215908257), + } +} + +impl From<(Price, Volume, Liquidity, BlockNumber)> for OracleEntry { + fn from((price, volume, liquidity, updated_at): (Price, Volume, Liquidity, BlockNumber)) -> Self { + Self { + price, + volume, + liquidity, + updated_at, + } + } +} diff --git a/pallets/ema-oracle/src/weights.rs b/pallets/ema-oracle/src/weights.rs new file mode 100644 index 00000000000..19aa0e85af2 --- /dev/null +++ b/pallets/ema-oracle/src/weights.rs @@ -0,0 +1,122 @@ +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_ema_oracle. +pub trait WeightInfo { + fn add_oracle() -> Weight; + fn remove_oracle() -> Weight; + fn on_finalize_no_entry() -> Weight; + fn on_finalize_multiple_tokens(b: u32) -> Weight; + fn on_trade_multiple_tokens(b: u32) -> Weight; + fn on_liquidity_changed_multiple_tokens(b: u32) -> Weight; + fn get_entry() -> Weight; +} + +/// Weights for `pallet_ema_oracle` using the HydraDX node and recommended hardware. +impl WeightInfo for () { + /// Storage: `EmaOracle::WhitelistedAssets` (r:1 w:1) + /// Proof: `EmaOracle::WhitelistedAssets` (`max_values`: Some(1), `max_size`: Some(641), added: 1136, mode: `MaxEncodedLen`) + fn add_oracle() -> Weight { + // Proof Size summary in bytes: + // Measured: `860` + // Estimated: `2126` + // Minimum execution time: 18_453_000 picoseconds. + Weight::from_parts(18_728_000, 2126) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `EmaOracle::WhitelistedAssets` (r:1 w:1) + /// Proof: `EmaOracle::WhitelistedAssets` (`max_values`: Some(1), `max_size`: Some(641), added: 1136, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::Accumulator` (r:1 w:1) + /// Proof: `EmaOracle::Accumulator` (`max_values`: Some(1), `max_size`: Some(5921), added: 6416, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::Oracles` (r:0 w:3) + /// Proof: `EmaOracle::Oracles` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + fn remove_oracle() -> Weight { + // Proof Size summary in bytes: + // Measured: `876` + // Estimated: `7406` + // Minimum execution time: 35_110_000 picoseconds. + Weight::from_parts(35_479_000, 7406) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) + } + /// Storage: `EmaOracle::Accumulator` (r:1 w:0) + /// Proof: `EmaOracle::Accumulator` (`max_values`: Some(1), `max_size`: Some(5921), added: 6416, mode: `MaxEncodedLen`) + fn on_finalize_no_entry() -> Weight { + // Proof Size summary in bytes: + // Measured: `208` + // Estimated: `7406` + // Minimum execution time: 3_428_000 picoseconds. + Weight::from_parts(3_551_000, 7406) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `EmaOracle::Accumulator` (r:1 w:1) + /// Proof: `EmaOracle::Accumulator` (`max_values`: Some(1), `max_size`: Some(5921), added: 6416, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::Oracles` (r:117 w:117) + /// Proof: `EmaOracle::Oracles` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// The range of component `b` is `[1, 39]`. + fn on_finalize_multiple_tokens(b: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `305 + b * (626 ±0)` + // Estimated: `7406 + b * (7956 ±0)` + // Minimum execution time: 50_796_000 picoseconds. + Weight::from_parts(13_853_333, 7406) + // Standard Error: 19_995 + .saturating_add(Weight::from_parts(36_619_947, 0).saturating_mul(b.into())) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(b.into()))) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(b.into()))) + .saturating_add(Weight::from_parts(0, 7956).saturating_mul(b.into())) + } + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::Accumulator` (r:1 w:1) + /// Proof: `EmaOracle::Accumulator` (`max_values`: Some(1), `max_size`: Some(5921), added: 6416, mode: `MaxEncodedLen`) + /// The range of component `b` is `[1, 39]`. + fn on_trade_multiple_tokens(b: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `821 + b * (164 ±0)` + // Estimated: `7406` + // Minimum execution time: 21_833_000 picoseconds. + Weight::from_parts(22_673_078, 7406) + // Standard Error: 3_367 + .saturating_add(Weight::from_parts(503_352, 0).saturating_mul(b.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::Accumulator` (r:1 w:1) + /// Proof: `EmaOracle::Accumulator` (`max_values`: Some(1), `max_size`: Some(5921), added: 6416, mode: `MaxEncodedLen`) + /// The range of component `b` is `[1, 39]`. + fn on_liquidity_changed_multiple_tokens(b: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `821 + b * (164 ±0)` + // Estimated: `7406` + // Minimum execution time: 22_117_000 picoseconds. + Weight::from_parts(22_701_600, 7406) + // Standard Error: 3_410 + .saturating_add(Weight::from_parts(500_409, 0).saturating_mul(b.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `EmaOracle::Oracles` (r:2 w:0) + /// Proof: `EmaOracle::Oracles` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + fn get_entry() -> Weight { + // Proof Size summary in bytes: + // Measured: `638` + // Estimated: `6294` + // Minimum execution time: 21_346_000 picoseconds. + Weight::from_parts(21_721_000, 6294) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + } +} diff --git a/pallets/lbp/Cargo.toml b/pallets/lbp/Cargo.toml new file mode 100644 index 00000000000..ab58a5fdfe7 --- /dev/null +++ b/pallets/lbp/Cargo.toml @@ -0,0 +1,74 @@ +[package] +name = "pallet-lbp" +version = "4.11.0" +description = "HydraDX Liquidity Bootstrapping Pool Pallet" +authors = ["GalacticCouncil"] +edition = "2021" +homepage = "https://github.com/galacticcouncil/hydradx-node" +license = "Apache 2.0" +repository = "https://github.com/galacticcouncil/hydradx-node" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[build-dependencies] +substrate-wasm-builder = { workspace = true } + +[dependencies] +codec = { workspace = true } +scale-info = { workspace = true } +primitive-types = { workspace = true } +serde = { workspace = true, optional = true } + +basilisk-traits = { workspace = true } + +# HydraDX dependencies +hydra-dx-math = { workspace = true } +hydradx-traits = { workspace = true } +pallet-broadcast = { workspace = true } + +## ORML dependencies +orml-traits = { workspace = true } + +## Substrate dependencies +frame-benchmarking = { workspace = true, optional = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +sp-std = { workspace = true } + +# Needed for benchmarks +orml-tokens = { workspace = true } +sp-core = { workspace = true } +sp-runtime = { workspace = true } + +[dev-dependencies] +sp-io = { workspace = true } +test-utils = { workspace = true } +rug = { workspace = true } +proptest = { workspace = true } + +[features] +default = ["std"] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-system/runtime-benchmarks", + "frame-support/runtime-benchmarks", +] +std = [ + "serde", + "codec/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "orml-tokens/std", + "orml-traits/std", + "sp-runtime/std", + "sp-core/std", + "sp-std/std", + "hydradx-traits/std", + "frame-benchmarking/std", + "scale-info/std", + "hydra-dx-math/std", + "pallet-broadcast/std", +] +try-runtime = ["frame-support/try-runtime"] diff --git a/pallets/lbp/src/benchmarking.rs b/pallets/lbp/src/benchmarking.rs new file mode 100644 index 00000000000..60d31b39b93 --- /dev/null +++ b/pallets/lbp/src/benchmarking.rs @@ -0,0 +1,305 @@ +// This file is part of HydraDX-node. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::*; + +use crate::Pallet as LBP; + +use basilisk_traits::router::{PoolType, TradeExecution}; + +use frame_benchmarking::{account, benchmarks}; +use frame_system::RawOrigin; + +const SEED: u32 = 1; + +const ASSET_HDX: AssetId = 0; +const ASSET_A_ID: AssetId = 1; +const ASSET_B_ID: AssetId = 2; +const ASSET_A_AMOUNT: Balance = 1_000_000_000; +const ASSET_B_AMOUNT: Balance = 2_000_000_000; +const INITIAL_WEIGHT: LBPWeight = 20_000_000; +const FINAL_WEIGHT: LBPWeight = 90_000_000; + +const DEFAULT_FEE: (u32, u32) = (2, 1_000); + +fn funded_account(name: &'static str, index: u32) -> T::AccountId { + let caller: T::AccountId = account(name, index, SEED); + T::MultiCurrency::update_balance(ASSET_HDX, &caller, 1_000_000_000_000_000).unwrap(); + T::MultiCurrency::update_balance(ASSET_A_ID, &caller, 1_000_000_000_000_000).unwrap(); + T::MultiCurrency::update_balance(ASSET_B_ID, &caller, 1_000_000_000_000_000).unwrap(); + caller +} + +benchmarks! { + create_pool { + let caller = funded_account::("caller", 0); + let pool_id = LBP::::pair_account_from_assets(ASSET_A_ID, ASSET_B_ID); + + }: _(RawOrigin::Root, caller.clone(), ASSET_A_ID, ASSET_A_AMOUNT, ASSET_B_ID, ASSET_B_AMOUNT, INITIAL_WEIGHT, FINAL_WEIGHT, WeightCurveType::Linear, DEFAULT_FEE, caller, 0) + verify { + assert!(PoolData::::contains_key(&pool_id)); + } + + update_pool_data { + let caller = funded_account::("caller", 0); + let fee_collector = funded_account::("fee_collector", 0); + let pool_id = LBP::::pair_account_from_assets(ASSET_A_ID, ASSET_B_ID); + let new_start = Some(BlockNumberFor::::from(50_u32)); + let new_end = Some(BlockNumberFor::::from(100_u32)); + let new_initial_weight = 45_250_600; + let new_final_weight = 55_250_600; + let fee = (5, 1000); + + LBP::::create_pool(RawOrigin::Root.into(), caller.clone(), ASSET_A_ID, ASSET_A_AMOUNT, ASSET_B_ID, ASSET_B_AMOUNT, INITIAL_WEIGHT, FINAL_WEIGHT, WeightCurveType::Linear, fee, caller.clone(), 0)?; + ensure!(PoolData::::contains_key(&pool_id), "Pool does not exist."); + + }: _(RawOrigin::Signed(caller.clone()), pool_id.clone(), Some(caller.clone()), new_start, new_end, Some(new_initial_weight), Some(new_final_weight), Some(DEFAULT_FEE), Some(fee_collector), Some(1)) + verify { + let pool_data = LBP::::pool_data(pool_id).unwrap(); + assert_eq!(pool_data.start, new_start); + assert_eq!(pool_data.end, new_end); + assert_eq!(pool_data.initial_weight, new_initial_weight); + assert_eq!(pool_data.final_weight, new_final_weight); + } + + add_liquidity { + let caller = funded_account::("caller", 0); + let pool_id = LBP::::pair_account_from_assets(ASSET_A_ID, ASSET_B_ID); + + LBP::::create_pool(RawOrigin::Root.into(), caller.clone(), ASSET_A_ID, ASSET_A_AMOUNT, ASSET_B_ID, ASSET_B_AMOUNT, INITIAL_WEIGHT, FINAL_WEIGHT, WeightCurveType::Linear, DEFAULT_FEE, caller.clone(), 0)?; + ensure!(PoolData::::contains_key(&pool_id), "Pool does not exist."); + + }: _(RawOrigin::Signed(caller), (ASSET_A_ID, 1_000_000_000_u128), (ASSET_B_ID, 2_000_000_000_u128)) + verify { + assert_eq!(T::MultiCurrency::free_balance(ASSET_A_ID, &pool_id), 2_000_000_000_u128); + assert_eq!(T::MultiCurrency::free_balance(ASSET_B_ID, &pool_id), 4_000_000_000_u128); + } + + remove_liquidity { + let caller = funded_account::("caller", 0); + let pool_id = LBP::::pair_account_from_assets(ASSET_A_ID, ASSET_B_ID); + + LBP::::create_pool(RawOrigin::Root.into(), caller.clone(), ASSET_A_ID, ASSET_A_AMOUNT, ASSET_B_ID, ASSET_B_AMOUNT, INITIAL_WEIGHT, FINAL_WEIGHT, WeightCurveType::Linear, DEFAULT_FEE, caller.clone(), 0)?; + ensure!(PoolData::::contains_key(&pool_id), "Pool does not exist."); + + }: _(RawOrigin::Signed(caller.clone()), pool_id.clone()) + verify { + assert!(!PoolData::::contains_key(&pool_id)); + assert_eq!(T::MultiCurrency::free_balance(ASSET_A_ID, &caller), 1000000000000000); + assert_eq!(T::MultiCurrency::free_balance(ASSET_B_ID, &caller), 1000000000000000); + } + + sell { + let caller = funded_account::("caller", 0); + let fee_collector = funded_account::("fee_collector", 0); + let asset_in: AssetId = ASSET_A_ID; + let asset_out: AssetId = ASSET_B_ID; + let amount : Balance = 100_000_000; + let max_limit: Balance = 10_000_000; + + let pool_id = LBP::::pair_account_from_assets(ASSET_A_ID, ASSET_B_ID); + + LBP::::create_pool(RawOrigin::Root.into(), caller.clone(), ASSET_A_ID, ASSET_A_AMOUNT, ASSET_B_ID, ASSET_B_AMOUNT, INITIAL_WEIGHT, FINAL_WEIGHT, WeightCurveType::Linear, DEFAULT_FEE, fee_collector, 0)?; + ensure!(PoolData::::contains_key(&pool_id), "Pool does not exist."); + + let start = BlockNumberFor::::from(1u32); + let end = BlockNumberFor::::from(11u32); + + LBP::::update_pool_data(RawOrigin::Signed(caller.clone()).into(), pool_id, None, Some(start), Some(end), None, None, None, None, None)?; + + frame_system::Pallet::::set_block_number(BlockNumberFor::::from(2u32)); + + }: _(RawOrigin::Signed(caller.clone()), asset_in, asset_out, amount, max_limit) + verify{ + assert_eq!(T::MultiCurrency::free_balance(asset_in, &caller), 999998900000000); + assert_eq!(T::MultiCurrency::free_balance(asset_out, &caller), 999998069275212); + } + + buy { + let caller = funded_account::("caller", 0); + let fee_collector = funded_account::("fee_collector", 0); + let asset_in: AssetId = ASSET_A_ID; + let asset_out: AssetId = ASSET_B_ID; + let amount : Balance = 100_000_000; + let max_limit: Balance = 1_000_000_000; + let pool_id = LBP::::pair_account_from_assets(ASSET_A_ID, ASSET_B_ID); + + LBP::::create_pool(RawOrigin::Root.into(), caller.clone(), ASSET_A_ID, ASSET_A_AMOUNT, ASSET_B_ID, ASSET_B_AMOUNT, INITIAL_WEIGHT, FINAL_WEIGHT, WeightCurveType::Linear, DEFAULT_FEE, fee_collector, 0)?; + ensure!(PoolData::::contains_key(&pool_id), "Pool does not exist."); + + let start = BlockNumberFor::::from(1u32); + let end = BlockNumberFor::::from(11u32); + + LBP::::update_pool_data(RawOrigin::Signed(caller.clone()).into(), pool_id, None, Some(start), Some(end), None, None, None, None, None)?; + + frame_system::Pallet::::set_block_number(BlockNumberFor::::from(2u32)); + + }: _(RawOrigin::Signed(caller.clone()), asset_out, asset_in, amount, max_limit) + verify{ + assert_eq!(T::MultiCurrency::free_balance(asset_out, &caller), 999998100000000); + assert_eq!(T::MultiCurrency::free_balance(asset_in, &caller), 999998851241411); + } + + // The following benchmarks should have similar LBP setup as the corresponding benchmarks + // for the route executor in the runtime. Otherwise the router weights are incorrect. + router_execution_sell { + let c in 1..2; // if c == 1, calculate_sell is executed + let e in 0..1; // if e == 1, execute_sell is executed + + let caller = funded_account::("caller", 0); + let fee_collector = funded_account::("fee_collector", 0); + let asset_in: AssetId = ASSET_A_ID; + let asset_out: AssetId = ASSET_B_ID; + let amount : Balance = 100_000_000; + let max_limit: Balance = 10_000_000; + + let pool_id = LBP::::pair_account_from_assets(ASSET_A_ID, ASSET_B_ID); + + LBP::::create_pool(RawOrigin::Root.into(), caller.clone(), ASSET_A_ID, ASSET_A_AMOUNT, ASSET_B_ID, ASSET_B_AMOUNT, INITIAL_WEIGHT, FINAL_WEIGHT, WeightCurveType::Linear, DEFAULT_FEE, fee_collector, 0)?; + ensure!(PoolData::::contains_key(&pool_id), "Pool does not exist."); + + let start = BlockNumberFor::::from(1u32); + let end = BlockNumberFor::::from(11u32); + + LBP::::update_pool_data(RawOrigin::Signed(caller.clone()).into(), pool_id, None, Some(start), Some(end), None, None, None, None, None)?; + + frame_system::Pallet::::set_block_number(BlockNumberFor::::from(2u32)); + + }: { + for _ in 1..c { + assert!( as TradeExecution>::calculate_sell(PoolType::LBP, asset_in, asset_out, amount).is_ok()); + } + if e != 0 { + assert!( as TradeExecution>::execute_sell(RawOrigin::Signed(caller.clone()).into(), PoolType::LBP, asset_in, asset_out, amount, max_limit).is_ok()); + } + } + verify{ + if e != 0 { + assert_eq!(T::MultiCurrency::free_balance(asset_in, &caller), 999998900000000); + assert_eq!(T::MultiCurrency::free_balance(asset_out, &caller), 999998069275212); + } + } + + router_execution_buy { + let c in 1..3; // number of times calculate_buy is executed + let e in 0..1; // if e == 1, execute_buy is executed + + let caller = funded_account::("caller", 0); + let fee_collector = funded_account::("fee_collector", 0); + let asset_in: AssetId = ASSET_A_ID; + let asset_out: AssetId = ASSET_B_ID; + let amount : Balance = 100_000_000; + let max_limit: Balance = 1_000_000_000; + + let pool_id = LBP::::pair_account_from_assets(ASSET_A_ID, ASSET_B_ID); + + LBP::::create_pool(RawOrigin::Root.into(), caller.clone(), ASSET_A_ID, ASSET_A_AMOUNT, ASSET_B_ID, ASSET_B_AMOUNT, INITIAL_WEIGHT, FINAL_WEIGHT, WeightCurveType::Linear, DEFAULT_FEE, fee_collector, 0)?; + ensure!(PoolData::::contains_key(&pool_id), "Pool does not exist."); + + let start = BlockNumberFor::::from(1u32); + let end = BlockNumberFor::::from(11u32); + + LBP::::update_pool_data(RawOrigin::Signed(caller.clone()).into(), pool_id, None, Some(start), Some(end), None, None, None, None, None)?; + + frame_system::Pallet::::set_block_number(BlockNumberFor::::from(2u32)); + + }: { + for _ in 1..c { + assert!( as TradeExecution>::calculate_buy(PoolType::LBP, asset_in, asset_out, amount).is_ok()); + } + if e != 0 { + assert!( as TradeExecution>::execute_buy(RawOrigin::Signed(caller.clone()).into(), PoolType::LBP, asset_in, asset_out, amount, max_limit).is_ok()); + } + } + verify{ + if e != 0 { + assert_eq!(T::MultiCurrency::free_balance(asset_out, &caller), 999998100000000); + assert_eq!(T::MultiCurrency::free_balance(asset_in, &caller), 999998851241411); + } + } + + // We need to handle this case separately, because for some unknown reason, router_execution_buy provides incorrect weight when just one calculate_buy is executed + calculate_buy { + let caller = funded_account::("caller", 0); + let fee_collector = funded_account::("fee_collector", 0); + let asset_in: AssetId = ASSET_A_ID; + let asset_out: AssetId = ASSET_B_ID; + let amount : Balance = 100_000_000; + let max_limit: Balance = 1_000_000_000; + + let pool_id = LBP::::pair_account_from_assets(ASSET_A_ID, ASSET_B_ID); + + LBP::::create_pool(RawOrigin::Root.into(), caller.clone(), ASSET_A_ID, ASSET_A_AMOUNT, ASSET_B_ID, ASSET_B_AMOUNT, INITIAL_WEIGHT, FINAL_WEIGHT, WeightCurveType::Linear, DEFAULT_FEE, fee_collector, 0)?; + ensure!(PoolData::::contains_key(&pool_id), "Pool does not exist."); + + let start = BlockNumberFor::::from(1u32); + let end = BlockNumberFor::::from(11u32); + + LBP::::update_pool_data(RawOrigin::Signed(caller).into(), pool_id, None, Some(start), Some(end), None, None, None, None, None)?; + + frame_system::Pallet::::set_block_number(BlockNumberFor::::from(2u32)); + + }: { + assert!( as TradeExecution>::calculate_buy(PoolType::LBP, asset_in, asset_out, amount).is_ok()); + } + verify{} + + calculate_spot_price_with_fee { + let caller = funded_account::("caller", 0); + let fee_collector = funded_account::("fee_collector", 0); + let asset_in: AssetId = ASSET_A_ID; + let asset_out: AssetId = ASSET_B_ID; + let amount : Balance = 100_000_000; + let max_limit: Balance = 1_000_000_000; + + let pool_id = LBP::::pair_account_from_assets(ASSET_A_ID, ASSET_B_ID); + + LBP::::create_pool(RawOrigin::Root.into(), caller.clone(), ASSET_A_ID, ASSET_A_AMOUNT, ASSET_B_ID, ASSET_B_AMOUNT, INITIAL_WEIGHT, FINAL_WEIGHT, WeightCurveType::Linear, DEFAULT_FEE, fee_collector, 0)?; + ensure!(PoolData::::contains_key(&pool_id), "Pool does not exist."); + + let start = BlockNumberFor::::from(1u32); + let end = BlockNumberFor::::from(11u32); + + LBP::::update_pool_data(RawOrigin::Signed(caller).into(), pool_id, None, Some(start), Some(end), None, None, None, None, None)?; + + frame_system::Pallet::::set_block_number(BlockNumberFor::::from(2u32)); + + }: { + assert!( as TradeExecution>::calculate_spot_price_with_fee(PoolType::LBP, asset_in, asset_out).is_ok()); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_create_pool()); + assert_ok!(Pallet::::test_benchmark_update_pool_data()); + assert_ok!(Pallet::::test_benchmark_add_liquidity()); + assert_ok!(Pallet::::test_benchmark_remove_liquidity()); + assert_ok!(Pallet::::test_benchmark_sell()); + assert_ok!(Pallet::::test_benchmark_buy()); + assert_ok!(Pallet::::test_benchmark_router_execution_sell()); + assert_ok!(Pallet::::test_benchmark_router_execution_buy()); + }); + } +} diff --git a/pallets/lbp/src/invariants.rs b/pallets/lbp/src/invariants.rs new file mode 100644 index 00000000000..a0c9dbf0d6b --- /dev/null +++ b/pallets/lbp/src/invariants.rs @@ -0,0 +1,339 @@ +use super::*; +use crate::mock::BlockNumber; +pub use crate::mock::{ + set_block_number, Currency, ExtBuilder, LBPPallet, RuntimeOrigin as Origin, Test, ALICE, CHARLIE, +}; +use frame_support::assert_ok; +use hydra_dx_math::types::HYDRA_ONE; +use orml_traits::MultiCurrency; +use rug::ops::Pow; +use rug::Rational; +use sp_runtime::ModuleError; + +use proptest::prelude::*; +use proptest::proptest; + +fn calc_invariant(x: Balance, y: Balance, w1: u32, w2: u32) -> Rational { + let x = Rational::from((x, HYDRA_ONE)); + let y = Rational::from((y, HYDRA_ONE)); + let w1 = w1 * 10 / MAX_WEIGHT; + let w2 = w2 * 10 / MAX_WEIGHT; + let r1 = x.pow(w1); + let r2 = y.pow(w2); + + r1 * r2 +} + +fn invariant(pool_id: u64, asset_a: AssetId, asset_b: AssetId, at: BlockNumber) -> Rational { + let pool_data = LBPPallet::pool_data(pool_id).unwrap(); + let a_balance = Currency::free_balance(asset_a, &pool_id); + let b_balance = Currency::free_balance(asset_b, &pool_id); + let (w1, w2) = LBPPallet::calculate_weights(&pool_data, at).unwrap(); + calc_invariant(a_balance, b_balance, w1, w2) +} + +const RESERVE_RANGE: (Balance, Balance) = (10_000, 1_000_000_000); +const TRADE_RANGE: (Balance, Balance) = (1, 2_000); +fn asset_amount() -> impl Strategy { + RESERVE_RANGE.0..RESERVE_RANGE.1 +} + +fn trade_amount() -> impl Strategy { + TRADE_RANGE.0..TRADE_RANGE.1 +} + +fn to_precision(value: Balance, precision: u8) -> Balance { + value * 10u128.pow(precision as u32) +} + +fn decimals() -> impl Strategy { + prop_oneof![Just(6), Just(8), Just(10), Just(12), Just(18)] +} + +fn weight_ratio() -> impl Strategy { + // we can only use simple ratios due to limitations in the invariant calculation + 1u32..10u32 +} + +fn weights() -> impl Strategy { + weight_ratio().prop_map(|ratio| (ratio * MAX_WEIGHT / 10, (10 - ratio) * MAX_WEIGHT / 10)) +} + +#[derive(Debug, Copy, Clone)] +struct Assets { + pub asset_a_amount: u128, + pub asset_a_decimals: u8, + pub asset_b_amount: u128, + pub asset_b_decimals: u8, +} + +fn pool_assets() -> impl Strategy { + (decimals(), decimals(), asset_amount(), asset_amount()).prop_map(|(dec_a, dec_b, a_amount, b_amount)| Assets { + asset_a_amount: to_precision(a_amount, dec_a), + asset_a_decimals: dec_a, + asset_b_amount: to_precision(b_amount, dec_b), + asset_b_decimals: dec_b, + }) +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1000))] + #[test] + fn sell_accumulated_asset_invariant( + assets in pool_assets(), + sell_amount in trade_amount(), + (weight_a, weight_b) in weights(), + ) { + let asset_a = 1; + let asset_b = 2; + let pool_id: PoolId = 1002; + + let sell_amount = to_precision(sell_amount, assets.asset_a_decimals); + + ExtBuilder::default() + .with_endowed_accounts(vec![ + (ALICE, asset_a, assets.asset_a_amount + sell_amount), + (ALICE, asset_b, assets.asset_b_amount + sell_amount), + ]) + .build() + .execute_with(|| { + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + asset_a, + assets.asset_a_amount, + asset_b, + assets.asset_b_amount, + weight_a, + weight_b, + WeightCurveType::Linear, + (0, 1), + CHARLIE, + 0, + )); + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + pool_id, + None, + Some(10), + Some(40), + None, + None, + None, + None, + None, + )); + + let block_num = 10; + set_block_number(block_num); + + let before = invariant(pool_id, asset_a, asset_b, block_num); + assert_ok!(filter_errors(LBPPallet::sell(Origin::signed(ALICE), asset_a, asset_b, sell_amount, 0,))); + + let after = invariant(pool_id, asset_a, asset_b, block_num); + assert!(after >= before); + }); + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1000))] + #[test] + fn sell_distributed_asset_invariant( + assets in pool_assets(), + sell_amount in trade_amount(), + (weight_a, weight_b) in weights(), + ) { + let asset_a = 1; + let asset_b = 2; + let pool_id: PoolId = 1002; + + let sell_amount = to_precision(sell_amount, assets.asset_a_decimals); + + ExtBuilder::default() + .with_endowed_accounts(vec![ + (ALICE, asset_a, assets.asset_a_amount + sell_amount), + (ALICE, asset_b, assets.asset_b_amount + sell_amount), + ]) + .build() + .execute_with(|| { + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + asset_a, + assets.asset_a_amount, + asset_b, + assets.asset_b_amount, + weight_a, + weight_b, + WeightCurveType::Linear, + (0, 1), + CHARLIE, + 0, + )); + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + pool_id, + None, + Some(10), + Some(40), + None, + None, + None, + None, + None, + )); + + let block_num = 10; + set_block_number(block_num); + + let before = invariant(pool_id, asset_a, asset_b, block_num); + assert_ok!(filter_errors(LBPPallet::sell(Origin::signed(ALICE), asset_b, asset_a, sell_amount, 0,))); + let after = invariant(pool_id, asset_a, asset_b, block_num); + assert!(after >= before); + }); + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1000))] + #[test] + fn buy_distributed_invariant( + assets in pool_assets(), + buy_amount in trade_amount(), + (weight_a, weight_b) in weights(), + ) { + let asset_a = 1; + let asset_b = 2; + let pool_id: PoolId = 1002; + + let buy_amount = to_precision(buy_amount, assets.asset_b_decimals); + + ExtBuilder::default() + .with_endowed_accounts(vec![ + (ALICE, asset_a, assets.asset_a_amount * 1000), + (ALICE, asset_b, assets.asset_b_amount * 1000), + ]) + .build() + .execute_with(|| { + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + asset_a, + assets.asset_a_amount, + asset_b, + assets.asset_b_amount, + weight_a, + weight_b, + WeightCurveType::Linear, + (0, 1), + CHARLIE, + 0, + )); + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + pool_id, + None, + Some(10), + Some(40), + None, + None, + None, + None, + None, + )); + + let block_num = 10; + set_block_number(block_num); + + let before = invariant(pool_id, asset_a, asset_b, block_num); + assert_ok!(filter_errors(LBPPallet::buy(Origin::signed(ALICE), asset_b, asset_a, buy_amount, u128::MAX,))); + let after = invariant(pool_id, asset_a, asset_b, block_num); + assert!(after >= before); + }); + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1000))] + #[test] + fn buy_accumulated_invariant( + assets in pool_assets(), + buy_amount in trade_amount(), + (weight_a, weight_b) in weights(), + ) { + let asset_a = 1; + let asset_b = 2; + let pool_id: PoolId = 1002; + + let buy_amount = to_precision(buy_amount, assets.asset_b_decimals); + + ExtBuilder::default() + .with_endowed_accounts(vec![ + (ALICE, asset_a, assets.asset_a_amount * 1000), + (ALICE, asset_b, assets.asset_b_amount * 1000), + ]) + .build() + .execute_with(|| { + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + asset_a, + assets.asset_a_amount, + asset_b, + assets.asset_b_amount, + weight_a, + weight_b, + WeightCurveType::Linear, + (0, 1), + CHARLIE, + 0, + )); + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + pool_id, + None, + Some(10), + Some(40), + None, + None, + None, + None, + None, + )); + + let block_num = 10; + set_block_number(block_num); + + let before = invariant(pool_id, asset_a, asset_b, block_num); + assert_ok!(filter_errors(LBPPallet::buy(Origin::signed(ALICE), asset_a, asset_b, buy_amount, u128::MAX,))); + + let after = invariant(pool_id, asset_a, asset_b, block_num); + assert!(after >= before); + }); + } +} + +fn filter_errors(dispatch_result: DispatchResult) -> DispatchResult { + if dispatch_result.is_err() { + let is_filtered = matches!( + dispatch_result, + Err(DispatchError::Module(ModuleError { + index: 1, + error: [14, 0, 0, 0], + message: Some("MaxInRatioExceeded"), + })) | Err(DispatchError::Module(ModuleError { + index: 1, + error: [15, 0, 0, 0], + message: Some("MaxOutRatioExceeded"), + })) + ); + + if is_filtered { + println!("Error skipped"); + return Ok(()); + }; + } + + dispatch_result +} diff --git a/pallets/lbp/src/lib.rs b/pallets/lbp/src/lib.rs new file mode 100644 index 00000000000..f677f117313 --- /dev/null +++ b/pallets/lbp/src/lib.rs @@ -0,0 +1,1359 @@ +// This file is part of HydraDX-node. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::unused_unit)] +#![allow(clippy::upper_case_acronyms)] +#![allow(clippy::type_complexity)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::manual_inspect)] + +pub use crate::types::{Amount, AssetId, AssetPair, Balance}; +use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen}; +use frame_support::sp_runtime::{ + traits::{AtLeast32BitUnsigned, BlockNumberProvider, Saturating, Zero}, + DispatchError, RuntimeDebug, +}; +use frame_support::{ + dispatch::DispatchResult, + ensure, + traits::{EnsureOrigin, ExistenceRequirement, Get, LockIdentifier}, + transactional, +}; +use frame_system::ensure_signed; +use frame_system::pallet_prelude::BlockNumberFor; +use hydra_dx_math::types::LBPWeight; +use hydradx_traits::{AMMTransfer, AssetPairAccountIdFor, CanCreatePool, LockedBalance, AMM}; +use pallet_broadcast::types::{Asset, Destination, Fee}; + +use orml_traits::{MultiCurrency, MultiCurrencyExtended, MultiLockableCurrency}; + +use scale_info::TypeInfo; + +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; +use sp_std::{vec, vec::Vec}; + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +#[allow(clippy::all)] +pub mod weights; + +#[cfg(test)] +mod invariants; + +mod provider; +mod trade_execution; +pub mod types; + +pub use weights::WeightInfo; +// Re-export pallet items so that they can be accessed from the crate namespace. +pub use pallet::*; + +type BalanceOf = <::MultiCurrency as MultiCurrency<::AccountId>>::Balance; +type PoolId = ::AccountId; + +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive( + Default, RuntimeDebug, Encode, Decode, DecodeWithMemTracking, Copy, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen, +)] +pub enum WeightCurveType { + #[default] + Linear, +} + +/// Max weight corresponds to 100% +pub const MAX_WEIGHT: LBPWeight = 100_000_000; + +/// Max sale duration is 14 days, assuming 6 sec blocks +pub const MAX_SALE_DURATION: u32 = (60 * 60 * 24 / 6) * 14; + +/// Lock Identifier for the collected fees +pub const COLLECTOR_LOCK_ID: LockIdentifier = *b"lbpcllct"; + +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(RuntimeDebug, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +pub struct Pool { + /// owner of the pool after `CreatePoolOrigin` creates it + pub owner: AccountId, + + /// start block + pub start: Option, + + /// end block + pub end: Option, + + /// Asset ids of the tokens (accumulating asset, sold asset) // TODO maybe name them accordingly in struct instead of tuple + pub assets: (AssetId, AssetId), + + /// initial weight of the asset_a where the minimum value is 0 (equivalent to 0% weight), and the maximum value is 100_000_000 (equivalent to 100% weight) + pub initial_weight: LBPWeight, + + /// final weights of the asset_a where the minimum value is 0 (equivalent to 0% weight), and the maximum value is 100_000_000 (equivalent to 100% weight) + pub final_weight: LBPWeight, + + /// weight curve + pub weight_curve: WeightCurveType, + + /// standard fee amount + pub fee: (u32, u32), + + /// person that receives the fee + pub fee_collector: AccountId, + + /// repayment target of the accumulated asset in fee collectors account, when this target is reached fee drops from 20% to fee + pub repay_target: Balance, +} + +impl Pool { + fn new( + pool_owner: AccountId, + asset_a: AssetId, + asset_b: AssetId, + initial_weight: LBPWeight, + final_weight: LBPWeight, + weight_curve: WeightCurveType, + fee: (u32, u32), + fee_collector: AccountId, + repay_target: Balance, + ) -> Self { + Pool { + owner: pool_owner, + start: None, + end: None, + assets: (asset_a, asset_b), + initial_weight, + final_weight, + weight_curve, + fee, + fee_collector, + repay_target, + } + } +} + +pub trait LBPWeightCalculation { + fn calculate_weight( + weight_curve: WeightCurveType, + start: BlockNumber, + end: BlockNumber, + initial_weight: LBPWeight, + final_weight: LBPWeight, + at: BlockNumber, + ) -> Option; +} + +pub struct LBPWeightFunction; +impl LBPWeightCalculation for LBPWeightFunction { + fn calculate_weight( + _weight_curve: WeightCurveType, + start: BlockNumber, + end: BlockNumber, + initial_weight: LBPWeight, + final_weight: LBPWeight, + at: BlockNumber, + ) -> Option { + hydra_dx_math::lbp::calculate_linear_weights(start, end, initial_weight, final_weight, at).ok() + } +} + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::OriginFor; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config + pallet_broadcast::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// Multi currency for transfer of currencies + type MultiCurrency: MultiCurrencyExtended + + MultiLockableCurrency; + + /// Universal locked balance getter for tracking of fee collector balance + type LockedBalance: LockedBalance; + + /// The origin which can create a new pool + type CreatePoolOrigin: EnsureOrigin; + + /// Function for calculation of LBP weights + type LBPWeightFunction: LBPWeightCalculation>; + + /// Mapping of asset pairs to unique pool identities + type AssetPairAccountId: AssetPairAccountIdFor>; + + /// Weight information for the extrinsics + type WeightInfo: WeightInfo; + + /// Minimum trading limit, sole purpose of this is to keep the math working + #[pallet::constant] + type MinTradingLimit: Get; + + /// Minimum pool liquidity, sole purpose of this is to keep the math working + #[pallet::constant] + type MinPoolLiquidity: Get; + + /// Max fraction of pool to sell in single transaction + #[pallet::constant] + type MaxInRatio: Get; + + /// Max fraction of pool to buy in single transaction + #[pallet::constant] + type MaxOutRatio: Get; + + /// The block number provider + type BlockNumberProvider: BlockNumberProvider>; + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn integrity_test() { + // The exponentiation used in the math can overflow for values smaller than 3 + assert!(T::MaxInRatio::get() >= 3, "LBP: MaxInRatio is set to invalid value."); + + assert!(T::MaxOutRatio::get() >= 3, "LBP: MaxOutRatio is set to invalid value."); + } + } + + #[pallet::error] + pub enum Error { + /// Pool assets can not be the same + CannotCreatePoolWithSameAssets, + + /// Account is not a pool owner + NotOwner, + + /// Sale already started + SaleStarted, + + /// Sale is still in progress + SaleNotEnded, + + /// Sale is not running + SaleIsNotRunning, + + /// Sale duration is too long + MaxSaleDurationExceeded, + + /// Liquidity being added should not be zero + CannotAddZeroLiquidity, + + /// Asset balance too low + InsufficientAssetBalance, + + /// Pool does not exist + PoolNotFound, + + /// Pool has been already created + PoolAlreadyExists, + + /// Invalid block range + InvalidBlockRange, + + /// Calculation error + WeightCalculationError, + + /// Weight set is out of range + InvalidWeight, + + /// Can not perform a trade with zero amount + ZeroAmount, + + /// Trade amount is too high + MaxInRatioExceeded, + + /// Trade amount is too high + MaxOutRatioExceeded, + + /// Invalid fee amount + FeeAmountInvalid, + + /// Trading limit reached + TradingLimitReached, + + /// An unexpected integer overflow occurred + Overflow, + + /// Nothing to update + NothingToUpdate, + + /// Liquidity has not reached the required minimum. + InsufficientLiquidity, + + /// Amount is less than minimum trading limit. + InsufficientTradingAmount, + + /// Not more than one fee collector per asset id + FeeCollectorWithAssetAlreadyUsed, + } + + #[pallet::event] + #[pallet::generate_deposit(pub(crate) fn deposit_event)] + pub enum Event { + /// Pool was created by the `CreatePool` origin. + PoolCreated { + pool: PoolId, + data: Pool>, + }, + + /// Pool data were updated. + PoolUpdated { + pool: PoolId, + data: Pool>, + }, + + /// New liquidity was provided to the pool. + LiquidityAdded { + who: T::AccountId, + asset_a: AssetId, + asset_b: AssetId, + amount_a: BalanceOf, + amount_b: BalanceOf, + }, + + /// Liquidity was removed from the pool and the pool was destroyed. + LiquidityRemoved { + who: T::AccountId, + asset_a: AssetId, + asset_b: AssetId, + amount_a: BalanceOf, + amount_b: BalanceOf, + }, + + /// Sale executed. + /// Deprecated. Replaced by pallet_broadcast::Swapped + SellExecuted { + who: T::AccountId, + asset_in: AssetId, + asset_out: AssetId, + amount: BalanceOf, + sale_price: BalanceOf, + fee_asset: AssetId, + fee_amount: BalanceOf, + }, + + /// Purchase executed. + /// Deprecated. Replaced by pallet_broadcast::Swapped + BuyExecuted { + who: T::AccountId, + asset_out: AssetId, + asset_in: AssetId, + amount: BalanceOf, + buy_price: BalanceOf, + fee_asset: AssetId, + fee_amount: BalanceOf, + }, + } + + /// Details of a pool. + #[pallet::storage] + #[pallet::getter(fn pool_data)] + pub type PoolData = + StorageMap<_, Blake2_128Concat, PoolId, Pool>, OptionQuery>; + + /// Storage used for tracking existing fee collectors + /// Not more than one fee collector per asset possible + #[pallet::storage] + pub type FeeCollectorWithAsset = + StorageDoubleMap<_, Blake2_128Concat, T::AccountId, Blake2_128Concat, AssetId, bool, ValueQuery>; + + #[pallet::extra_constants] + impl Pallet { + pub fn repay_fee() -> (u32, u32) { + (2, 10) + } + } + + #[pallet::call] + impl Pallet { + /// Create a new liquidity bootstrapping pool for given asset pair. + /// + /// For any asset pair, only one pool can exist at a time. + /// + /// The dispatch origin for this call must be `T::CreatePoolOrigin`. + /// The pool is created with initial liquidity provided by the `pool_owner` who must have + /// sufficient funds free. + /// + /// The pool starts uninitialized and update_pool call should be called once created to set the start block. + /// + /// This function should be dispatched from governing entity `T::CreatePoolOrigin` + /// + /// Parameters: + /// - `pool_owner`: the future owner of the new pool. + /// - `asset_a`: { asset_id, amount } Asset ID and initial liquidity amount. + /// - `asset_b`: { asset_id, amount } Asset ID and initial liquidity amount. + /// - `initial_weight`: Initial weight of the asset_a. 1_000_000 corresponding to 1% and 100_000_000 to 100% + /// this should be higher than final weight + /// - `final_weight`: Final weight of the asset_a. 1_000_000 corresponding to 1% and 100_000_000 to 100% + /// this should be lower than initial weight + /// - `weight_curve`: The weight function used to update the LBP weights. Currently, + /// there is only one weight function implemented, the linear function. + /// - `fee`: The trading fee charged on every trade distributed to `fee_collector`. + /// - `fee_collector`: The account to which trading fees will be transferred. + /// - `repay_target`: The amount of tokens to repay to separate fee_collector account. Until this amount is + /// reached, fee will be increased to 20% and taken from the pool + /// + /// Emits `PoolCreated` event when successful. + /// + /// BEWARE: We are taking the fee from the accumulated asset. If the accumulated asset is sold to the pool, + /// the fee cost is transferred to the pool. If its bought from the pool the buyer bears the cost. + /// This increases the price of the sold asset on every trade. Make sure to only run this with + /// previously illiquid assets. + #[pallet::call_index(0)] + #[pallet::weight(::WeightInfo::create_pool())] + pub fn create_pool( + origin: OriginFor, + pool_owner: T::AccountId, + asset_a: AssetId, + asset_a_amount: Balance, + asset_b: AssetId, + asset_b_amount: Balance, + initial_weight: LBPWeight, + final_weight: LBPWeight, + weight_curve: WeightCurveType, + fee: (u32, u32), + fee_collector: T::AccountId, + repay_target: Balance, + ) -> DispatchResult { + T::CreatePoolOrigin::ensure_origin(origin)?; + + ensure!( + asset_a_amount >= T::MinPoolLiquidity::get() && asset_b_amount >= T::MinPoolLiquidity::get(), + Error::::InsufficientLiquidity + ); + + ensure!(asset_a != asset_b, Error::::CannotCreatePoolWithSameAssets); + + let asset_pair = AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }; + + ensure!(!Self::exists(asset_pair), Error::::PoolAlreadyExists); + + ensure!( + !>::contains_key(fee_collector.clone(), asset_a), + Error::::FeeCollectorWithAssetAlreadyUsed + ); + + ensure!( + T::MultiCurrency::free_balance(asset_a, &pool_owner) >= asset_a_amount, + Error::::InsufficientAssetBalance + ); + + ensure!( + T::MultiCurrency::free_balance(asset_b, &pool_owner) >= asset_b_amount, + Error::::InsufficientAssetBalance + ); + + let pool_data = Pool::new( + pool_owner.clone(), + asset_a, + asset_b, + initial_weight, + final_weight, + weight_curve, + fee, + fee_collector.clone(), + repay_target, + ); + + Self::validate_pool_data(&pool_data)?; + + let pool_id = Self::get_pair_id(asset_pair); + + >::insert(&pool_id, &pool_data); + >::insert(fee_collector, asset_a, true); + + Self::deposit_event(Event::PoolCreated { + pool: pool_id.clone(), + data: pool_data, + }); + + T::MultiCurrency::transfer( + asset_a, + &pool_owner, + &pool_id, + asset_a_amount, + ExistenceRequirement::AllowDeath, + )?; + T::MultiCurrency::transfer( + asset_b, + &pool_owner, + &pool_id, + asset_b_amount, + ExistenceRequirement::AllowDeath, + )?; + + Self::deposit_event(Event::LiquidityAdded { + who: pool_id, + asset_a, + asset_b, + amount_a: asset_a_amount, + amount_b: asset_b_amount, + }); + + Ok(()) + } + + /// Update pool data of a pool. + /// + /// The dispatch origin for this call must be signed by the pool owner. + /// + /// The pool can be updated only if the sale has not already started. + /// + /// At least one of the following optional parameters has to be specified. + /// + /// Parameters: + /// - `pool_id`: The identifier of the pool to be updated. + /// - `start`: The new starting time of the sale. This parameter is optional. + /// - `end`: The new ending time of the sale. This parameter is optional. + /// - `initial_weight`: The new initial weight. This parameter is optional. + /// - `final_weight`: The new final weight. This parameter is optional. + /// - `fee`: The new trading fee charged on every trade. This parameter is optional. + /// - `fee_collector`: The new receiver of trading fees. This parameter is optional. + /// + /// Emits `PoolUpdated` event when successful. + #[pallet::call_index(1)] + #[pallet::weight(::WeightInfo::update_pool_data())] + pub fn update_pool_data( + origin: OriginFor, + pool_id: PoolId, + pool_owner: Option, + start: Option>, + end: Option>, + initial_weight: Option, + final_weight: Option, + fee: Option<(u32, u32)>, + fee_collector: Option, + repay_target: Option, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + >::try_mutate_exists(pool_id.clone(), |maybe_pool| -> DispatchResult { + // check existence of the pool + let pool = maybe_pool.as_mut().ok_or(Error::::PoolNotFound)?; + + ensure!( + start.is_some() + || end.is_some() || initial_weight.is_some() + || final_weight.is_some() + || fee.is_some() || fee_collector.is_some() + || repay_target.is_some(), + Error::::NothingToUpdate + ); + + ensure!(who == pool.owner, Error::::NotOwner); + + ensure!(!Self::has_pool_started(pool), Error::::SaleStarted); + + pool.owner = pool_owner.unwrap_or_else(|| pool.owner.clone()); + + pool.start = start.or(pool.start); + pool.end = end.or(pool.end); + + pool.initial_weight = initial_weight.unwrap_or(pool.initial_weight); + + pool.final_weight = final_weight.unwrap_or(pool.final_weight); + + pool.fee = fee.unwrap_or(pool.fee); + + // Handle update of fee collector - validate and replace old fee collector + if let Some(updated_fee_collector) = fee_collector { + FeeCollectorWithAsset::::try_mutate( + &updated_fee_collector, + pool.assets.0, + |collector| -> DispatchResult { + ensure!(!*collector, Error::::FeeCollectorWithAssetAlreadyUsed); + + >::remove(&pool.fee_collector, pool.assets.0); + *collector = true; + + Ok(()) + }, + )?; + + pool.fee_collector = updated_fee_collector; + } + + pool.repay_target = repay_target.unwrap_or(pool.repay_target); + + Self::validate_pool_data(pool)?; + + Self::deposit_event(Event::PoolUpdated { + pool: pool_id, + data: (*pool).clone(), + }); + Ok(()) + }) + } + + /// Add liquidity to a pool. + /// + /// Assets to add has to match the pool assets. At least one amount has to be non-zero. + /// + /// The dispatch origin for this call must be signed by the pool owner. + /// + /// Parameters: + /// - `pool_id`: The identifier of the pool + /// - `amount_a`: The identifier of the asset and the amount to add. + /// - `amount_b`: The identifier of the second asset and the amount to add. + /// + /// Emits `LiquidityAdded` event when successful. + #[pallet::call_index(2)] + #[pallet::weight(::WeightInfo::add_liquidity())] + pub fn add_liquidity( + origin: OriginFor, + amount_a: (AssetId, BalanceOf), + amount_b: (AssetId, BalanceOf), + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + let (asset_a, asset_b) = (amount_a.0, amount_b.0); + let (amount_a, amount_b) = (amount_a.1, amount_b.1); + + let pool_id = Self::pair_account_from_assets(asset_a, asset_b); + let pool_data = >::try_get(&pool_id).map_err(|_| Error::::PoolNotFound)?; + + ensure!(who == pool_data.owner, Error::::NotOwner); + + ensure!( + !amount_a.is_zero() || !amount_b.is_zero(), + Error::::CannotAddZeroLiquidity + ); + + if !amount_a.is_zero() { + ensure!( + T::MultiCurrency::free_balance(asset_a, &who) >= amount_a, + Error::::InsufficientAssetBalance + ); + } + + if !amount_b.is_zero() { + ensure!( + T::MultiCurrency::free_balance(asset_b, &who) >= amount_b, + Error::::InsufficientAssetBalance + ); + } + + T::MultiCurrency::transfer(asset_a, &who, &pool_id, amount_a, ExistenceRequirement::AllowDeath)?; + T::MultiCurrency::transfer(asset_b, &who, &pool_id, amount_b, ExistenceRequirement::AllowDeath)?; + + Self::deposit_event(Event::LiquidityAdded { + who: pool_id, + asset_a, + asset_b, + amount_a, + amount_b, + }); + + Ok(()) + } + + /// Transfer all the liquidity from a pool back to the pool owner and destroy the pool. + /// The pool data are also removed from the storage. + /// + /// The pool can't be destroyed during the sale. + /// + /// The dispatch origin for this call must be signed by the pool owner. + /// + /// Parameters: + /// - `amount_a`: The identifier of the asset and the amount to add. + /// + /// Emits 'LiquidityRemoved' when successful. + #[pallet::call_index(3)] + #[pallet::weight(::WeightInfo::remove_liquidity())] + pub fn remove_liquidity(origin: OriginFor, pool_id: PoolId) -> DispatchResult { + let who = ensure_signed(origin)?; + + let pool_data = >::try_get(&pool_id).map_err(|_| Error::::PoolNotFound)?; + + ensure!(who == pool_data.owner, Error::::NotOwner); + + ensure!(!Self::is_pool_running(&pool_data), Error::::SaleNotEnded); + + let (asset_a, asset_b) = pool_data.assets; + + let amount_a = T::MultiCurrency::free_balance(asset_a, &pool_id); + let amount_b = T::MultiCurrency::free_balance(asset_b, &pool_id); + + T::MultiCurrency::transfer(asset_a, &pool_id, &who, amount_a, ExistenceRequirement::AllowDeath)?; + T::MultiCurrency::transfer(asset_b, &pool_id, &who, amount_b, ExistenceRequirement::AllowDeath)?; + + if Self::collected_fees(&pool_data) > 0 { + T::MultiCurrency::remove_lock(COLLECTOR_LOCK_ID, asset_a, &pool_data.fee_collector)?; + } + + >::remove(pool_data.fee_collector, pool_data.assets.0); + >::remove(&pool_id); + + Self::deposit_event(Event::LiquidityRemoved { + who: pool_id, + asset_a, + asset_b, + amount_a, + amount_b, + }); + + Ok(()) + } + + /// Trade `asset_in` for `asset_out`. + /// + /// Executes a swap of `asset_in` for `asset_out`. Price is determined by the pool and is + /// affected by the amount and proportion of the pool assets and the weights. + /// + /// Trading `fee` is distributed to the `fee_collector`. + /// + /// Parameters: + /// - `asset_in`: The identifier of the asset being transferred from the account to the pool. + /// - `asset_out`: The identifier of the asset being transferred from the pool to the account. + /// - `amount`: The amount of `asset_in` + /// - `max_limit`: minimum amount of `asset_out` / amount of asset_out to be obtained from the pool in exchange for `asset_in`. + /// + /// Emits `SellExecuted` when successful. Deprecated. + /// Emits `pallet_broadcast::Swapped` when successful. + #[pallet::call_index(4)] + #[pallet::weight(::WeightInfo::sell())] + pub fn sell( + origin: OriginFor, + asset_in: AssetId, + asset_out: AssetId, + amount: BalanceOf, + max_limit: BalanceOf, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + >::sell(&who, AssetPair { asset_in, asset_out }, amount, max_limit, false)?; + + Ok(()) + } + + /// Trade `asset_in` for `asset_out`. + /// + /// Executes a swap of `asset_in` for `asset_out`. Price is determined by the pool and is + /// affected by the amount and the proportion of the pool assets and the weights. + /// + /// Trading `fee` is distributed to the `fee_collector`. + /// + /// Parameters: + /// - `asset_in`: The identifier of the asset being transferred from the account to the pool. + /// - `asset_out`: The identifier of the asset being transferred from the pool to the account. + /// - `amount`: The amount of `asset_out`. + /// - `max_limit`: maximum amount of `asset_in` to be sold in exchange for `asset_out`. + /// + /// Emits `BuyExecuted` when successful. Deprecated. + /// Emits `pallet_broadcast::Swapped` when successful. + #[pallet::call_index(5)] + #[pallet::weight(::WeightInfo::buy())] + pub fn buy( + origin: OriginFor, + asset_out: AssetId, + asset_in: AssetId, + amount: BalanceOf, + max_limit: BalanceOf, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + >::buy(&who, AssetPair { asset_in, asset_out }, amount, max_limit, false)?; + + Ok(()) + } + } +} + +impl Pallet { + fn calculate_weights( + pool_data: &Pool>, + at: BlockNumberFor, + ) -> Result<(LBPWeight, LBPWeight), DispatchError> { + let weight_a = T::LBPWeightFunction::calculate_weight( + pool_data.weight_curve, + pool_data.start.unwrap_or_else(Zero::zero), + pool_data.end.unwrap_or_else(Zero::zero), + pool_data.initial_weight, + pool_data.final_weight, + at, + ) + .ok_or(Error::::WeightCalculationError)?; + + let weight_b = MAX_WEIGHT.saturating_sub(weight_a); + + Ok((weight_a, weight_b)) + } + + fn validate_pool_data(pool_data: &Pool>) -> DispatchResult { + let now = T::BlockNumberProvider::current_block_number(); + + ensure!( + match (pool_data.start, pool_data.end) { + (Some(start), Some(end)) => now < start && start < end, + (None, None) => true, + _ => false, + }, + Error::::InvalidBlockRange + ); + + // duration of the LBP sale should not exceed 2 weeks (assuming 6 sec blocks) + ensure!( + pool_data + .end + .unwrap_or_default() + .saturating_sub(pool_data.start.unwrap_or_default()) + < MAX_SALE_DURATION.into(), + Error::::MaxSaleDurationExceeded + ); + + // zero weight at the beginning or at the end of a sale may cause a problem in the price calculation + // Minimum allowed weight is 2%. The exponentiation used in the math can overflow when the ration between the weights is higher than 98/2. + ensure!( + !pool_data.initial_weight.is_zero() + && pool_data.initial_weight < MAX_WEIGHT + && pool_data.initial_weight >= MAX_WEIGHT / 50 // 2% + && !pool_data.final_weight.is_zero() + && pool_data.final_weight < MAX_WEIGHT + // when initial and final weights are >= 2%, then the weights are also <= 98% + && pool_data.final_weight >= MAX_WEIGHT / 50, // 2%, + // TODO people could leak value out the pool if initial weight is < final weight due to fee structure + // && pool_data.initial_weight > pool_data.final_weight, + Error::::InvalidWeight + ); + + ensure!(!pool_data.fee.1.is_zero(), Error::::FeeAmountInvalid); + + Ok(()) + } + + fn get_sorted_weight( + asset_in: AssetId, + now: BlockNumberFor, + pool_data: &Pool>, + ) -> Result<(LBPWeight, LBPWeight), Error> { + match Self::calculate_weights(pool_data, now) { + Ok(weights) => { + if asset_in == pool_data.assets.0 { + Ok((weights.0, weights.1)) + } else { + // swap weights if assets are in different order + Ok((weights.1, weights.0)) + } + } + Err(_) => Err(Error::::InvalidWeight), + } + } + + /// return true if now is in interval + fn is_pool_running(pool_data: &Pool>) -> bool { + let now = T::BlockNumberProvider::current_block_number(); + match (pool_data.start, pool_data.end) { + (Some(start), Some(end)) => start <= now && now <= end, + _ => false, + } + } + + /// return true if now is > pool.start and pool has been initialized + fn has_pool_started(pool_data: &Pool>) -> bool { + let now = T::BlockNumberProvider::current_block_number(); + match pool_data.start { + Some(start) => start <= now, + _ => false, + } + } + + /// returns fees collected and locked in the fee collector account + /// note: after LBP finishes and liquidity is removed this will be 0 + fn collected_fees(pool: &Pool>) -> BalanceOf { + T::LockedBalance::get_by_lock(COLLECTOR_LOCK_ID, pool.assets.0, pool.fee_collector.clone()) + } + + /// repay fee is applied until repay target amount is reached + fn is_repay_fee_applied(pool: &Pool>) -> bool { + Self::collected_fees(pool) < pool.repay_target + } + + #[transactional] + fn execute_trade(transfer: &AMMTransfer) -> DispatchResult { + let pool_account = Self::get_pair_id(transfer.assets); + let pool = >::try_get(&pool_account).map_err(|_| Error::::PoolNotFound)?; + + // Transfer assets between pool and user + T::MultiCurrency::transfer( + transfer.assets.asset_in, + &transfer.origin, + &pool_account, + transfer.amount, + ExistenceRequirement::AllowDeath, + )?; + T::MultiCurrency::transfer( + transfer.assets.asset_out, + &pool_account, + &transfer.origin, + transfer.amount_b, + ExistenceRequirement::AllowDeath, + )?; + + // Fee is deducted from the sent out amount of accumulated asset and transferred to the fee collector + let (fee_asset, fee_amount) = transfer.fee; + let fee_payer = if transfer.assets.asset_in == fee_asset { + &transfer.origin + } else { + &pool_account + }; + + T::MultiCurrency::transfer( + fee_asset, + fee_payer, + &pool.fee_collector, + fee_amount, + ExistenceRequirement::AllowDeath, + )?; + + // Resets lock for total of collected fees + let collected_fee_total = Self::collected_fees(&pool) + fee_amount; + T::MultiCurrency::set_lock(COLLECTOR_LOCK_ID, fee_asset, &pool.fee_collector, collected_fee_total)?; + + Ok(()) + } + + /// determines fee rate and applies it to the amount + fn calculate_fees( + pool: &Pool>, + amount: BalanceOf, + ) -> Result, DispatchError> { + let fee = if Self::is_repay_fee_applied(pool) { + Self::repay_fee() + } else { + pool.fee + }; + Ok(hydra_dx_math::fee::calculate_pool_trade_fee(amount, (fee.0, fee.1)) + .ok_or::>(Error::::FeeAmountInvalid)?) + } + + pub fn pair_account_from_assets(asset_a: AssetId, asset_b: AssetId) -> PoolId { + T::AssetPairAccountId::from_assets(asset_a, asset_b, "lbp") + } +} + +impl AMM> for Pallet { + fn exists(assets: AssetPair) -> bool { + let pair_account = Self::pair_account_from_assets(assets.asset_in, assets.asset_out); + >::contains_key(&pair_account) + } + + fn get_pair_id(assets: AssetPair) -> T::AccountId { + Self::pair_account_from_assets(assets.asset_in, assets.asset_out) + } + + fn get_share_token(_assets: AssetPair) -> AssetId { + // No share token in lbp + AssetId::MAX + } + + fn get_pool_assets(pool_account_id: &T::AccountId) -> Option> { + let maybe_pool = >::try_get(pool_account_id); + if let Ok(pool_data) = maybe_pool { + Some(vec![pool_data.assets.0, pool_data.assets.1]) + } else { + None + } + } + + /// Calculate spot price for given assets and amount. This method does not modify the storage. + /// + /// Provided assets must exist in the pool. Panic if an asset does not exist in the pool. + /// + /// Return 0 if calculation overflows or weights calculation overflows. + fn get_spot_price_unchecked(asset_a: AssetId, asset_b: AssetId, amount: BalanceOf) -> BalanceOf { + let pool_id = Self::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + + let asset_a_reserve = T::MultiCurrency::free_balance(asset_a, &pool_id); + let asset_b_reserve = T::MultiCurrency::free_balance(asset_b, &pool_id); + + let pool_data = match >::try_get(&pool_id) { + Ok(pool) => pool, + Err(_) => return BalanceOf::::zero(), + }; + + let now = T::BlockNumberProvider::current_block_number(); + + // We need to sort weights here if asset_in is not the first asset + let (weight_in, weight_out) = match Self::get_sorted_weight(asset_a, now, &pool_data) { + Ok(weights) => weights, + Err(_) => return BalanceOf::::zero(), + }; + + hydra_dx_math::lbp::calculate_spot_price(asset_a_reserve, asset_b_reserve, weight_in, weight_out, amount) + .unwrap_or_else(|_| BalanceOf::::zero()) + } + + fn validate_sell( + who: &T::AccountId, + assets: AssetPair, + amount: BalanceOf, + min_bought: BalanceOf, + _discount: bool, + ) -> Result, DispatchError> { + ensure!(!amount.is_zero(), Error::::ZeroAmount); + ensure!( + T::MultiCurrency::free_balance(assets.asset_in, who) >= amount, + Error::::InsufficientAssetBalance + ); + + let pool_id = Self::get_pair_id(assets); + let pool_data = >::try_get(&pool_id).map_err(|_| Error::::PoolNotFound)?; + + ensure!(Self::is_pool_running(&pool_data), Error::::SaleIsNotRunning); + + let now = T::BlockNumberProvider::current_block_number(); + let (weight_in, weight_out) = Self::get_sorted_weight(assets.asset_in, now, &pool_data)?; + let asset_in_reserve = T::MultiCurrency::free_balance(assets.asset_in, &pool_id); + let asset_out_reserve = T::MultiCurrency::free_balance(assets.asset_out, &pool_id); + + ensure!( + amount + <= asset_in_reserve + .checked_div(T::MaxInRatio::get()) + .ok_or(Error::::Overflow)?, + Error::::MaxInRatioExceeded + ); + + // LBP fee asset is always accumulated asset + let fee_asset = pool_data.assets.0; + + // Accumulated asset is sold (in) to the pool for distributed asset (out) + // Take accumulated asset (in) sans fee from the seller and add to pool + // Take distributed asset (out) and send to seller + // Take fee from the seller and send to fee collector + // Pool bears repay fee + if fee_asset == assets.asset_in { + let fee = Self::calculate_fees(&pool_data, amount)?; + + let amount_out = hydra_dx_math::lbp::calculate_out_given_in( + asset_in_reserve, + asset_out_reserve, + weight_in, + weight_out, + amount, + ) + .map_err(|_| Error::::Overflow)?; + + ensure!( + amount_out + <= asset_out_reserve + .checked_div(T::MaxOutRatio::get()) + .ok_or(Error::::Overflow)?, + Error::::MaxOutRatioExceeded + ); + + ensure!(min_bought <= amount_out, Error::::TradingLimitReached); + + let amount_without_fee = amount.checked_sub(fee).ok_or(Error::::Overflow)?; + + Ok(AMMTransfer { + origin: who.clone(), + assets, + amount: amount_without_fee, + amount_b: amount_out, + discount: false, + discount_amount: 0_u128, + fee: (fee_asset, fee), + }) + + // Distributed asset is sold (in) to the pool for accumulated asset (out) + // Take accumulated asset (out) from the pool sans fee and send to the seller + // Take distributed asset (in) from the seller and send to pool + // Take fee from the pool and send to fee collector + // Seller bears repay fee + } else { + let calculated_out = hydra_dx_math::lbp::calculate_out_given_in( + asset_in_reserve, + asset_out_reserve, + weight_in, + weight_out, + amount, + ) + .map_err(|_| Error::::Overflow)?; + + let fee = Self::calculate_fees(&pool_data, calculated_out)?; + let amount_out_without_fee = calculated_out.checked_sub(fee).ok_or(Error::::Overflow)?; + + ensure!( + calculated_out + <= asset_out_reserve + .checked_div(T::MaxOutRatio::get()) + .ok_or(Error::::Overflow)?, + Error::::MaxOutRatioExceeded + ); + + ensure!(min_bought <= amount_out_without_fee, Error::::TradingLimitReached); + + Ok(AMMTransfer { + origin: who.clone(), + assets, + amount, + amount_b: amount_out_without_fee, + discount: false, + discount_amount: 0_u128, + fee: (fee_asset, fee), + }) + } + } + + fn execute_sell(transfer: &AMMTransfer) -> DispatchResult { + Self::execute_trade(transfer)?; + + // TODO: Deprecated, remove when ready + Self::deposit_event(Event::::SellExecuted { + who: transfer.origin.clone(), + asset_in: transfer.assets.asset_in, + asset_out: transfer.assets.asset_out, + amount: transfer.amount, + sale_price: transfer.amount_b, + fee_asset: transfer.fee.0, + fee_amount: transfer.fee.1, + }); + + let pool_account = Self::get_pair_id(transfer.assets); + let pool = >::try_get(&pool_account).map_err(|_| Error::::PoolNotFound)?; + + pallet_broadcast::Pallet::::deposit_trade_event( + transfer.origin.clone(), + pool_account, + pallet_broadcast::types::Filler::LBP, + pallet_broadcast::types::TradeOperation::ExactIn, + vec![Asset::new(transfer.assets.asset_in, transfer.amount)], + vec![Asset::new(transfer.assets.asset_out, transfer.amount_b)], + vec![Fee { + asset: transfer.fee.0, + amount: transfer.fee.1, + destination: Destination::Account(pool.fee_collector), + }], + ); + + Ok(()) + } + + fn validate_buy( + who: &T::AccountId, + assets: AssetPair, + amount: BalanceOf, + max_sold: BalanceOf, + _discount: bool, + ) -> Result, DispatchError> { + ensure!(!amount.is_zero(), Error::::ZeroAmount); + + let pool_id = Self::get_pair_id(assets); + let pool_data = >::try_get(&pool_id).map_err(|_| Error::::PoolNotFound)?; + + ensure!(Self::is_pool_running(&pool_data), Error::::SaleIsNotRunning); + + let now = T::BlockNumberProvider::current_block_number(); + let (weight_in, weight_out) = Self::get_sorted_weight(assets.asset_in, now, &pool_data)?; + let asset_in_reserve = T::MultiCurrency::free_balance(assets.asset_in, &pool_id); + let asset_out_reserve = T::MultiCurrency::free_balance(assets.asset_out, &pool_id); + + ensure!( + amount + <= asset_out_reserve + .checked_div(T::MaxOutRatio::get()) + .ok_or(Error::::Overflow)?, + Error::::MaxOutRatioExceeded + ); + + // LBP fee asset is always accumulated asset + let fee_asset = pool_data.assets.0; + + // Accumulated asset is bought (out) of the pool for distributed asset (in) + // Take accumulated asset (out) sans fee from the pool and send to seller + // Take distributed asset (in) from the seller and add to pool + // Take fee from the pool and send to fee collector + // Buyer bears repay fee + if fee_asset == assets.asset_out { + let fee = Self::calculate_fees(&pool_data, amount)?; + let amount_out_plus_fee = amount.checked_add(fee).ok_or(Error::::Overflow)?; + + let calculated_in = hydra_dx_math::lbp::calculate_in_given_out( + asset_in_reserve, + asset_out_reserve, + weight_in, + weight_out, + amount_out_plus_fee, + ) + .map_err(|_| Error::::Overflow)?; + + ensure!( + calculated_in + <= asset_in_reserve + .checked_div(T::MaxInRatio::get()) + .ok_or(Error::::Overflow)?, + Error::::MaxInRatioExceeded + ); + + ensure!( + T::MultiCurrency::free_balance(assets.asset_in, who) >= calculated_in, + Error::::InsufficientAssetBalance + ); + + ensure!(max_sold >= calculated_in, Error::::TradingLimitReached); + + Ok(AMMTransfer { + origin: who.clone(), + assets, + amount: calculated_in, + amount_b: amount, + discount: false, + discount_amount: 0_u128, + fee: (fee_asset, fee), + }) + + // Distributed asset is bought (out) of the pool for accumulated asset (in) + // Take accumulated asset (in) sans fee from the buyer and send to pool + // Take distributed asset (out) from the pool and send to buyer + // Take fee from the buyer and send to fee collector + // Pool bears repay fee + } else { + let calculated_in = hydra_dx_math::lbp::calculate_in_given_out( + asset_in_reserve, + asset_out_reserve, + weight_in, + weight_out, + amount, + ) + .map_err(|_| Error::::Overflow)?; + + let fee = Self::calculate_fees(&pool_data, calculated_in)?; + let calculated_in_without_fee = calculated_in.checked_sub(fee).ok_or(Error::::Overflow)?; + + ensure!( + calculated_in + <= asset_in_reserve + .checked_div(T::MaxInRatio::get()) + .ok_or(Error::::Overflow)?, + Error::::MaxInRatioExceeded + ); + + ensure!( + T::MultiCurrency::free_balance(assets.asset_in, who) >= calculated_in, + Error::::InsufficientAssetBalance + ); + + ensure!(max_sold >= calculated_in, Error::::TradingLimitReached); + + Ok(AMMTransfer { + origin: who.clone(), + assets, + amount: calculated_in_without_fee, + amount_b: amount, + discount: false, + discount_amount: 0_u128, + fee: (fee_asset, fee), + }) + } + } + + fn execute_buy( + transfer: &AMMTransfer>, + _destination: Option<&T::AccountId>, + ) -> DispatchResult { + Self::execute_trade(transfer)?; + + // TODO: Deprecated, remove when ready + Self::deposit_event(Event::::BuyExecuted { + who: transfer.origin.clone(), + asset_out: transfer.assets.asset_out, + asset_in: transfer.assets.asset_in, + amount: transfer.amount, + buy_price: transfer.amount_b, + fee_asset: transfer.fee.0, + fee_amount: transfer.fee.1, + }); + + let pool_account = Self::get_pair_id(transfer.assets); + let pool = >::try_get(&pool_account).map_err(|_| Error::::PoolNotFound)?; + + pallet_broadcast::Pallet::::deposit_trade_event( + transfer.origin.clone(), + pool_account, + pallet_broadcast::types::Filler::LBP, + pallet_broadcast::types::TradeOperation::ExactOut, + vec![Asset::new(transfer.assets.asset_in, transfer.amount)], + vec![Asset::new(transfer.assets.asset_out, transfer.amount_b)], + vec![Fee { + asset: transfer.fee.0, + amount: transfer.fee.1, + destination: Destination::Account(pool.fee_collector), + }], + ); + + Ok(()) + } + + fn get_min_trading_limit() -> Balance { + T::MinTradingLimit::get() + } + + fn get_min_pool_liquidity() -> Balance { + T::MinPoolLiquidity::get() + } + + fn get_max_in_ratio() -> u128 { + T::MaxInRatio::get() + } + + fn get_max_out_ratio() -> u128 { + T::MaxOutRatio::get() + } + + fn get_fee(pool_account_id: &T::AccountId) -> (u32, u32) { + let maybe_pool_data = >::get(pool_account_id); + match maybe_pool_data { + Some(pool_data) => pool_data.fee, + None => (0, 0), + } + } +} + +pub struct DisallowWhenLBPPoolRunning(sp_std::marker::PhantomData); + +impl CanCreatePool for DisallowWhenLBPPoolRunning { + fn can_create(asset_a: AssetId, asset_b: AssetId) -> bool { + let pool_id = Pallet::::pair_account_from_assets(asset_a, asset_b); + let now = T::BlockNumberProvider::current_block_number(); + match >::try_get(&pool_id) { + // returns true if the pool exists and the sale ended + Ok(data) => match data.end { + Some(end) => end < now, + None => false, + }, + _ => true, + } + } +} diff --git a/pallets/lbp/src/mock.rs b/pallets/lbp/src/mock.rs new file mode 100644 index 00000000000..eea51a7c081 --- /dev/null +++ b/pallets/lbp/src/mock.rs @@ -0,0 +1,282 @@ +use crate as lbp; +use crate::{ + types::{AssetId, AssetPair, Balance}, + AssetPairAccountIdFor, Config, Pool, WeightCurveType, +}; +use frame_support::parameter_types; +use frame_support::traits::{Everything, LockIdentifier, Nothing}; +use hydradx_traits::{AMMTransfer, LockedBalance}; +use orml_traits::parameter_type_with_key; +use sp_core::H256; +use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup, Zero}, + BuildStorage, +}; +use std::collections::BTreeMap; + +pub type Amount = i128; +pub type AccountId = u64; +pub type BlockNumber = u64; +type Block = frame_system::mocking::MockBlock; + +pub const INITIAL_BALANCE: Balance = 1_000_000_000_000_000u128; +pub const INITIAL_ETH_BALANCE: Balance = 1_000_000_000_000_000_000_000u128; + +pub const ALICE: AccountId = 1; +pub const BOB: AccountId = 2; +pub const CHARLIE: AccountId = 3; + +pub const HDX: AssetId = 0; +pub const KUSD: AssetId = 2_000; +pub const BSX: AssetId = 3_000; +pub const ETH: AssetId = 4_000; + +pub const EXISTENTIAL_DEPOSIT: Balance = 100; +pub const SALE_START: Option = Some(10); +pub const SALE_END: Option = Some(40); + +pub const HDX_BSX_POOL_ID: AccountId = 3_000; +pub const KUSD_BSX_POOL_ID: AccountId = 2_003_000; + +pub const DEFAULT_FEE: (u32, u32) = (2, 1_000); + +pub const SAMPLE_POOL_DATA: Pool = Pool { + owner: ALICE, + start: SALE_START, + end: SALE_END, + assets: (KUSD, BSX), + initial_weight: 10_000_000, + final_weight: 90_000_000, + weight_curve: WeightCurveType::Linear, + fee: DEFAULT_FEE, + fee_collector: CHARLIE, + repay_target: 0, +}; + +pub const SAMPLE_AMM_TRANSFER: AMMTransfer = AMMTransfer { + origin: ALICE, + assets: AssetPair { + asset_in: KUSD, + asset_out: BSX, + }, + amount: 1000, + amount_b: 10000, + discount: false, + discount_amount: 0_u128, + fee: (KUSD, 200), +}; + +frame_support::construct_runtime!( + pub enum Test + { + System: frame_system, + LBPPallet: lbp, + Currency: orml_tokens, + Broadcast: pallet_broadcast, + } + +); + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 63; +} + +impl frame_system::Config for Test { + type BaseCallFilter = Everything; + type BlockWeights = (); + type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; + type Nonce = u64; + type Block = Block; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; + type SingleBlockMigrations = (); + type MultiBlockMigrator = (); + type PreInherents = (); + type PostInherents = (); + type PostTransactions = (); + type ExtensionsWeightInfo = (); +} + +parameter_type_with_key! { + pub ExistentialDeposits: |_currency_id: AssetId| -> Balance { + EXISTENTIAL_DEPOSIT + }; +} + +parameter_types! { + pub const MaxLocks: u32 = 1; +} + +impl orml_tokens::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type Amount = Amount; + type CurrencyId = AssetId; + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; + type MaxLocks = MaxLocks; + type DustRemovalWhitelist = Nothing; + type ReserveIdentifier = (); + type MaxReserves = (); + type CurrencyHooks = (); +} + +pub struct AssetPairAccountIdTest(); + +impl AssetPairAccountIdFor for AssetPairAccountIdTest { + fn from_assets(asset_a: AssetId, asset_b: AssetId, _: &str) -> u64 { + let mut a = asset_a as u128; + let mut b = asset_b as u128; + if a > b { + std::mem::swap(&mut a, &mut b); + } + (a * 1000 + b) as u64 + } +} + +parameter_types! { + pub const NativeAssetId: AssetId = HDX; + pub const MinTradingLimit: Balance = 1_000; + pub const MinPoolLiquidity: Balance = 1_000; + pub const MaxInRatio: u128 = 3; + pub const MaxOutRatio: u128 = 3; +} + +pub struct MultiLockedBalance(); + +impl LockedBalance for MultiLockedBalance { + fn get_by_lock(lock_id: LockIdentifier, asset: AssetId, account: AccountId) -> Balance { + match Currency::locks(account, asset) + .into_iter() + .find(|lock| lock.id == lock_id) + { + Some(lock) => lock.amount, + None => Zero::zero(), + } + } +} + +impl pallet_broadcast::Config for Test { + type RuntimeEvent = RuntimeEvent; +} + +impl Config for Test { + type RuntimeEvent = RuntimeEvent; + type MultiCurrency = Currency; + type LockedBalance = MultiLockedBalance; + type CreatePoolOrigin = frame_system::EnsureRoot; + type LBPWeightFunction = lbp::LBPWeightFunction; + type AssetPairAccountId = AssetPairAccountIdTest; + type WeightInfo = (); + type MinTradingLimit = MinTradingLimit; + type MinPoolLiquidity = MinPoolLiquidity; + type MaxInRatio = MaxInRatio; + type MaxOutRatio = MaxOutRatio; + type BlockNumberProvider = System; +} + +pub struct ExtBuilder { + endowed_accounts: Vec<(AccountId, AssetId, Balance)>, +} + +impl Default for ExtBuilder { + fn default() -> Self { + Self { + endowed_accounts: vec![ + (ALICE, HDX, INITIAL_BALANCE), + (ALICE, BSX, INITIAL_BALANCE), + (ALICE, KUSD, INITIAL_BALANCE), + (ALICE, ETH, INITIAL_ETH_BALANCE), + (BOB, HDX, INITIAL_BALANCE), + (BOB, BSX, INITIAL_BALANCE), + (BOB, KUSD, INITIAL_BALANCE), + (BOB, ETH, INITIAL_ETH_BALANCE), + ], + } + } +} + +impl ExtBuilder { + pub fn with_endowed_accounts(mut self, accounts: Vec<(AccountId, AssetId, Balance)>) -> Self { + self.endowed_accounts.extend_from_slice(&accounts); + self + } + + pub fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + + orml_tokens::GenesisConfig:: { + balances: self.endowed_accounts, + } + .assimilate_storage(&mut t) + .unwrap(); + + t.into() + } +} + +pub fn set_block_number(n: u64) { + frame_system::Pallet::::set_block_number(n); +} + +pub fn run_to_sale_start() { + set_block_number(SALE_START.unwrap()); +} + +pub fn run_to_sale_end() { + set_block_number(SALE_END.unwrap() + 1); +} + +pub fn generate_trades( + start: BlockNumber, + end: BlockNumber, + sale_rate: u128, + sell_ratio: u128, +) -> BTreeMap { + let mut trades = BTreeMap::new(); + let intervals: u64 = 72; + + let buy_amount = sale_rate / 24; + let sell_amount = sale_rate / sell_ratio / 24; + + let skip = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + let sells = [19, 20, 21, 33, 34, 35, 48, 49, 50, 62, 63, 64]; + for i in 0..=intervals { + let block_num = start + (i * ((end - start) / intervals)); + + if skip.contains(&i) { + continue; + } + + let (is_buy, amount) = if sells.contains(&i) { + (false, sell_amount) + } else { + (true, buy_amount) + }; + + trades.insert(block_num, (is_buy, amount)); + } + trades +} + +pub fn expect_events(e: Vec) { + test_utils::expect_events::(e); +} diff --git a/pallets/lbp/src/provider.rs b/pallets/lbp/src/provider.rs new file mode 100644 index 00000000000..8ff41f9ef34 --- /dev/null +++ b/pallets/lbp/src/provider.rs @@ -0,0 +1,45 @@ +use crate::{AssetId, AssetPair, Config, Pallet, PoolData}; +use hydra_dx_math::types::Price; +use hydradx_traits::pools::SpotPriceProvider; +use hydradx_traits::AMM; +use orml_traits::MultiCurrency; +use sp_runtime::traits::{BlockNumberProvider, One}; +use sp_runtime::{FixedPointNumber, FixedU128}; + +impl SpotPriceProvider for Pallet { + type Price = FixedU128; + + fn pair_exists(asset_a: AssetId, asset_b: AssetId) -> bool { + Self::exists(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }) + } + + fn spot_price(asset_a: AssetId, asset_b: AssetId) -> Option { + if asset_a == asset_b { + return Some(FixedU128::one()); + } + + if Self::pair_exists(asset_a, asset_b) { + let pair_account = >::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + + let now = T::BlockNumberProvider::current_block_number(); + let pool_data = >::try_get(&pair_account).ok()?; + let (weight_in, weight_out) = Self::get_sorted_weight(asset_a, now, &pool_data).ok()?; + + let asset_in_reserve = T::MultiCurrency::free_balance(asset_a, &pair_account); + let asset_out_reserve = T::MultiCurrency::free_balance(asset_b, &pair_account); + + let n = asset_in_reserve.checked_mul(weight_out.into())?; + let d = asset_out_reserve.checked_mul(weight_in.into())?; + + Price::checked_from_rational(n, d) + } else { + None + } + } +} diff --git a/pallets/lbp/src/tests.rs b/pallets/lbp/src/tests.rs new file mode 100644 index 00000000000..b3b6204ae4c --- /dev/null +++ b/pallets/lbp/src/tests.rs @@ -0,0 +1,4177 @@ +// This file is part of HydraDX-node. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![allow(clippy::bool_assert_comparison)] +#![allow(clippy::excessive_precision)] + +use super::*; +use crate::mock::{ + expect_events, generate_trades, run_to_sale_end, run_to_sale_start, AccountId, RuntimeCall as Call, DEFAULT_FEE, + EXISTENTIAL_DEPOSIT, HDX_BSX_POOL_ID, INITIAL_BALANCE, INITIAL_ETH_BALANCE, KUSD_BSX_POOL_ID, SALE_END, SALE_START, + SAMPLE_AMM_TRANSFER, SAMPLE_POOL_DATA, +}; +pub use crate::mock::{ + set_block_number, Currency, ExtBuilder, LBPPallet, RuntimeOrigin as Origin, Test, ALICE, BOB, BSX, CHARLIE, ETH, + HDX, KUSD, +}; +use frame_support::{assert_err, assert_noop, assert_ok}; +use hydradx_traits::{AMMTransfer, LockedBalance}; +use pallet_broadcast::types::Destination; +use sp_runtime::traits::{BadOrigin, Dispatchable}; +use sp_std::convert::TryInto; + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut ext = ExtBuilder::default().build(); + ext.execute_with(|| set_block_number(1)); + ext +} + +pub fn predefined_test_ext() -> sp_io::TestExternalities { + let mut ext = new_test_ext(); + ext.execute_with(|| { + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 1_000_000_000, + BSX, + 2_000_000_000, + 20_000_000, + 80_000_000, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + )); + + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + SALE_START, + SALE_END, + None, + None, + None, + None, + None, + )); + + let pool_data2 = Pool { + owner: ALICE, + start: SALE_START, + end: SALE_END, + assets: (KUSD, BSX), + initial_weight: 20_000_000, + final_weight: 80_000_000, + weight_curve: WeightCurveType::Linear, + fee: DEFAULT_FEE, + fee_collector: CHARLIE, + repay_target: 0, + }; + + assert_eq!(>::get(KUSD_BSX_POOL_ID).unwrap(), pool_data2); + + expect_events(vec![ + Event::LiquidityAdded { + who: KUSD_BSX_POOL_ID, + asset_a: KUSD, + asset_b: BSX, + amount_a: 1_000_000_000, + amount_b: 2_000_000_000, + } + .into(), + Event::PoolUpdated { + pool: KUSD_BSX_POOL_ID, + data: pool_data2, + } + .into(), + ]); + }); + ext +} + +pub fn predefined_test_ext_with_repay_target() -> sp_io::TestExternalities { + let mut ext = new_test_ext(); + ext.execute_with(|| { + let initial_liquidity = 1_000_000_000; + + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 1_000_000_000, + BSX, + 2_000_000_000, + 80_000_000, + 20_000_000, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + initial_liquidity, + )); + + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + SALE_START, + Some(20), + None, + None, + None, + None, + None, + )); + + assert_ok!(LBPPallet::add_liquidity( + Origin::signed(ALICE), + (KUSD, 10_000_000_000), + (BSX, initial_liquidity), + )); + }); + ext +} + +pub fn start_50_50_lbp_without_fee_and_repay_target( + asset_in: AssetId, + reserve_in: Balance, + asset_out: AssetId, + reserve_out: Balance, +) -> AccountId { + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + asset_in, + reserve_in, + asset_out, + reserve_out, + 50_000_000, + 50_000_000, + WeightCurveType::Linear, + (0, 1), + CHARLIE, + 0, + )); + + let pool_id = LBPPallet::get_pair_id(AssetPair { asset_in, asset_out }); + + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + pool_id, + None, + SALE_START, + SALE_END, + None, + None, + None, + None, + None, + )); + + //start sale + set_block_number(11); + + pool_id +} + +#[test] +fn default_locked_balance_should_be_zero() { + new_test_ext().execute_with(|| { + assert_eq!( + ::LockedBalance::get_by_lock(COLLECTOR_LOCK_ID, BSX, BOB), + 0_u128 + ); + }); +} + +#[test] +fn validate_pool_data_should_work() { + new_test_ext().execute_with(|| { + let pool_data = Pool { + owner: ALICE, + start: SALE_START, + end: SALE_END, + assets: (KUSD, BSX), + initial_weight: 20_000_000, + final_weight: 90_000_000, + weight_curve: WeightCurveType::Linear, + fee: DEFAULT_FEE, + fee_collector: CHARLIE, + repay_target: 0, + }; + assert_ok!(LBPPallet::validate_pool_data(&pool_data)); + + // null interval + let pool_data = Pool { + owner: ALICE, + start: None, + end: None, + assets: (KUSD, BSX), + initial_weight: 20_000_000, + final_weight: 90_000_000, + weight_curve: WeightCurveType::Linear, + fee: DEFAULT_FEE, + fee_collector: CHARLIE, + repay_target: 0, + }; + assert_ok!(LBPPallet::validate_pool_data(&pool_data)); + + let pool_data = Pool { + owner: ALICE, + start: SALE_START, + end: Some(2u64), + assets: (KUSD, BSX), + initial_weight: 20_000_000, + final_weight: 90_000_000, + weight_curve: WeightCurveType::Linear, + fee: DEFAULT_FEE, + fee_collector: CHARLIE, + repay_target: 0, + }; + assert_noop!( + LBPPallet::validate_pool_data(&pool_data), + Error::::InvalidBlockRange + ); + + let pool_data = Pool { + owner: ALICE, + start: SALE_START, + end: Some(11u64 + u32::MAX as u64), + assets: (KUSD, BSX), + initial_weight: 20_000_000, + final_weight: 90_000_000, + weight_curve: WeightCurveType::Linear, + fee: DEFAULT_FEE, + fee_collector: CHARLIE, + repay_target: 0, + }; + assert_noop!( + LBPPallet::validate_pool_data(&pool_data), + Error::::MaxSaleDurationExceeded + ); + }); +} + +#[test] +fn max_sale_duration_ckeck() { + new_test_ext().execute_with(|| { + assert_ok!(LBPPallet::validate_pool_data(&Pool { + owner: ALICE, + start: SALE_START, + end: Some(SALE_START.unwrap() + MAX_SALE_DURATION as u64 - 1), + assets: (KUSD, BSX), + initial_weight: 20_000_000, + final_weight: 90_000_000, + weight_curve: WeightCurveType::Linear, + fee: DEFAULT_FEE, + fee_collector: CHARLIE, + repay_target: 0, + })); + assert_noop!( + LBPPallet::validate_pool_data(&Pool { + owner: ALICE, + start: SALE_START, + end: Some(SALE_START.unwrap() + MAX_SALE_DURATION as u64), + assets: (KUSD, BSX), + initial_weight: 20_000_000, + final_weight: 90_000_000, + weight_curve: WeightCurveType::Linear, + fee: DEFAULT_FEE, + fee_collector: CHARLIE, + repay_target: 0, + }), + Error::::MaxSaleDurationExceeded + ); + }); +} + +#[test] +fn calculate_weights_should_work() { + new_test_ext().execute_with(|| { + let mut pool_data = Pool { + owner: ALICE, + start: Some(100), + end: Some(200), + assets: (KUSD, BSX), + initial_weight: 50_000_000, + final_weight: 33_333_333, + weight_curve: WeightCurveType::Linear, + fee: DEFAULT_FEE, + fee_collector: CHARLIE, + repay_target: 0, + }; + assert_eq!(LBPPallet::calculate_weights(&pool_data, 170), Ok((38333333, 61666667))); + + pool_data.initial_weight = 33_333_333; + pool_data.final_weight = 66_666_666; + assert_eq!(LBPPallet::calculate_weights(&pool_data, 100), Ok((33333333, 66666667))); + + pool_data.initial_weight = 33_333_333; + pool_data.final_weight = 33_333_333; + assert_eq!(LBPPallet::calculate_weights(&pool_data, 100), Ok((33333333, 66666667))); + + pool_data.initial_weight = 50_000_000; + pool_data.final_weight = 33_333_333; + assert_eq!(LBPPallet::calculate_weights(&pool_data, 200), Ok((33333333, 66666667))); + + // invalid interval + pool_data.start = Some(200); + pool_data.end = Some(100); + assert_eq!( + LBPPallet::calculate_weights(&pool_data, 200), + Err(Error::::WeightCalculationError.into()) + ); + + // invalid interval + pool_data.start = Some(100); + pool_data.end = Some(200); + assert_eq!( + LBPPallet::calculate_weights(&pool_data, 201), + Err(Error::::WeightCalculationError.into()) + ); + + // out of bound + pool_data.start = Some(100); + pool_data.end = Some(200); + assert_eq!( + LBPPallet::calculate_weights(&pool_data, 10), + Err(Error::::WeightCalculationError.into()) + ); + assert_eq!( + LBPPallet::calculate_weights(&pool_data, 210), + Err(Error::::WeightCalculationError.into()) + ); + }); +} + +#[test] +fn create_pool_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 1_000_000_000, + BSX, + 2_000_000_000, + 20_000_000u32, + 90_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + )); + + assert_eq!(Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID), 1_000_000_000); + assert_eq!(Currency::free_balance(BSX, &KUSD_BSX_POOL_ID), 2_000_000_000); + assert_eq!( + Currency::free_balance(KUSD, &ALICE), + INITIAL_BALANCE.saturating_sub(1_000_000_000) + ); + assert_eq!( + Currency::free_balance(BSX, &ALICE), + INITIAL_BALANCE.saturating_sub(2_000_000_000) + ); + + let pool_data = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + assert_eq!(pool_data.owner, ALICE); + assert_eq!(pool_data.start, None); + assert_eq!(pool_data.end, None); + assert_eq!(pool_data.assets, (KUSD, BSX)); + assert_eq!(pool_data.initial_weight, 20_000_000); + assert_eq!(pool_data.final_weight, 90_000_000); + assert_eq!(pool_data.weight_curve, WeightCurveType::Linear); + assert_eq!(pool_data.fee, DEFAULT_FEE); + assert_eq!(pool_data.fee_collector, CHARLIE); + + assert!(>::contains_key(CHARLIE, KUSD)); + + expect_events(vec![Event::LiquidityAdded { + who: KUSD_BSX_POOL_ID, + asset_a: KUSD, + asset_b: BSX, + amount_a: 1_000_000_000, + amount_b: 2_000_000_000, + } + .into()]); + }); +} + +#[test] +fn create_pool_from_basic_origin_should_not_work() { + new_test_ext().execute_with(|| { + // only CreatePoolOrigin is allowed to create new pools + assert_noop!( + LBPPallet::create_pool( + Origin::signed(ALICE), + ALICE, + HDX, + 1_000_000_000, + BSX, + 2_000_000_000, + 80_000_000u32, + 10_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + ), + BadOrigin + ); + }); +} + +#[test] +fn create_same_pool_should_not_work() { + new_test_ext().execute_with(|| { + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 1_000_000_000, + BSX, + 2_000_000_000, + 80_000_000u32, + 10_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + )); + + assert_noop!( + LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 10_000_000_000, + BSX, + 20_000_000_000, + 80_000_000u32, + 10_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + ), + Error::::PoolAlreadyExists + ); + + expect_events(vec![Event::LiquidityAdded { + who: KUSD_BSX_POOL_ID, + asset_a: KUSD, + asset_b: BSX, + amount_a: 1_000_000_000, + amount_b: 2_000_000_000, + } + .into()]); + }); +} + +#[test] +fn create_pool_with_same_assets_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 1_000_000_000, + KUSD, + 2_000_000_000, + 80_000_000u32, + 10_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + ), + Error::::CannotCreatePoolWithSameAssets + ); + }); +} + +#[test] +fn create_pool_with_non_existing_fee_collector_with_asset_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 1_000_000_000, + BSX, + 2_000_000_000, + 20_000_000u32, + 90_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + )); + + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + HDX, + 1_000_000_000, + BSX, + 2_000_000_000, + 20_000_000u32, + 90_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + ),); + }); +} + +#[test] +fn create_pool_with_existing_fee_collector_with_asset_should_not_work() { + new_test_ext().execute_with(|| { + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 1_000_000_000, + BSX, + 2_000_000_000, + 20_000_000u32, + 90_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + )); + + assert_noop!( + LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 1_000_000_000, + HDX, + 2_000_000_000, + 20_000_000u32, + 90_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + ), + Error::::FeeCollectorWithAssetAlreadyUsed + ); + }); +} + +#[test] +fn create_pool_with_insufficient_liquidity_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::create_pool( + Origin::root(), + ALICE, + HDX, + 0, + BSX, + 0, + 80_000_000u32, + 10_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + ), + Error::::InsufficientLiquidity + ); + + assert_noop!( + LBPPallet::create_pool( + Origin::root(), + ALICE, + HDX, + 0, + BSX, + 2_000_000_000, + 80_000_000u32, + 10_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + ), + Error::::InsufficientLiquidity + ); + + assert_noop!( + LBPPallet::create_pool( + Origin::root(), + ALICE, + HDX, + 100, + BSX, + 100, + 80_000_000u32, + 10_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + ), + Error::::InsufficientLiquidity + ); + }); +} + +#[test] +fn create_pool_with_insufficient_balance_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 2_000_000_000_000_000, + BSX, + 2_000_000_000_000_000, + 80_000_000u32, + 10_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + ), + Error::::InsufficientAssetBalance + ); + }); +} + +#[test] +fn update_pool_data_should_work() { + predefined_test_ext().execute_with(|| { + // update all parameters + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + Some(15), + Some(18), + Some(10_000_000), + Some(80_000_000), + Some((5, 100)), + Some(BOB), + None, + )); + + // verify changes + let updated_pool_data_1 = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + assert_eq!(updated_pool_data_1.start, Some(15)); + assert_eq!(updated_pool_data_1.end, Some(18)); + assert_eq!(updated_pool_data_1.initial_weight, 10_000_000); + assert_eq!(updated_pool_data_1.final_weight, 80_000_000); + assert_eq!(updated_pool_data_1.fee, (5, 100),); + assert_eq!(updated_pool_data_1.fee_collector, BOB); + + // removes old fee collector from store and + // sets updated fee collector + assert!(!>::contains_key(CHARLIE, KUSD)); + assert!(>::contains_key(BOB, KUSD)); + + // update only one parameter + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + None, + Some(30), + None, + None, + None, + None, + None, + )); + + // verify changes + let updated_pool_data_2 = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + assert_eq!(updated_pool_data_2.start, Some(15)); + assert_eq!(updated_pool_data_2.end, Some(30)); + assert_eq!(updated_pool_data_2.initial_weight, 10_000_000); + assert_eq!(updated_pool_data_2.final_weight, 80_000_000); + assert_eq!(updated_pool_data_2.fee, (5, 100),); + assert_eq!(updated_pool_data_2.fee_collector, BOB); + + // update only one parameter + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + None, + None, + Some(12_500_000), + None, + None, + None, + None, + )); + + // verify changes + let updated_pool_data_3 = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + assert_eq!(updated_pool_data_3.start, Some(15)); + assert_eq!(updated_pool_data_3.end, Some(30)); + assert_eq!(updated_pool_data_3.initial_weight, 12_500_000); + assert_eq!(updated_pool_data_3.final_weight, 80_000_000); + assert_eq!(updated_pool_data_3.fee, (5, 100),); + assert_eq!(updated_pool_data_3.fee_collector, BOB); + + // update only one parameter + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + None, + None, + None, + None, + None, + Some(ALICE), + None, + )); + + // verify changes + let updated_pool_data_4 = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + assert_eq!(updated_pool_data_4.start, Some(15)); + assert_eq!(updated_pool_data_4.end, Some(30)); + assert_eq!(updated_pool_data_4.initial_weight, 12_500_000); + assert_eq!(updated_pool_data_4.final_weight, 80_000_000); + assert_eq!(updated_pool_data_4.fee, (5, 100),); + assert_eq!(updated_pool_data_4.fee_collector, ALICE); + + // mix + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + None, + Some(18), + Some(10_000_000), + Some(80_000_000), + Some((6, 1_000)), + None, + None, + )); + + // verify changes + let updated_pool_data_5 = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + assert_eq!(updated_pool_data_5.start, Some(15)); + assert_eq!(updated_pool_data_5.end, Some(18)); + assert_eq!(updated_pool_data_5.initial_weight, 10_000_000); + assert_eq!(updated_pool_data_5.final_weight, 80_000_000); + assert_eq!(updated_pool_data_5.fee, (6, 1_000),); + assert_eq!(updated_pool_data_5.fee_collector, ALICE); + + // set repay target + let repayment = 1_000_000; + assert_eq!(updated_pool_data_5.repay_target, 0); + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + None, + None, + None, + None, + None, + None, + Some(repayment), + )); + let updated_pool_data_6 = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + assert_eq!(updated_pool_data_6.repay_target, repayment); + + expect_events(vec![ + Event::PoolUpdated { + pool: KUSD_BSX_POOL_ID, + data: updated_pool_data_1, + } + .into(), + Event::PoolUpdated { + pool: KUSD_BSX_POOL_ID, + data: updated_pool_data_2, + } + .into(), + Event::PoolUpdated { + pool: KUSD_BSX_POOL_ID, + data: updated_pool_data_3, + } + .into(), + Event::PoolUpdated { + pool: KUSD_BSX_POOL_ID, + data: updated_pool_data_4, + } + .into(), + Event::PoolUpdated { + pool: KUSD_BSX_POOL_ID, + data: updated_pool_data_5, + } + .into(), + Event::PoolUpdated { + pool: KUSD_BSX_POOL_ID, + data: updated_pool_data_6, + } + .into(), + ]); + }); +} + +#[test] +fn update_non_existing_pool_data_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + Some(15), + Some(18), + Some(10_000_000), + Some(80_000_000), + Some((5, 100)), + None, + None, + ), + Error::::PoolNotFound + ); + }); +} + +#[test] +fn update_pool_with_invalid_data_should_not_work() { + predefined_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + // reversed interval, the end precedes the beginning + Some(20), + Some(10), + Some(10_000_000), + Some(80_000_000), + Some((5, 100)), + None, + None, + ), + Error::::InvalidBlockRange + ); + + set_block_number(6); + + assert_noop!( + LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + Some(5), + Some(20), + Some(10_000_000), + Some(80_000_000), + Some((5, 100)), + None, + None, + ), + Error::::InvalidBlockRange + ); + + assert_noop!( + LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + Some(0), + Some(20), + Some(10_000_000), + Some(80_000_000), + Some((5, 100)), + None, + None, + ), + Error::::InvalidBlockRange + ); + + assert_noop!( + LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + Some(5), + Some(0), + Some(10_000_000), + Some(80_000_000), + Some((5, 100)), + None, + None, + ), + Error::::InvalidBlockRange + ); + }); +} + +#[test] +fn update_pool_data_without_changes_should_not_work() { + predefined_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + None, + None, + None, + None, + None, + None, + None, + ), + Error::::NothingToUpdate + ); + }); +} + +#[test] +fn update_pool_data_by_non_owner_should_not_work() { + predefined_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::update_pool_data( + Origin::signed(BOB), + KUSD_BSX_POOL_ID, + None, + Some(15), + Some(20), + Some(10_000_000), + Some(80_000_000), + None, + None, + None, + ), + Error::::NotOwner + ); + }); +} + +#[test] +fn update_pool_owner_by_new_owner_should_work() { + predefined_test_ext().execute_with(|| { + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + Some(BOB), + Some(15), + Some(20), + Some(10_000_000), + Some(80_000_000), + None, + None, + None, + )); + + let pool_data1 = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(BOB), + KUSD_BSX_POOL_ID, + Some(ALICE), + Some(15), + Some(20), + Some(10_000_000), + Some(80_000_000), + None, + None, + None, + )); + + let pool_data2 = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + + expect_events(vec![ + Event::PoolUpdated { + pool: KUSD_BSX_POOL_ID, + data: pool_data1, + } + .into(), + Event::PoolUpdated { + pool: KUSD_BSX_POOL_ID, + data: pool_data2, + } + .into(), + ]); + }); +} + +#[test] +fn update_pool_data_for_running_lbp_should_not_work() { + predefined_test_ext().execute_with(|| { + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + Some(15), + Some(20), + None, + None, + None, + None, + None, + )); + + set_block_number(16); + + // update starting block and final weights + assert_noop!( + LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + Some(15), + Some(30), + Some(10_000_000), + Some(80_000_000), + Some((5, 100)), + Some(BOB), + None, + ), + Error::::SaleStarted + ); + + let pool_data = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + + expect_events(vec![Event::PoolUpdated { + pool: KUSD_BSX_POOL_ID, + data: pool_data, + } + .into()]); + }); +} + +#[test] +fn update_pool_with_existing_fee_collector_should_not_work() { + predefined_test_ext().execute_with(|| { + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 1_000_000_000, + HDX, + 2_000_000_000, + 20_000_000u32, + 90_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + BOB, + 0, + )); + + assert_noop!( + LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + Some(15), + Some(18), + Some(10_000_000), + Some(80_000_000), + Some((5, 100)), + Some(BOB), + None, + ), + Error::::FeeCollectorWithAssetAlreadyUsed + ); + }); +} + +#[test] +fn update_pool_interval_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 1_000_000_000, + BSX, + 2_000_000_000, + 10_000_000, + 10_000_000, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + )); + + set_block_number(15); + + assert_noop!( + LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + Some(16), + Some(0), + None, + None, + None, + None, + None, + ), + Error::::InvalidBlockRange + ); + + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + Some(16), + Some(20), + None, + None, + None, + None, + None, + )); + + // verify changes + let updated_pool_data = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + assert_eq!(updated_pool_data.start, Some(16)); + assert_eq!(updated_pool_data.end, Some(20)); + + expect_events(vec![ + Event::LiquidityAdded { + who: KUSD_BSX_POOL_ID, + asset_a: KUSD, + asset_b: BSX, + amount_a: 1_000_000_000, + amount_b: 2_000_000_000, + } + .into(), + Event::PoolUpdated { + pool: KUSD_BSX_POOL_ID, + data: updated_pool_data, + } + .into(), + ]); + }); +} + +#[test] +fn add_liquidity_should_work() { + predefined_test_ext().execute_with(|| { + let user_balance_a_before = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_before = Currency::free_balance(BSX, &ALICE); + let pool_balance_a_before = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_before = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + let added_a = 10_000_000_000; + let added_b = 20_000_000_000; + + assert_ok!(LBPPallet::add_liquidity( + Origin::signed(ALICE), + (KUSD, added_a), + (BSX, added_b), + )); + + expect_events(vec![Event::LiquidityAdded { + who: KUSD_BSX_POOL_ID, + asset_a: KUSD, + asset_b: BSX, + amount_a: added_a, + amount_b: added_b, + } + .into()]); + + let pool_balance_a_after = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_after = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + assert_eq!(pool_balance_a_after, pool_balance_a_before.saturating_add(added_a)); + assert_eq!(pool_balance_b_after, pool_balance_b_before.saturating_add(added_b)); + + let user_balance_a_after = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_after = Currency::free_balance(BSX, &ALICE); + assert_eq!(user_balance_a_after, user_balance_a_before.saturating_sub(added_a)); + assert_eq!(user_balance_b_after, user_balance_b_before.saturating_sub(added_b)); + + let user_balance_a_before = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_before = Currency::free_balance(BSX, &ALICE); + let pool_balance_a_before = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_before = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_ok!(LBPPallet::add_liquidity( + Origin::signed(ALICE), + (KUSD, added_a), + (BSX, 0), + )); + + expect_events(vec![Event::LiquidityAdded { + who: KUSD_BSX_POOL_ID, + asset_a: KUSD, + asset_b: BSX, + amount_a: added_a, + amount_b: 0, + } + .into()]); + + let pool_balance_a_after = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_after = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + assert_eq!(pool_balance_a_after, pool_balance_a_before.saturating_add(added_a)); + assert_eq!(pool_balance_b_after, pool_balance_b_before); + + let user_balance_a_after = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_after = Currency::free_balance(BSX, &ALICE); + assert_eq!(user_balance_a_after, user_balance_a_before.saturating_sub(added_a)); + assert_eq!(user_balance_b_after, user_balance_b_before); + + // change asset order + let user_balance_a_before = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_before = Currency::free_balance(BSX, &ALICE); + let pool_balance_a_before = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_before = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_ok!(LBPPallet::add_liquidity( + Origin::signed(ALICE), + (BSX, added_b), + (KUSD, added_a), + )); + + let pool_balance_a_after = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_after = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + assert_eq!(pool_balance_a_after, pool_balance_a_before.saturating_add(added_a)); + assert_eq!(pool_balance_b_after, pool_balance_b_before.saturating_add(added_b)); + + let user_balance_a_after = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_after = Currency::free_balance(BSX, &ALICE); + assert_eq!(user_balance_a_after, user_balance_a_before.saturating_sub(added_a)); + assert_eq!(user_balance_b_after, user_balance_b_before.saturating_sub(added_b)); + + expect_events(vec![Event::LiquidityAdded { + who: KUSD_BSX_POOL_ID, + asset_a: BSX, + asset_b: KUSD, + amount_a: added_b, + amount_b: added_a, + } + .into()]); + }); +} + +#[test] +fn add_liquidity_by_non_owner_should_not_work() { + predefined_test_ext().execute_with(|| { + assert_eq!(Currency::free_balance(KUSD, &BOB), 1000000000000000); + assert_eq!(Currency::free_balance(BSX, &BOB), 1000000000000000); + + assert_eq!(Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID), 1_000_000_000); + assert_eq!(Currency::free_balance(BSX, &KUSD_BSX_POOL_ID), 2_000_000_000); + + assert_noop!( + LBPPallet::add_liquidity(Origin::signed(BOB), (KUSD, 10_000_000_000), (BSX, 20_000_000_000),), + Error::::NotOwner + ); + }); +} + +#[test] +fn add_zero_liquidity_should_not_work() { + predefined_test_ext().execute_with(|| { + let user_balance_a_before = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_before = Currency::free_balance(BSX, &ALICE); + + let pool_balance_a_before = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_before = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_noop!( + LBPPallet::add_liquidity(Origin::signed(ALICE), (KUSD, 0), (BSX, 0),), + Error::::CannotAddZeroLiquidity + ); + + let pool_balance_a_after = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_after = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_eq!(pool_balance_a_after, pool_balance_a_before); + assert_eq!(pool_balance_b_after, pool_balance_b_before); + + let user_balance_a_after = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_after = Currency::free_balance(BSX, &ALICE); + assert_eq!(user_balance_a_after, user_balance_a_before); + assert_eq!(user_balance_b_after, user_balance_b_before); + + // No new events expected + expect_events(vec![]); + }); +} + +#[test] +fn add_liquidity_with_insufficient_balance_should_not_work() { + predefined_test_ext().execute_with(|| { + let user_balance_a_before = Currency::free_balance(KUSD, &ALICE); + + let pool_balance_a_before = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_before = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_noop!( + LBPPallet::add_liquidity(Origin::signed(ALICE), (KUSD, u128::MAX), (BSX, 0),), + Error::::InsufficientAssetBalance + ); + + let pool_balance_a_after = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_after = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_eq!(pool_balance_a_after, pool_balance_a_before); + assert_eq!(pool_balance_b_after, pool_balance_b_before); + + let user_balance_a_after = Currency::free_balance(KUSD, &ALICE); + assert_eq!(user_balance_a_after, user_balance_a_before); + }); +} + +#[test] +fn add_liquidity_after_sale_started_should_work() { + predefined_test_ext().execute_with(|| { + set_block_number(15); + + let user_balance_a_before = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_before = Currency::free_balance(BSX, &ALICE); + + let pool_balance_a_before = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_before = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_ok!(LBPPallet::add_liquidity( + Origin::signed(ALICE), + (KUSD, 1_000), + (BSX, 1_000), + )); + + expect_events(vec![Event::LiquidityAdded { + who: KUSD_BSX_POOL_ID, + asset_a: KUSD, + asset_b: BSX, + amount_a: 1_000, + amount_b: 1_000, + } + .into()]); + + let pool_balance_a_after = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_after = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_eq!(pool_balance_a_after, pool_balance_a_before.saturating_add(1_000)); + assert_eq!(pool_balance_b_after, pool_balance_b_before.saturating_add(1_000)); + + let user_balance_a_after = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_after = Currency::free_balance(BSX, &ALICE); + + assert_eq!(user_balance_a_after, user_balance_a_before.saturating_sub(1_000)); + assert_eq!(user_balance_b_after, user_balance_b_before.saturating_sub(1_000)); + + // sale ended at the block number 20 + set_block_number(30); + + let user_balance_a_before = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_before = Currency::free_balance(BSX, &ALICE); + + let pool_balance_a_before = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_before = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_ok!(LBPPallet::add_liquidity( + Origin::signed(ALICE), + (KUSD, 1_000), + (BSX, 1_000), + )); + + let pool_balance_a_after = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_after = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_eq!(pool_balance_a_after, pool_balance_a_before.saturating_add(1_000)); + assert_eq!(pool_balance_b_after, pool_balance_b_before.saturating_add(1_000)); + + let user_balance_a_after = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_after = Currency::free_balance(BSX, &ALICE); + + assert_eq!(user_balance_a_after, user_balance_a_before.saturating_sub(1_000)); + assert_eq!(user_balance_b_after, user_balance_b_before.saturating_sub(1_000)); + + expect_events(vec![Event::LiquidityAdded { + who: KUSD_BSX_POOL_ID, + asset_a: KUSD, + asset_b: BSX, + amount_a: 1_000, + amount_b: 1_000, + } + .into()]); + }); +} + +#[test] +fn add_liquidity_to_non_existing_pool_should_not_work() { + predefined_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::add_liquidity(Origin::signed(ALICE), (KUSD, 1_000), (HDX, 1_000),), + Error::::PoolNotFound + ); + }); +} + +#[test] +fn remove_liquidity_should_work() { + predefined_test_ext().execute_with(|| { + set_block_number(41); + + let user_balance_a_before = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_before = Currency::free_balance(BSX, &ALICE); + + let pool_balance_a_before = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_before = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_ok!(LBPPallet::remove_liquidity(Origin::signed(ALICE), KUSD_BSX_POOL_ID,)); + + let pool_balance_a_after = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_after = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_eq!(pool_balance_a_after, 0); + assert_eq!(pool_balance_b_after, 0); + + let user_balance_a_after = Currency::free_balance(KUSD, &ALICE); + assert_eq!( + user_balance_a_after, + user_balance_a_before.saturating_add(pool_balance_a_before) + ); + + let user_balance_b_after = Currency::free_balance(BSX, &ALICE); + assert_eq!( + user_balance_b_after, + user_balance_b_before.saturating_add(pool_balance_b_before) + ); + + assert!(!>::contains_key(CHARLIE, KUSD)); + assert!(!>::contains_key(KUSD_BSX_POOL_ID)); + + expect_events(vec![ + frame_system::Event::KilledAccount { + account: KUSD_BSX_POOL_ID, + } + .into(), + mock::RuntimeEvent::Currency(orml_tokens::Event::Transfer { + currency_id: BSX, + from: KUSD_BSX_POOL_ID, + to: ALICE, + amount: 2000000000, + }), + Event::LiquidityRemoved { + who: KUSD_BSX_POOL_ID, + asset_a: KUSD, + asset_b: BSX, + amount_a: pool_balance_a_before, + amount_b: pool_balance_b_before, + } + .into(), + ]); + }); +} + +#[test] +fn remove_liquidity_from_not_started_pool_should_work() { + predefined_test_ext().execute_with(|| { + let user_balance_a_before = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_before = Currency::free_balance(BSX, &ALICE); + + let pool_balance_a_before = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_before = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_ok!(LBPPallet::remove_liquidity(Origin::signed(ALICE), KUSD_BSX_POOL_ID,)); + expect_events(vec![Event::LiquidityRemoved { + who: KUSD_BSX_POOL_ID, + asset_a: KUSD, + asset_b: BSX, + amount_a: pool_balance_a_before, + amount_b: pool_balance_b_before, + } + .into()]); + + let pool_balance_a_after = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_after = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_eq!(pool_balance_a_after, 0); + assert_eq!(pool_balance_b_after, 0); + + let user_balance_a_after = Currency::free_balance(KUSD, &ALICE); + assert_eq!( + user_balance_a_after, + user_balance_a_before.saturating_add(pool_balance_a_before) + ); + + let user_balance_b_after = Currency::free_balance(BSX, &ALICE); + assert_eq!( + user_balance_b_after, + user_balance_b_before.saturating_add(pool_balance_b_before) + ); + + assert!(!>::contains_key(KUSD_BSX_POOL_ID)); + + // sale duration is not specified + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + HDX, + 1_000_000_000, + BSX, + 2_000_000_000, + 10_000_000, + 90_000_000, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + )); + + let user_balance_a_before = Currency::free_balance(HDX, &ALICE); + let user_balance_b_before = Currency::free_balance(BSX, &ALICE); + + let pool_balance_a_before = Currency::free_balance(HDX, &HDX_BSX_POOL_ID); + let pool_balance_b_before = Currency::free_balance(BSX, &HDX_BSX_POOL_ID); + + assert_ok!(LBPPallet::remove_liquidity(Origin::signed(ALICE), HDX_BSX_POOL_ID,)); + + expect_events(vec![Event::LiquidityRemoved { + who: HDX_BSX_POOL_ID, + asset_a: HDX, + asset_b: BSX, + amount_a: pool_balance_a_before, + amount_b: pool_balance_b_before, + } + .into()]); + + let pool_balance_a_after = Currency::free_balance(HDX, &HDX_BSX_POOL_ID); + let pool_balance_b_after = Currency::free_balance(BSX, &HDX_BSX_POOL_ID); + + assert_eq!(pool_balance_a_after, 0); + assert_eq!(pool_balance_b_after, 0); + + let user_balance_a_after = Currency::free_balance(HDX, &ALICE); + assert_eq!( + user_balance_a_after, + user_balance_a_before.saturating_add(pool_balance_a_before) + ); + + let user_balance_b_after = Currency::free_balance(BSX, &ALICE); + assert_eq!( + user_balance_b_after, + user_balance_b_before.saturating_add(pool_balance_b_before) + ); + + assert!(!>::contains_key(HDX_BSX_POOL_ID)); + }); +} + +#[test] +fn remove_liquidity_from_non_existing_pool_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::remove_liquidity(Origin::signed(ALICE), KUSD_BSX_POOL_ID), + Error::::PoolNotFound + ); + }); +} + +#[test] +fn remove_liquidity_from_not_finalized_pool_should_not_work() { + predefined_test_ext().execute_with(|| { + set_block_number(15); + + let user_balance_a_before = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_before = Currency::free_balance(BSX, &ALICE); + + let pool_balance_a_before = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_before = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_noop!( + LBPPallet::remove_liquidity(Origin::signed(ALICE), KUSD_BSX_POOL_ID,), + Error::::SaleNotEnded + ); + + let user_balance_a_after = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_after = Currency::free_balance(BSX, &ALICE); + + let pool_balance_a_after = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_after = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_eq!(pool_balance_a_before, pool_balance_a_after); + assert_eq!(pool_balance_b_before, pool_balance_b_after); + assert_eq!(user_balance_a_before, user_balance_a_after); + assert_eq!(user_balance_b_before, user_balance_b_after); + }); +} + +#[test] +fn remove_liquidity_from_finalized_pool_should_work() { + predefined_test_ext().execute_with(|| { + set_block_number(41); + + let user_balance_a_before = Currency::free_balance(KUSD, &ALICE); + let user_balance_b_before = Currency::free_balance(BSX, &ALICE); + + let pool_balance_a_before = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_before = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_ok!(LBPPallet::remove_liquidity(Origin::signed(ALICE), KUSD_BSX_POOL_ID,)); + + let pool_balance_a_after = Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID); + let pool_balance_b_after = Currency::free_balance(BSX, &KUSD_BSX_POOL_ID); + + assert_eq!(pool_balance_a_after, 0); + assert_eq!(pool_balance_b_after, 0); + + let user_balance_a_after = Currency::free_balance(KUSD, &ALICE); + assert_eq!( + user_balance_a_after, + user_balance_a_before.saturating_add(pool_balance_a_before) + ); + + let user_balance_b_after = Currency::free_balance(BSX, &ALICE); + assert_eq!( + user_balance_b_after, + user_balance_b_before.saturating_add(pool_balance_b_before) + ); + + assert!(!>::contains_key(KUSD_BSX_POOL_ID)); + + expect_events(vec![ + frame_system::Event::KilledAccount { + account: KUSD_BSX_POOL_ID, + } + .into(), + mock::RuntimeEvent::Currency(orml_tokens::Event::Transfer { + currency_id: BSX, + from: KUSD_BSX_POOL_ID, + to: ALICE, + amount: 2000000000, + }), + Event::LiquidityRemoved { + who: KUSD_BSX_POOL_ID, + asset_a: KUSD, + asset_b: BSX, + amount_a: pool_balance_a_before, + amount_b: pool_balance_b_before, + } + .into(), + ]); + }); +} + +#[test] +fn remove_liquidity_by_non_owner_should_not_work() { + predefined_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::remove_liquidity(Origin::signed(BOB), KUSD_BSX_POOL_ID), + Error::::NotOwner + ); + }); +} + +#[test] +fn execute_trade_should_work() { + predefined_test_ext().execute_with(|| { + let asset_in = KUSD; + let asset_out = BSX; + let pool_id = KUSD_BSX_POOL_ID; + + let amount_in = 5_000_000_u128; + let amount_b = 10_000_000_u128; + let t_sell = AMMTransfer { + origin: ALICE, + assets: AssetPair { asset_in, asset_out }, + amount: amount_in, + amount_b, + discount: false, + discount_amount: 0_u128, + fee: (asset_in, 1_000), + }; + + assert_eq!(Currency::free_balance(asset_in, &ALICE), 999_999_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &ALICE), 999_998_000_000_000); + assert_eq!(Currency::free_balance(asset_in, &CHARLIE), 0); + assert_eq!(Currency::free_balance(asset_out, &CHARLIE), 0); + + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 2_000_000_000); + + assert_ok!(LBPPallet::execute_trade(&t_sell)); + + assert_eq!(Currency::free_balance(asset_in, &ALICE), 999_998_994_999_000); + assert_eq!(Currency::free_balance(asset_out, &ALICE), 999_998_010_000_000); + assert_eq!(Currency::free_balance(asset_in, &CHARLIE), 1_000); + assert_eq!(Currency::free_balance(asset_out, &CHARLIE), 0); + + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_005_000_000); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 1_990_000_000); + + let t_buy = AMMTransfer { + origin: ALICE, + assets: AssetPair { asset_in, asset_out }, + amount: amount_in, + amount_b, + discount: false, + discount_amount: 0_u128, + fee: (asset_in, 1_000), + }; + + assert_ok!(LBPPallet::execute_trade(&t_buy)); + + assert_eq!(Currency::free_balance(asset_in, &ALICE), 999_998_989_998_000); + assert_eq!(Currency::free_balance(asset_out, &ALICE), 999_998_020_000_000); + assert_eq!(Currency::free_balance(asset_in, &CHARLIE), 2_000); + assert_eq!(Currency::free_balance(asset_out, &CHARLIE), 0); + + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_010_000_000); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 1_980_000_000); + }); +} + +#[test] +fn trade_fails_when_first_fee_lesser_than_existential_deposit() { + predefined_test_ext().execute_with(|| { + let trade = AMMTransfer { + origin: ALICE, + assets: AssetPair { + asset_in: KUSD, + asset_out: BSX, + }, + amount: 1000, + amount_b: 1000, + discount: false, + discount_amount: 0_u128, + fee: (KUSD, EXISTENTIAL_DEPOSIT - 1), + }; + + assert_noop!( + LBPPallet::execute_trade(&trade), + orml_tokens::Error::::ExistentialDeposit + ); + }); +} + +// // This test ensure storage was not modified on error +#[test] +fn execute_trade_should_not_work() { + predefined_test_ext().execute_with(|| { + let asset_in = KUSD; + let asset_out = BSX; + let pool_id = LBPPallet::get_pair_id(AssetPair { asset_in, asset_out }); + + let amount_in = 5_000_000_u128; + let amount_b = 10_000_000_000_000_000u128; + let t = AMMTransfer { + origin: ALICE, + assets: AssetPair { asset_in, asset_out }, + amount: amount_in, + amount_b, + discount: false, + discount_amount: 0_u128, + fee: (asset_in, 1_000), + }; + + assert_eq!(Currency::free_balance(asset_in, &ALICE), 999_999_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &ALICE), 999_998_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &CHARLIE), 0); + + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 2_000_000_000); + + assert_noop!(LBPPallet::execute_trade(&t), orml_tokens::Error::::BalanceTooLow); + + assert_eq!(Currency::free_balance(asset_in, &ALICE), 999_999_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &ALICE), 999_998_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &CHARLIE), 0); + + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 2_000_000_000); + }); +} + +#[test] +fn execute_sell_should_work() { + predefined_test_ext().execute_with(|| { + let asset_in = KUSD; + let asset_out = BSX; + let pool_id = LBPPallet::get_pair_id(AssetPair { asset_in, asset_out }); + let pool_data = >::try_get(pool_id).unwrap(); + + let amount_in = 8_000_000_u128; + let amount_b = 20_000_000_u128; + let t = AMMTransfer { + origin: ALICE, + assets: AssetPair { asset_in, asset_out }, + amount: amount_in, + amount_b, + discount: false, + discount_amount: 0_u128, + fee: (asset_in, 1_000), + }; + + assert_eq!(Currency::free_balance(asset_in, &ALICE), 999_999_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &ALICE), 999_998_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &CHARLIE), 0); + + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 2_000_000_000); + + assert_ok!(LBPPallet::execute_sell(&t)); + + expect_events(vec![ + Event::SellExecuted { + who: ALICE, + asset_in, + asset_out, + amount: amount_in, + sale_price: amount_b, + fee_asset: asset_in, + fee_amount: 1_000, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: ALICE, + filler: pool_id, + filler_type: pallet_broadcast::types::Filler::LBP, + operation: pallet_broadcast::types::TradeOperation::ExactIn, + inputs: vec![Asset::new(asset_in, amount_in)], + outputs: vec![Asset::new(asset_out, amount_b)], + fees: vec![Fee::new(asset_in, 1_000, Destination::Account(pool_data.fee_collector))], + operation_stack: vec![], + } + .into(), + ]); + + assert_eq!(Currency::free_balance(asset_in, &ALICE), 999_998_991_999_000); + assert_eq!(Currency::free_balance(asset_out, &ALICE), 999_998_020_000_000); + assert_eq!(Currency::free_balance(asset_in, &CHARLIE), 1_000); + + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_008_000_000); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 1_980_000_000); + }); +} + +// This test ensure storage was not modified on error +#[test] +fn execute_sell_should_not_work() { + predefined_test_ext().execute_with(|| { + let t = AMMTransfer { + origin: ALICE, + assets: AssetPair { + asset_in: KUSD, + asset_out: BSX, + }, + amount: 8_000_000_000_u128, + amount_b: 200_000_000_000_000_u128, + discount: false, + discount_amount: 0_u128, + fee: (KUSD, 1_000), + }; + + assert_eq!(Currency::free_balance(KUSD, &ALICE), 999_999_000_000_000); + assert_eq!(Currency::free_balance(BSX, &ALICE), 999_998_000_000_000); + assert_eq!(Currency::free_balance(BSX, &CHARLIE), 0); + + assert_eq!(Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID), 1_000_000_000); + assert_eq!(Currency::free_balance(BSX, &KUSD_BSX_POOL_ID), 2_000_000_000); + + assert_noop!(LBPPallet::execute_sell(&t), orml_tokens::Error::::BalanceTooLow); + + assert_eq!(Currency::free_balance(KUSD, &ALICE), 999_999_000_000_000); + assert_eq!(Currency::free_balance(BSX, &ALICE), 999_998_000_000_000); + assert_eq!(Currency::free_balance(BSX, &CHARLIE), 0); + + assert_eq!(Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID), 1_000_000_000); + assert_eq!(Currency::free_balance(BSX, &KUSD_BSX_POOL_ID), 2_000_000_000); + }); +} + +#[test] +fn zero_weight_should_not_work() { + predefined_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::create_pool( + Origin::root(), + ALICE, + ETH, + 1_000_000_000, + KUSD, + 2_000_000_000, + 0u32, + 20u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + ), + Error::::InvalidWeight + ); + + let call = Call::LBPPallet(crate::Call::::update_pool_data { + pool_id: KUSD_BSX_POOL_ID, + pool_owner: None, + start: Some(15), + end: Some(18), + initial_weight: Some(0), + final_weight: Some(80), + fee: Some((5, 100)), + fee_collector: Some(BOB), + repay_target: Some(0), + }); + + assert_noop!(call.dispatch(Origin::signed(ALICE)), Error::::InvalidWeight); + }); +} + +#[test] +fn execute_buy_should_work() { + predefined_test_ext().execute_with(|| { + let asset_in = KUSD; + let asset_out = BSX; + let pool_id = LBPPallet::get_pair_id(AssetPair { asset_in, asset_out }); + let pool_data = >::try_get(pool_id).unwrap(); + + let amount_in = 8_000_000_u128; + let amount_b = 20_000_000_u128; + let t = AMMTransfer { + origin: ALICE, + assets: AssetPair { asset_in, asset_out }, + amount: amount_in, + amount_b, + discount: false, + discount_amount: 0_u128, + fee: (asset_in, 1_000), + }; + + assert_eq!(Currency::free_balance(asset_in, &ALICE), 999_999_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &ALICE), 999_998_000_000_000); + assert_eq!(Currency::free_balance(asset_in, &CHARLIE), 0); + assert_eq!(Currency::free_balance(asset_out, &CHARLIE), 0); + + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 2_000_000_000); + + assert_ok!(LBPPallet::execute_buy(&t, None)); + + assert_eq!(Currency::free_balance(asset_in, &ALICE), 999_998_991_999_000); + assert_eq!(Currency::free_balance(asset_out, &ALICE), 999_998_020_000_000); + assert_eq!(Currency::free_balance(asset_in, &CHARLIE), 1_000); + assert_eq!(Currency::free_balance(asset_out, &CHARLIE), 0); + + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_008_000_000); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 1_980_000_000); + + expect_events(vec![ + Event::BuyExecuted { + who: ALICE, + asset_in, + asset_out, + amount: amount_in, + buy_price: amount_b, + fee_asset: asset_in, + fee_amount: 1_000, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: ALICE, + filler: pool_id, + filler_type: pallet_broadcast::types::Filler::LBP, + operation: pallet_broadcast::types::TradeOperation::ExactOut, + inputs: vec![Asset::new(asset_in, amount_in)], + outputs: vec![Asset::new(asset_out, amount_b)], + fees: vec![Fee::new(asset_in, 1_000, Destination::Account(pool_data.fee_collector))], + operation_stack: vec![], + } + .into(), + ]); + }); +} + +// This test ensures storage was not modified on error +#[test] +fn execute_buy_should_not_work() { + predefined_test_ext().execute_with(|| { + let asset_in = KUSD; + let asset_out = BSX; + let pool_id = LBPPallet::get_pair_id(AssetPair { asset_in, asset_out }); + + let amount_in = 8_000_000_000_u128; + let amount_b = 200_000_000_000_000_u128; + let t = AMMTransfer { + origin: ALICE, + assets: AssetPair { asset_in, asset_out }, + amount: amount_in, + amount_b, + discount: false, + discount_amount: 0_u128, + fee: (asset_in, 1_000), + }; + + assert_eq!(Currency::free_balance(asset_in, &ALICE), 999_999_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &ALICE), 999_998_000_000_000); + assert_eq!(Currency::free_balance(asset_in, &CHARLIE), 0); + + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 2_000_000_000); + + assert_noop!( + LBPPallet::execute_buy(&t, None), + orml_tokens::Error::::BalanceTooLow + ); + + assert_eq!(Currency::free_balance(asset_in, &ALICE), 999_999_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &ALICE), 999_998_000_000_000); + assert_eq!(Currency::free_balance(asset_in, &CHARLIE), 0); + + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_000_000_000); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 2_000_000_000); + }); +} + +#[test] +fn sell_zero_amount_should_not_work() { + predefined_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::sell(Origin::signed(BOB), KUSD, BSX, 0_u128, 200_000_u128), + Error::::ZeroAmount + ); + }); +} + +#[test] +fn buy_zero_amount_should_not_work() { + predefined_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::buy(Origin::signed(BOB), KUSD, BSX, 0_u128, 200_000_u128), + Error::::ZeroAmount + ); + }); +} + +#[test] +fn sell_to_non_existing_pool_should_not_work() { + predefined_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::sell(Origin::signed(BOB), KUSD, ETH, 800_000_u128, 200_000_u128), + Error::::PoolNotFound + ); + }); +} + +#[test] +fn buy_from_non_existing_pool_should_not_work() { + predefined_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::buy(Origin::signed(BOB), KUSD, ETH, 800_000_u128, 200_000_u128), + Error::::PoolNotFound + ); + }); +} + +#[test] +fn exceed_max_in_ratio_should_not_work() { + predefined_test_ext().execute_with(|| { + set_block_number(11); //start sale + assert_noop!( + LBPPallet::sell( + Origin::signed(BOB), + KUSD, + BSX, + 1_000_000_000 / LBPPallet::get_max_in_ratio() + 1, + 200_000_u128 + ), + Error::::MaxInRatioExceeded + ); + + // 1/2 should not work + assert_noop!( + LBPPallet::sell(Origin::signed(BOB), KUSD, BSX, 1_000_000_000 / 2, 200_000_u128), + Error::::MaxInRatioExceeded + ); + + // max ratio should work + assert_ok!(LBPPallet::sell( + Origin::signed(BOB), + KUSD, + BSX, + 1_000_000_000 / LBPPallet::get_max_in_ratio(), + 2_000_u128 + )); + }); +} + +#[test] +fn exceed_max_out_ratio_should_not_work() { + predefined_test_ext().execute_with(|| { + set_block_number(11); //start sale + + // max_ratio_out + 1 should not work + assert_noop!( + LBPPallet::buy( + Origin::signed(BOB), + BSX, + KUSD, + 2_000_000_000 / LBPPallet::get_max_out_ratio() + 1, + 200_000_u128 + ), + Error::::MaxOutRatioExceeded + ); + + // 1/2 should not work + assert_noop!( + LBPPallet::buy(Origin::signed(BOB), BSX, KUSD, 2_000_000_000 / 2, 200_000_u128), + Error::::MaxOutRatioExceeded + ); + }); +} + +#[test] +fn trade_in_non_running_pool_should_not_work() { + predefined_test_ext().execute_with(|| { + let who = BOB; + let asset_in = KUSD; + let asset_out = BSX; + let amount = 800_000_u128; + let limit = 200_000_u128; + + //sale not started + set_block_number(9); + assert_noop!( + LBPPallet::sell(Origin::signed(who), asset_in, asset_out, amount, limit), + Error::::SaleIsNotRunning + ); + assert_noop!( + LBPPallet::buy(Origin::signed(who), asset_out, asset_in, amount, limit), + Error::::SaleIsNotRunning + ); + + //sale ended + set_block_number(41); + assert_noop!( + LBPPallet::sell(Origin::signed(who), asset_in, asset_out, amount, limit), + Error::::SaleIsNotRunning + ); + assert_noop!( + LBPPallet::buy(Origin::signed(who), asset_out, asset_in, amount, limit), + Error::::SaleIsNotRunning + ); + }); +} + +#[test] +fn exceed_trader_limit_should_not_work() { + predefined_test_ext().execute_with(|| { + let who = BOB; + let asset_in = KUSD; + let asset_out = BSX; + let amount = 800_000_u128; + let sell_limit = 800_000_u128; + let buy_limit = 1_000_u128; + + //start sale + set_block_number(11); + assert_noop!( + LBPPallet::sell(Origin::signed(who), asset_in, asset_out, amount, sell_limit), + Error::::TradingLimitReached + ); + + assert_noop!( + LBPPallet::buy(Origin::signed(who), asset_out, asset_in, amount, buy_limit), + Error::::TradingLimitReached + ); + }); +} + +#[test] +fn sell_with_insufficient_balance_should_not_work() { + predefined_test_ext().execute_with(|| { + let who = BOB; + let asset_in = KUSD; + let asset_out = BSX; + let amount = 1_000_000_u128; + + Currency::set_balance(Origin::root(), who, asset_in, 100_000, 0).unwrap(); + Currency::set_balance(Origin::root(), who, asset_out, 100_000, 0).unwrap(); + + //start sale + set_block_number(11); + + assert_noop!( + LBPPallet::sell(Origin::signed(who), asset_in, asset_out, amount, 800_000_u128), + Error::::InsufficientAssetBalance + ); + + // swap assets + assert_noop!( + LBPPallet::sell(Origin::signed(who), asset_out, asset_in, amount, 800_000_u128), + Error::::InsufficientAssetBalance + ); + }); +} + +#[test] +fn buy_with_insufficient_balance_should_not_work() { + predefined_test_ext().execute_with(|| { + let who = BOB; + let asset_in = KUSD; + let asset_out = BSX; + let amount = 1_000_000_u128; + + Currency::set_balance(Origin::root(), who, asset_in, 100_000, 0).unwrap(); + Currency::set_balance(Origin::root(), who, asset_out, 100_000, 0).unwrap(); + + //start sale + set_block_number(11); + + assert_noop!( + LBPPallet::buy(Origin::signed(who), asset_out, asset_in, amount, 2_000_000_u128), + Error::::InsufficientAssetBalance + ); + + // swap assets + assert_noop!( + LBPPallet::buy(Origin::signed(who), asset_in, asset_out, amount, 2_000_000_u128), + Error::::InsufficientAssetBalance + ); + }); +} + +#[test] +fn inverted_operations_should_be_equal() { + let buy = predefined_test_ext().execute_with(|| { + run_to_sale_start(); + assert_ok!(LBPPallet::buy( + Origin::signed(BOB), + BSX, + KUSD, + 10_000_000_u128, + 21_000_000_u128 + )); + ( + Currency::free_balance(KUSD, &BOB), + Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID), + Currency::free_balance(KUSD, &CHARLIE), + ) + }); + let sell = predefined_test_ext().execute_with(|| { + run_to_sale_start(); + assert_ok!(LBPPallet::sell( + Origin::signed(BOB), + KUSD, + BSX, + 20_252_524_u128, + 9_000_000_u128 + )); + ( + Currency::free_balance(KUSD, &BOB), + Currency::free_balance(KUSD, &KUSD_BSX_POOL_ID), + Currency::free_balance(KUSD, &CHARLIE), + ) + }); + assert_eq!(buy, sell); +} + +#[test] +fn buy_should_work() { + predefined_test_ext().execute_with(|| { + let buyer = BOB; + let asset_in = KUSD; + let asset_out = BSX; + let pool_id = LBPPallet::get_pair_id(AssetPair { asset_in, asset_out }); + let pool_data = >::try_get(pool_id).unwrap(); + + //start sale + set_block_number(11); + assert_ok!(LBPPallet::buy( + Origin::signed(buyer), + asset_out, + asset_in, + 10_000_000_u128, + 2_000_000_000_u128 + )); + + expect_events(vec![ + Event::BuyExecuted { + who: buyer, + asset_in, + asset_out, + amount: 17_894_738, + buy_price: 10_000_000, + fee_asset: asset_in, + fee_amount: 35860, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: buyer, + filler: pool_id, + filler_type: pallet_broadcast::types::Filler::LBP, + operation: pallet_broadcast::types::TradeOperation::ExactOut, + inputs: vec![Asset::new(asset_in, 17_894_738)], + outputs: vec![Asset::new(asset_out, 10_000_000)], + fees: vec![Fee::new(asset_in, 35860, Destination::Account(pool_data.fee_collector))], + operation_stack: vec![], // calling buy directly from the pallet doesn't set event_id + } + .into(), + ]); + + assert_eq!(Currency::free_balance(asset_in, &buyer), 999_999_982_069_402); + assert_eq!(Currency::free_balance(asset_out, &buyer), 1_000_000_010_000_000); + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_017_894_738); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 1_990_000_000); + + // test buy where the amount_in is less than the amount_out + let asset_in = HDX; + let asset_out = BSX; + let pool_id2 = LBPPallet::get_pair_id(AssetPair { asset_in, asset_out }); + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + HDX, + 1_000_000_000, + BSX, + 2_000_000_000, + 80_000_000u32, + 10_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + )); + + let pool_data1 = LBPPallet::pool_data(pool_id2).unwrap(); + expect_events(vec![ + Event::PoolCreated { + pool: pool_id2, + data: pool_data1, + } + .into(), + frame_system::Event::NewAccount { account: pool_id2 }.into(), + mock::RuntimeEvent::Currency(orml_tokens::Event::Endowed { + currency_id: HDX, + who: HDX_BSX_POOL_ID, + amount: 1000000000, + }), + mock::RuntimeEvent::Currency(orml_tokens::Event::Transfer { + currency_id: HDX, + from: ALICE, + to: HDX_BSX_POOL_ID, + amount: 1000000000, + }), + mock::RuntimeEvent::Currency(orml_tokens::Event::Endowed { + currency_id: BSX, + who: HDX_BSX_POOL_ID, + amount: 2000000000, + }), + mock::RuntimeEvent::Currency(orml_tokens::Event::Transfer { + currency_id: BSX, + from: ALICE, + to: HDX_BSX_POOL_ID, + amount: 2000000000, + }), + mock::RuntimeEvent::LBPPallet(Event::LiquidityAdded { + who: pool_id2, + asset_a: HDX, + asset_b: BSX, + amount_a: 1_000_000_000, + amount_b: 2_000_000_000, + }), + ]); + + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + HDX_BSX_POOL_ID, + None, + Some(20), + Some(30), + None, + None, + None, + None, + None + )); + + let pool_data2 = LBPPallet::pool_data(pool_id2).unwrap(); + + expect_events(vec![Event::PoolUpdated { + pool: pool_id2, + data: pool_data2, + } + .into()]); + + //start sale + set_block_number(21); + assert_ok!(LBPPallet::buy( + Origin::signed(buyer), + asset_out, + asset_in, + 10_000_000_u128, + 2_000_000_000_u128 + )); + + assert_eq!(Currency::free_balance(asset_in, &buyer), 999_999_998_144_325); + assert_eq!(Currency::free_balance(asset_out, &buyer), 1_000_000_020_000_000); + assert_eq!(Currency::free_balance(asset_in, &pool_id2), 1_001_851_965); + assert_eq!(Currency::free_balance(asset_out, &pool_id2), 1_990_000_000); + }); +} + +#[test] +fn buy_should_work_when_limit_is_set_above_account_balance() { + predefined_test_ext().execute_with(|| { + let buyer = BOB; + let asset_in = KUSD; + let asset_out = BSX; + let pool_id = LBPPallet::get_pair_id(AssetPair { asset_in, asset_out }); + let pool_data = >::try_get(pool_id).unwrap(); + + //start sale + set_block_number(11); + + assert_ok!(LBPPallet::buy( + Origin::signed(buyer), + asset_out, + asset_in, + 10_000_000_u128, + u128::MAX, + )); + + expect_events(vec![ + Event::BuyExecuted { + who: buyer, + asset_in, + asset_out, + amount: 17_894_738, + buy_price: 10_000_000, + fee_asset: asset_in, + fee_amount: 35860, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: buyer, + filler: pool_id, + filler_type: pallet_broadcast::types::Filler::LBP, + operation: pallet_broadcast::types::TradeOperation::ExactOut, + inputs: vec![Asset::new(asset_in, 17_894_738)], + outputs: vec![Asset::new(asset_out, 10_000_000)], + fees: vec![Fee::new(asset_in, 35860, Destination::Account(pool_data.fee_collector))], + operation_stack: vec![], + } + .into(), + ]); + + // swap assets + set_block_number(11); + assert_ok!(LBPPallet::buy( + Origin::signed(buyer), + asset_in, + asset_out, + 10_000_000_u128, + u128::MAX, + )); + + expect_events(vec![ + Event::BuyExecuted { + who: buyer, + asset_in: BSX, + asset_out: KUSD, + amount: 5_560_304, + buy_price: 10_000_000, + fee_asset: KUSD, + fee_amount: 20_000, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: buyer, + filler: pool_id, + filler_type: pallet_broadcast::types::Filler::LBP, + operation: pallet_broadcast::types::TradeOperation::ExactOut, + inputs: vec![Asset::new(BSX, 5_560_304)], + outputs: vec![Asset::new(KUSD, 10_000_000)], + + fees: vec![Fee::new(KUSD, 20_000, Destination::Account(pool_data.fee_collector))], + operation_stack: vec![], + } + .into(), + ]); + }); +} + +#[test] +fn update_pool_data_after_sale_should_not_work() { + predefined_test_ext().execute_with(|| { + let buyer = BOB; + let asset_in = KUSD; + let asset_out = BSX; + let pool_id = LBPPallet::get_pair_id(AssetPair { asset_in, asset_out }); + + //start sale + set_block_number(11); + assert_ok!(LBPPallet::buy( + Origin::signed(buyer), + asset_out, + asset_in, + 10_000_000_u128, + 2_000_000_000_u128 + )); + + assert_eq!(Currency::free_balance(asset_in, &buyer), 999_999_982_069_402); + assert_eq!(Currency::free_balance(asset_out, &buyer), 1_000_000_010_000_000); + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_017_894_738); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 1_990_000_000); + assert_eq!(Currency::free_balance(asset_in, &CHARLIE), 35_860); + + set_block_number(41); + + assert_noop!( + LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + Some(50), + Some(60), + None, + None, + None, + None, + None, + ), + Error::::SaleStarted + ); + }); +} + +#[test] +fn sell_should_work() { + predefined_test_ext().execute_with(|| { + let buyer = BOB; + let asset_in = KUSD; + let asset_out = BSX; + let pool_id = LBPPallet::get_pair_id(AssetPair { asset_in, asset_out }); + let pool_data = >::try_get(pool_id).unwrap(); + + //start sale + set_block_number(11); + + assert_ok!(LBPPallet::sell( + Origin::signed(buyer), + asset_in, + asset_out, + 10_000_000_u128, + 2_000_u128 + )); + + expect_events(vec![ + Event::SellExecuted { + who: buyer, + asset_in, + asset_out, + amount: 9_980_000, + sale_price: 5_605_138, + fee_asset: asset_in, + fee_amount: 20_000, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: buyer, + filler: pool_id, + filler_type: pallet_broadcast::types::Filler::LBP, + operation: pallet_broadcast::types::TradeOperation::ExactIn, + inputs: vec![Asset::new(asset_in, 9_980_000)], + outputs: vec![Asset::new(asset_out, 5_605_138)], + fees: vec![Fee::new( + asset_in, + 20_000, + Destination::Account(pool_data.fee_collector), + )], + operation_stack: vec![], + } + .into(), + ]); + + assert_eq!(Currency::free_balance(asset_in, &buyer), 999_999_990_000_000); + assert_eq!(Currency::free_balance(asset_out, &buyer), 1_000_000_005_605_138); + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_009_980_000); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 1_994_394_862); + + // test buy where the amount_in is less than the amount_out + let asset_in = HDX; + let asset_out = BSX; + let pool_id2 = LBPPallet::get_pair_id(AssetPair { asset_in, asset_out }); + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + HDX, + 1_000_000_000, + BSX, + 2_000_000_000, + 80_000_000u32, + 10_000_000u32, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + )); + let pool_data1 = LBPPallet::pool_data(pool_id2).unwrap(); + + expect_events(vec![ + Event::PoolCreated { + pool: pool_id2, + data: pool_data1, + } + .into(), + frame_system::Event::NewAccount { account: pool_id2 }.into(), + mock::RuntimeEvent::Currency(orml_tokens::Event::Endowed { + currency_id: HDX, + who: HDX_BSX_POOL_ID, + amount: 1000000000, + }), + mock::RuntimeEvent::Currency(orml_tokens::Event::Transfer { + currency_id: HDX, + from: ALICE, + to: HDX_BSX_POOL_ID, + amount: 1000000000, + }), + mock::RuntimeEvent::Currency(orml_tokens::Event::Endowed { + currency_id: BSX, + who: HDX_BSX_POOL_ID, + amount: 2000000000, + }), + mock::RuntimeEvent::Currency(orml_tokens::Event::Transfer { + currency_id: BSX, + from: ALICE, + to: HDX_BSX_POOL_ID, + amount: 2000000000, + }), + mock::RuntimeEvent::LBPPallet(Event::LiquidityAdded { + who: pool_id2, + asset_a: HDX, + asset_b: BSX, + amount_a: 1_000_000_000, + amount_b: 2_000_000_000, + }), + ]); + + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + HDX_BSX_POOL_ID, + None, + Some(20), + Some(30), + None, + None, + None, + None, + None + )); + + let pool_data2 = LBPPallet::pool_data(pool_id2).unwrap(); + + expect_events(vec![Event::PoolUpdated { + pool: pool_id2, + data: pool_data2, + } + .into()]); + + //start sale + set_block_number(21); + assert_ok!(LBPPallet::sell( + Origin::signed(buyer), + asset_out, + asset_in, + 10_000_000_u128, + 2_000_u128 + )); + + assert_eq!(Currency::free_balance(asset_in, &buyer), 1_000_000_001_839_320); + assert_eq!(Currency::free_balance(asset_out, &buyer), 999_999_995_605_138); + assert_eq!(Currency::free_balance(asset_in, &pool_id2), 998_156_994); + assert_eq!(Currency::free_balance(asset_out, &pool_id2), 2_010_000_000); + }); +} + +#[test] +fn sell_should_work_with_different_token_precisions() { + new_test_ext().execute_with(|| { + let asset_in = KUSD; + let asset_out = BSX; + let reserve_in = 1_000 * 1_000_000; + let reserve_out = 1_000 * 1_000_000_000_000; + + let pool_id = start_50_50_lbp_without_fee_and_repay_target(asset_in, reserve_in, asset_out, reserve_out); + + let sell_amount = 1_000_000; + + assert_ok!(LBPPallet::sell( + Origin::signed(BOB), + asset_in, + asset_out, + sell_amount, + 0 + )); + + assert_eq!(Currency::free_balance(asset_in, &BOB), INITIAL_BALANCE - sell_amount); + assert_eq!( + Currency::free_balance(asset_out, &BOB), + INITIAL_BALANCE + 999_000_999_000 + ); + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_001_000_000); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 999_000_999_001_000); + }); + + new_test_ext().execute_with(|| { + let asset_in = BSX; + let asset_out = KUSD; + let reserve_in = 1_000 * 1_000_000_000_000; + let reserve_out = 1_000 * 1_000_000; + + let pool_id = start_50_50_lbp_without_fee_and_repay_target(asset_in, reserve_in, asset_out, reserve_out); + + let sell_amount = 1_000_000_000_000; + + assert_ok!(LBPPallet::sell( + Origin::signed(BOB), + asset_in, + asset_out, + sell_amount, + 0 + )); + + assert_eq!(Currency::free_balance(asset_in, &BOB), INITIAL_BALANCE - sell_amount); + assert_eq!(Currency::free_balance(asset_out, &BOB), INITIAL_BALANCE + 999_000); + assert_eq!( + Currency::free_balance(asset_in, &pool_id), + INITIAL_BALANCE + 1_000_000_000_000 + ); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 999_001_000); + }); + + new_test_ext().execute_with(|| { + let asset_in = KUSD; + let asset_out = ETH; + let reserve_in = 1_000 * 1_000_000; + let reserve_out = 1_000 * 1_000_000_000_000_000_000; + + let pool_id = start_50_50_lbp_without_fee_and_repay_target(asset_in, reserve_in, asset_out, reserve_out); + + let sell_amount = 1_000_000; + + assert_ok!(LBPPallet::sell( + Origin::signed(BOB), + asset_in, + asset_out, + sell_amount, + 0 + )); + + assert_eq!(Currency::free_balance(asset_in, &BOB), INITIAL_BALANCE - sell_amount); + assert_eq!( + Currency::free_balance(asset_out, &BOB), + INITIAL_ETH_BALANCE + 999_000_999_000_999_000 + ); + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_001_000_000); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 999_000_999_000_999_001_000); + }); + + // selling a small amount can result in receiving 0 + new_test_ext().execute_with(|| { + let asset_in = BSX; + let asset_out = KUSD; + let reserve_in = 1_000 * 1_000_000_000_000; + let reserve_out = 1_000 * 1_000_000; + + let pool_id = start_50_50_lbp_without_fee_and_repay_target(asset_in, reserve_in, asset_out, reserve_out); + + let sell_amount = 100_000; + + assert_ok!(LBPPallet::sell( + Origin::signed(BOB), + asset_in, + asset_out, + sell_amount, + 0 + )); + + assert_eq!(Currency::free_balance(asset_in, &BOB), INITIAL_BALANCE - sell_amount); + assert_eq!(Currency::free_balance(asset_out, &BOB), INITIAL_BALANCE); + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_000_000_000_100_000); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 1_000_000_000); + }); +} + +#[test] +fn buy_should_work_with_different_token_precisions() { + new_test_ext().execute_with(|| { + let asset_in = BSX; + let asset_out = KUSD; + let reserve_in = 1_000 * 1_000_000_000_000; + let reserve_out = 1_000 * 1_000_000; + + let pool_id = start_50_50_lbp_without_fee_and_repay_target(asset_in, reserve_in, asset_out, reserve_out); + + let buy_amount = 1_000_000; + + assert_ok!(LBPPallet::buy( + Origin::signed(BOB), + asset_out, + asset_in, + buy_amount, + 2_000_000_000_000, + )); + + assert_eq!(Currency::free_balance(asset_in, &BOB), 998_998_998_998_997); + assert_eq!(Currency::free_balance(asset_out, &BOB), INITIAL_BALANCE + buy_amount); + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_001_001_001_001_003); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 999_000_000); + }); + + new_test_ext().execute_with(|| { + let asset_in = KUSD; + let asset_out = BSX; + let reserve_in = 1_000 * 1_000_000; + let reserve_out = 1_000 * 1_000_000_000_000; + + let pool_id = start_50_50_lbp_without_fee_and_repay_target(asset_in, reserve_in, asset_out, reserve_out); + + let buy_amount = 1_000_000; + + assert_ok!(LBPPallet::buy(Origin::signed(BOB), asset_out, asset_in, buy_amount, 10,)); + + assert_eq!(Currency::free_balance(asset_in, &BOB), INITIAL_BALANCE - 3); + assert_eq!(Currency::free_balance(asset_out, &BOB), INITIAL_BALANCE + buy_amount); + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_000_000_003); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 999_999_999_000_000); + }); + + new_test_ext().execute_with(|| { + let asset_in = KUSD; + let asset_out = ETH; + let reserve_in = 1_000 * 1_000_000; + let reserve_out = 1_000 * 1_000_000_000_000_000_000; + + let pool_id = start_50_50_lbp_without_fee_and_repay_target(asset_in, reserve_in, asset_out, reserve_out); + + let buy_amount = 1_000_000; + + assert_ok!(LBPPallet::buy(Origin::signed(BOB), asset_out, asset_in, buy_amount, 10,)); + + assert_eq!(Currency::free_balance(asset_in, &BOB), INITIAL_BALANCE - 2); + assert_eq!( + Currency::free_balance(asset_out, &BOB), + INITIAL_ETH_BALANCE + buy_amount + ); + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_000_000_002); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 999_999_999_999_999_000_000); + }); +} + +#[test] +fn buy_small_amount_should_return_non_zero_amount() { + new_test_ext().execute_with(|| { + let asset_in = KUSD; + let asset_out = ETH; + let reserve_in = 1_000 * 1_000_000; + let reserve_out = 1_000 * 1_000_000_000_000_000_000; + + let pool_id = start_50_50_lbp_without_fee_and_repay_target(asset_in, reserve_in, asset_out, reserve_out); + + //start sale + set_block_number(11); + + let buy_amount = 1_000; + + assert_ok!(LBPPallet::buy(Origin::signed(BOB), asset_out, asset_in, buy_amount, 10,)); + + assert_eq!(Currency::free_balance(asset_in, &BOB), INITIAL_BALANCE - 2); + assert_eq!( + Currency::free_balance(asset_out, &BOB), + INITIAL_ETH_BALANCE + buy_amount + ); + assert_eq!(Currency::free_balance(asset_in, &pool_id), 1_000_000_002); + assert_eq!(Currency::free_balance(asset_out, &pool_id), 999_999_999_999_999_999_000); + }); +} + +#[test] +fn zero_fee_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 1_000_000_000, + BSX, + 2_000_000_000, + 20_000_000, + 80_000_000, + WeightCurveType::Linear, + (0, 100), + CHARLIE, + 0, + )); + + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + Some(10), + Some(20), + None, + None, + None, + None, + None + )); + + //start sale + set_block_number(11); + + assert_ok!(LBPPallet::sell(Origin::signed(ALICE), KUSD, BSX, 1_000, 1,)); + }); +} + +#[test] +fn invalid_fee_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 1_000_000_000, + BSX, + 2_000_000_000, + 20_000_000, + 80_000_000, + WeightCurveType::Linear, + (10, 0), + CHARLIE, + 0, + ), + Error::::FeeAmountInvalid + ); + }); +} + +#[test] +fn amm_trait_should_work() { + predefined_test_ext().execute_with(|| { + let asset_pair = AssetPair { + asset_in: KUSD, + asset_out: BSX, + }; + let reversed_asset_pair = AssetPair { + asset_in: BSX, + asset_out: KUSD, + }; + let non_existing_asset_pair = AssetPair { + asset_in: BSX, + asset_out: HDX, + }; + + set_block_number(11); + + assert!(LBPPallet::exists(asset_pair)); + assert!(LBPPallet::exists(reversed_asset_pair)); + assert!(!LBPPallet::exists(non_existing_asset_pair)); + + assert_eq!(LBPPallet::get_pair_id(asset_pair), KUSD_BSX_POOL_ID); + assert_eq!(LBPPallet::get_pair_id(reversed_asset_pair), KUSD_BSX_POOL_ID); + + assert_eq!(LBPPallet::get_pool_assets(&KUSD_BSX_POOL_ID), Some(vec![KUSD, BSX])); + assert_eq!(LBPPallet::get_pool_assets(&HDX_BSX_POOL_ID), None); + + // calculate_spot_price is tested in get_spot_price_should_work + // execute_sell and execute_buy is tested in execute_sell_should_work and execute_buy_should_work + + let who = BOB; + let amount_in = 1_000_000; + let sell_limit = 100_000; + let pool_id = LBPPallet::get_pair_id(asset_pair); + let pool_data = LBPPallet::pool_data(pool_id).unwrap(); + + let fee = LBPPallet::calculate_fees(&pool_data, amount_in).unwrap(); + + let t_sell = AMMTransfer { + origin: who, + assets: asset_pair, + amount: amount_in - fee, + amount_b: 563_741, + discount: false, + discount_amount: 0_u128, + fee: (asset_pair.asset_in, fee), + }; + + assert_eq!( + LBPPallet::validate_sell(&who, asset_pair, amount_in, sell_limit, false).unwrap(), + t_sell + ); + + let amount_b = 1_000_000; + let buy_limit = 10_000_000; + let t_buy = AMMTransfer { + origin: who, + assets: asset_pair, + amount: 1_771_197, + amount_b, + discount: false, + discount_amount: 0_u128, + fee: (asset_pair.asset_in, 3_548), + }; + assert_eq!( + LBPPallet::validate_buy(&who, asset_pair, amount_in, buy_limit, false).unwrap(), + t_buy + ); + + assert_eq!( + LBPPallet::get_min_trading_limit(), + ::MinTradingLimit::get() + ); + assert_eq!( + LBPPallet::get_min_pool_liquidity(), + ::MinPoolLiquidity::get() + ); + assert_eq!(LBPPallet::get_max_in_ratio(), ::MaxInRatio::get()); + assert_eq!(LBPPallet::get_max_out_ratio(), ::MaxOutRatio::get()); + + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + HDX, + 1_000_000_000, + BSX, + 2_000_000_000, + 20_000_000, + 80_000_000, + WeightCurveType::Linear, + (400, 1_000), + CHARLIE, + 0, + )); + + let pool_id = LBPPallet::get_pair_id(AssetPair { + asset_in: HDX, + asset_out: BSX, + }); + // existing pool + assert_eq!(LBPPallet::get_fee(&pool_id), (400, 1_000)); + // not existing pool + assert_eq!(LBPPallet::get_fee(&1_234), (0, 0)); + }); +} + +#[test] +fn get_spot_price_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 1_000_000_000, + BSX, + 2_000_000_000, + 20_000_000, + 90_000_000, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + )); + + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + Some(10), + Some(20), + None, + None, + None, + None, + None + )); + + set_block_number(10); + + let price = hydra_dx_math::lbp::calculate_spot_price( + 1_000_000_000_u128, + 2_000_000_000_u128, + 20_u32, + 80_u32, + 1_000_000_u128, + ) + .unwrap_or_else(|_| BalanceOf::::zero()); + + assert_eq!(LBPPallet::get_spot_price_unchecked(KUSD, BSX, 1_000_000_u128), price); + + // swap assets + let price = hydra_dx_math::lbp::calculate_spot_price( + 2_000_000_000_u128, + 1_000_000_000_u128, + 80_u32, + 20_u32, + 1_000_000_u128, + ) + .unwrap_or_else(|_| BalanceOf::::zero()); + + assert_eq!(LBPPallet::get_spot_price_unchecked(BSX, KUSD, 1_000_000_u128), price); + + // change weights + set_block_number(20); + + let price = hydra_dx_math::lbp::calculate_spot_price( + 1_000_000_000_u128, + 2_000_000_000_u128, + 90_u32, + 10_u32, + 1_000_000_u128, + ) + .unwrap_or_else(|_| BalanceOf::::zero()); + + assert_eq!(LBPPallet::get_spot_price_unchecked(KUSD, BSX, 1_000_000), price); + + // pool does not exist + assert_eq!(LBPPallet::get_spot_price_unchecked(KUSD, HDX, 1_000_000), 0); + + // overflow + assert_eq!(LBPPallet::get_spot_price_unchecked(KUSD, BSX, u128::MAX), 0); + + // sale ended + set_block_number(21); + assert_eq!(LBPPallet::get_spot_price_unchecked(KUSD, BSX, 1_000_000), 0); + }); +} + +#[test] +fn simulate_lbp_event_should_work() { + new_test_ext().execute_with(|| { + // setup + let pool_owner = BOB; + let lbp_participant = CHARLIE; + + let asset_in = BSX; + let asset_in_pool_reserve: u128 = 1_000_000; + let owner_initial_asset_in_balance: u128 = 1_000_000_000_000; + let lbp_participant_initial_asset_in_balance: u128 = 1_000_000_000_000; + + let asset_in_initial_weight = 10_000_000; // 10% + let asset_in_final_weight = 75_000_000; // 75% + + let asset_out = HDX; + let asset_out_pool_reserve: u128 = 500_000_000; + let owner_initial_asset_out_balance: u128 = 1_000_000_000_000; + let lbp_participant_initial_asset_out_balance: u128 = 1_000_000_000_000; + + let sale_start: u64 = 1_000; + let sale_end: u64 = 22_600; // in blocks; 3 days + + let trades = generate_trades(sale_start, sale_end, 200_000_000, 2); + + let fee = (9, 1_000); + + let fee_collector = ALICE; + + let trade_limit_factor: u128 = 1_000; + + // preparations + let asset_pair = AssetPair { asset_in, asset_out }; + let pool_account = LBPPallet::get_pair_id(asset_pair); + + Currency::set_balance(Origin::root(), fee_collector, asset_in, 0, 0).unwrap(); + Currency::set_balance(Origin::root(), fee_collector, asset_out, 0, 0).unwrap(); + + Currency::set_balance(Origin::root(), pool_owner, asset_in, 0, 0).unwrap(); + Currency::set_balance(Origin::root(), pool_owner, asset_out, 0, 0).unwrap(); + + Currency::set_balance( + Origin::root(), + pool_owner, + asset_in, + owner_initial_asset_in_balance + .checked_add(asset_in_pool_reserve) + .unwrap(), + 0, + ) + .unwrap(); + Currency::set_balance( + Origin::root(), + pool_owner, + asset_out, + owner_initial_asset_out_balance + .checked_add(asset_out_pool_reserve) + .unwrap(), + 0, + ) + .unwrap(); + + ::MultiCurrency::update_balance( + asset_in, + &lbp_participant, + lbp_participant_initial_asset_in_balance.try_into().unwrap(), + ) + .unwrap(); + ::MultiCurrency::update_balance( + asset_out, + &lbp_participant, + lbp_participant_initial_asset_out_balance.try_into().unwrap(), + ) + .unwrap(); + + assert_ok!(LBPPallet::create_pool( + Origin::root(), + pool_owner, + asset_in, + asset_in_pool_reserve, + asset_out, + asset_out_pool_reserve, + asset_in_initial_weight, + asset_in_final_weight, + WeightCurveType::Linear, + fee, + fee_collector, + 0, + )); + + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(pool_owner), + pool_account, + None, + Some(sale_start), + Some(sale_end), + None, + None, + None, + None, + None + )); + + set_block_number(sale_start.checked_sub(1).unwrap()); + //frame_system::Pallet::::set_block_number(sale_start + 1); + + // start LBP + for block_num in sale_start..=sale_end { + set_block_number(block_num); + + if let Some((is_buy, amount)) = trades.get(&block_num) { + if *is_buy { + assert_ok!(LBPPallet::buy( + Origin::signed(lbp_participant), + asset_out, + asset_in, + *amount, + amount.saturating_mul(trade_limit_factor) + )); + } else { + assert_ok!(LBPPallet::sell( + Origin::signed(lbp_participant), + asset_out, + asset_in, + *amount, + amount.checked_div(trade_limit_factor).unwrap() + )); + } + } + } + + // end LBP and consolidate results + set_block_number(sale_end.checked_add(1).unwrap()); + + let pool_account_result_asset_in = Currency::free_balance(asset_in, &pool_account); + let pool_account_result_asset_out = Currency::free_balance(asset_out, &pool_account); + + assert_eq!( + Currency::free_balance(asset_in, &pool_owner), + owner_initial_asset_in_balance + ); + assert_eq!( + Currency::free_balance(asset_out, &pool_owner), + owner_initial_asset_out_balance + ); + + // TODO: figure out why this changed so much: 4_893_544 -> 4_892_751 + assert_eq!(Currency::free_balance(asset_in, &pool_account), 4_892_751); + assert_eq!(Currency::free_balance(asset_out, &pool_account), 125_000_009); + + // TODO: figure out why this changed so much: 999_996_061_843 -> 999_996_062_654 + assert_eq!(Currency::free_balance(asset_in, &lbp_participant), 999_996_062_654); + assert_eq!(Currency::free_balance(asset_out, &lbp_participant), 1_000_374_999_991); + + // remove liquidity from the pool + assert_ok!(LBPPallet::remove_liquidity(Origin::signed(pool_owner), pool_account)); + + assert_eq!(Currency::free_balance(asset_in, &pool_account), 0); + assert_eq!(Currency::free_balance(asset_out, &pool_account), 0); + + assert_eq!( + Currency::free_balance(asset_in, &pool_owner), + owner_initial_asset_in_balance + .checked_add(pool_account_result_asset_in) + .unwrap() + ); + assert_eq!( + Currency::free_balance(asset_out, &pool_owner), + owner_initial_asset_out_balance + .checked_add(pool_account_result_asset_out) + .unwrap() + ); + + assert_eq!(Currency::free_balance(asset_in, &fee_collector), 44_595); + assert_eq!(Currency::free_balance(asset_out, &fee_collector), 0); + }); +} + +#[test] +fn validate_trade_should_work() { + predefined_test_ext().execute_with(|| { + run_to_sale_start(); + + assert_eq!( + LBPPallet::validate_buy( + &ALICE, + AssetPair { + asset_in: KUSD, + asset_out: BSX + }, + 1_000_000_u128, + 2_157_153_u128, + false + ) + .unwrap(), + AMMTransfer { + origin: ALICE, + assets: AssetPair { + asset_in: KUSD, + asset_out: BSX + }, + amount: 1_998_500_u128, + amount_b: 1_000_000_u128, + discount: false, + discount_amount: 0_u128, + fee: (KUSD, 4_004), + } + ); + + assert_eq!( + LBPPallet::validate_sell( + &ALICE, + AssetPair { + asset_in: KUSD, + asset_out: BSX + }, + 1_000_000_u128, + 2_000_u128, + false + ) + .unwrap(), + AMMTransfer { + origin: ALICE, + assets: AssetPair { + asset_in: KUSD, + asset_out: BSX + }, + amount: 998_000_u128, + amount_b: 499_687_u128, + discount: false, + discount_amount: 0_u128, + fee: (KUSD, 2000), + } + ); + }); +} + +#[test] +fn validate_trade_should_not_work() { + predefined_test_ext().execute_with(|| { + set_block_number(9); + + assert_noop!( + LBPPallet::validate_buy( + &ALICE, + AssetPair { + asset_in: KUSD, + asset_out: BSX + }, + 1_000_000_u128, + 2_157_153_u128, + false, + ), + Error::::SaleIsNotRunning + ); + + set_block_number(10); + + assert_noop!( + LBPPallet::validate_buy( + &ALICE, + AssetPair { + asset_in: KUSD, + asset_out: BSX + }, + 0, + 2_157_153_u128, + false, + ), + Error::::ZeroAmount + ); + + Currency::set_balance(Origin::root(), ALICE, KUSD, 10_000_000, 0).unwrap(); + assert_err!( + LBPPallet::validate_buy( + &ALICE, + AssetPair { + asset_in: KUSD, + asset_out: BSX + }, + 100_000_000u128, + 3_000_000_000_u128, + false, + ), + Error::::InsufficientAssetBalance + ); + // set the balance back + Currency::set_balance(Origin::root(), ALICE, KUSD, INITIAL_BALANCE, 0).unwrap(); + + assert_noop!( + LBPPallet::validate_buy( + &ALICE, + AssetPair { + asset_in: KUSD, + asset_out: HDX + }, + 1_000_000_u128, + 2_157_153_u128, + false, + ), + Error::::PoolNotFound + ); + + assert_err!( + LBPPallet::validate_buy( + &ALICE, + AssetPair { + asset_in: KUSD, + asset_out: BSX + }, + 1_000_000_000_u128, + 2_157_153_u128, + false, + ), + Error::::MaxOutRatioExceeded + ); + + assert_err!( + LBPPallet::validate_sell( + &ALICE, + AssetPair { + asset_in: KUSD, + asset_out: BSX + }, + 400_000_000_u128, + 2_157_153_u128, + false, + ), + Error::::MaxInRatioExceeded + ); + + assert_err!( + LBPPallet::validate_sell( + &ALICE, + AssetPair { + asset_in: KUSD, + asset_out: BSX + }, + 1_000_u128, + 500_u128, + false, + ), + Error::::TradingLimitReached + ); + + assert_err!( + LBPPallet::validate_buy( + &ALICE, + AssetPair { + asset_in: KUSD, + asset_out: BSX + }, + 1_000_u128, + 1_994_u128, + false, + ), + Error::::TradingLimitReached + ); + + Currency::set_balance(Origin::root(), ALICE, KUSD, INITIAL_BALANCE, 0).unwrap(); + Currency::set_balance(Origin::root(), ALICE, HDX, INITIAL_BALANCE, 0).unwrap(); + + // transfer fee > token amount in + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + HDX, + 1_000_000_000, + KUSD, + 2_000_000_000, + 20_000_000, + 80_000_000, + WeightCurveType::Linear, + (10, 1), + CHARLIE, + 0, + )); + let pool_id2 = LBPPallet::get_pair_id(AssetPair { + asset_in: KUSD, + asset_out: HDX, + }); + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + pool_id2, + None, + Some(12), + Some(20), + None, + None, + None, + None, + None + )); + }); +} + +#[test] +fn get_sorted_weight_should_work() { + predefined_test_ext().execute_with(|| { + let pool = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + + assert_eq!( + LBPPallet::get_sorted_weight(KUSD, BlockNumberFor::::from(10u32), &pool).unwrap(), + (20_000_000, 80_000_000), + ); + + assert_eq!( + LBPPallet::get_sorted_weight(BSX, BlockNumberFor::::from(10u32), &pool).unwrap(), + (80_000_000, 20_000_000), + ); + + assert_err!( + LBPPallet::get_sorted_weight(KUSD, BlockNumberFor::::from(41u32), &pool) + .map_err(Into::::into), + Error::::InvalidWeight + ); + }); +} + +#[test] +fn calculate_fees_should_work() { + predefined_test_ext().execute_with(|| { + let pool = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + + assert_eq!(LBPPallet::calculate_fees(&pool, 1_234_567_890_u128).unwrap(), 2_469_134,); + + assert_eq!(LBPPallet::calculate_fees(&pool, 1000_u128).unwrap(), 2,); + + assert_eq!(LBPPallet::calculate_fees(&pool, 1999_u128).unwrap(), 2,); + + assert_eq!(LBPPallet::calculate_fees(&pool, 999_u128).unwrap(), 0,); + + assert_eq!( + LBPPallet::calculate_fees(&pool, u128::MAX).unwrap(), + 680564733841876926926749214863536422 + ); + + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + HDX, + 1_000_000_000, + BSX, + 2_000_000_000, + 80_000_000, + 20_000_000, + WeightCurveType::Linear, + (10, 1), + CHARLIE, + 0, + )); + + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + SALE_START, + Some(20), + None, + None, + None, + None, + None, + )); + + let pool = LBPPallet::pool_data(HDX_BSX_POOL_ID).unwrap(); + + assert_err!( + LBPPallet::calculate_fees(&pool, u128::MAX), + Error::::FeeAmountInvalid, + ); + }); +} + +#[test] +fn can_create_should_work() { + new_test_ext().execute_with(|| { + let asset_pair = AssetPair { + asset_in: KUSD, + asset_out: BSX, + }; + // pool doesn't exist + assert!(DisallowWhenLBPPoolRunning::::can_create( + asset_pair.asset_in, + asset_pair.asset_out + )); + + assert_ok!(LBPPallet::create_pool( + Origin::root(), + ALICE, + KUSD, + 1_000_000_000, + BSX, + 2_000_000_000, + 20_000_000, + 80_000_000, + WeightCurveType::Linear, + DEFAULT_FEE, + CHARLIE, + 0, + )); + // pool is not initialized + assert!(!DisallowWhenLBPPoolRunning::::can_create( + asset_pair.asset_in, + asset_pair.asset_out + )); + + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(ALICE), + KUSD_BSX_POOL_ID, + None, + Some(10), + Some(20), + None, + None, + None, + None, + None, + )); + // pool is initialized but is not running + assert!(!DisallowWhenLBPPoolRunning::::can_create( + asset_pair.asset_in, + asset_pair.asset_out + )); + + set_block_number(15); + // pool is running + assert!(!DisallowWhenLBPPoolRunning::::can_create( + asset_pair.asset_in, + asset_pair.asset_out + )); + + set_block_number(30); + // sale ended + assert!(DisallowWhenLBPPoolRunning::::can_create( + asset_pair.asset_in, + asset_pair.asset_out + )); + + assert_ok!(LBPPallet::remove_liquidity(Origin::signed(ALICE), KUSD_BSX_POOL_ID,)); + // pool was destroyed + assert!(DisallowWhenLBPPoolRunning::::can_create( + asset_pair.asset_in, + asset_pair.asset_out + )); + }); +} + +#[test] +fn repay_fee_not_applied_when_set_to_zero() { + new_test_ext().execute_with(|| { + let pool = Pool { + repay_target: 0, + ..SAMPLE_POOL_DATA + }; + assert_eq!(LBPPallet::is_repay_fee_applied(&pool), false); + }); +} + +#[test] +fn repay_fee_applied_when_set() { + new_test_ext().execute_with(|| { + let pool = Pool { + repay_target: 10_000_000, + ..SAMPLE_POOL_DATA + }; + assert_eq!(LBPPallet::is_repay_fee_applied(&pool), true); + }); +} + +#[test] +fn repay_fee_not_applied_when_target_reached() { + new_test_ext().execute_with(|| { + let pool = Pool { + fee_collector: ALICE, + repay_target: INITIAL_BALANCE, + ..SAMPLE_POOL_DATA + }; + assert_ok!(Currency::set_lock( + COLLECTOR_LOCK_ID, + pool.assets.0, + &ALICE, + INITIAL_BALANCE + )); + assert_eq!(LBPPallet::is_repay_fee_applied(&pool), false); + }); +} + +#[test] +fn repay_fee_not_applied_in_predefined_env() { + predefined_test_ext().execute_with(|| { + let pool = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + assert_eq!(LBPPallet::is_repay_fee_applied(&pool), false); + }); +} + +#[test] +fn repay_fee_applied_in_env_with_repay_target() { + predefined_test_ext_with_repay_target().execute_with(|| { + let pool = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + assert_eq!(LBPPallet::is_repay_fee_applied(&pool), true); + }); +} + +#[test] +fn calculate_repay_fee() { + predefined_test_ext_with_repay_target().execute_with(|| { + let pool = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + + assert_eq!(LBPPallet::calculate_fees(&pool, 1000).unwrap(), 200,); + }); +} + +#[test] +fn repay_fee_should_work() { + new_test_ext().execute_with(|| { + assert_eq!(LBPPallet::repay_fee(), (2, 10)); + }); +} + +#[test] +fn collected_fees_should_be_locked_and_unlocked_after_liquidity_is_removed() { + predefined_test_ext().execute_with(|| { + run_to_sale_start(); + let Pool { fee_collector, .. } = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + let (fee_asset, fee_amount) = SAMPLE_AMM_TRANSFER.fee; + assert_ok!(LBPPallet::execute_buy(&SAMPLE_AMM_TRANSFER, None)); + + // collector receives locked fee + assert_eq!(Currency::free_balance(fee_asset, &fee_collector), fee_amount); + assert_eq!( + ::LockedBalance::get_by_lock(COLLECTOR_LOCK_ID, fee_asset, fee_collector), + fee_amount + ); + + // still locked after sale ends + run_to_sale_end(); + assert_eq!( + ::LockedBalance::get_by_lock(COLLECTOR_LOCK_ID, fee_asset, fee_collector), + fee_amount + ); + + // unlocked after liquidity is removed from pool + assert_ok!(LBPPallet::remove_liquidity(Origin::signed(ALICE), KUSD_BSX_POOL_ID)); + assert_eq!( + ::LockedBalance::get_by_lock(COLLECTOR_LOCK_ID, fee_asset, fee_collector), + 0 + ); + }); +} + +#[test] +fn collected_fees_are_continually_locked() { + predefined_test_ext().execute_with(|| { + run_to_sale_start(); + let Pool { fee_collector, .. } = LBPPallet::pool_data(KUSD_BSX_POOL_ID).unwrap(); + let (fee_asset, fee_amount) = SAMPLE_AMM_TRANSFER.fee; + assert_ok!(LBPPallet::execute_buy(&SAMPLE_AMM_TRANSFER, None)); + assert_ok!(LBPPallet::execute_buy(&SAMPLE_AMM_TRANSFER, None)); + let total = 2 * fee_amount; + assert_eq!(Currency::free_balance(fee_asset, &fee_collector), total); + assert_eq!( + ::LockedBalance::get_by_lock(COLLECTOR_LOCK_ID, fee_asset, fee_collector), + total + ); + }); +} + +#[ignore] +#[test] +fn simulate_lbp_event_with_repayment() { + new_test_ext().execute_with(|| { + // setup + let pool_owner = ALICE; + let lbp_participant = BOB; + let initial_balance: u128 = 1_000_000_000_000_000_000_000_000; + + let accumulated_asset = BSX; + let asset_in_pool_reserve: u128 = 1_000_000_000_000; + + let sold_asset = HDX; + let asset_out_pool_reserve: u128 = 500_000_000_000_000; + + let initial_weight = 90_000_000; + let final_weight = 30_000_000; + + let sale_start: u64 = 1_000; + let sale_end: u64 = 22_600; // in blocks; 3 days + + let trades = generate_trades(sale_start, sale_end, 500_000_000_000, 4); + + let fee = (9, 1_000); + + let fee_collector = CHARLIE; + + let trade_limit_factor: u128 = 1_000_000_000; + + // preparations + let asset_pair = AssetPair { + asset_in: accumulated_asset, + asset_out: sold_asset, + }; + let pool_account = LBPPallet::get_pair_id(asset_pair); + + assert_ok!(LBPPallet::create_pool( + Origin::root(), + pool_owner, + accumulated_asset, + asset_in_pool_reserve, + sold_asset, + asset_out_pool_reserve, + initial_weight, + final_weight, + WeightCurveType::Linear, + fee, + fee_collector, + 0, + )); + + assert_ok!(LBPPallet::update_pool_data( + Origin::signed(pool_owner), + pool_account, + None, + Some(sale_start), + Some(sale_end), + None, + None, + None, + None, + None + )); + + set_block_number(sale_start.checked_sub(1).unwrap()); + //frame_system::Pallet::::set_block_number(sale_start + 1); + + // start LBP + for block_num in sale_start..=sale_end { + set_block_number(block_num); + println!("{}", LBPPallet::get_spot_price_unchecked(HDX, BSX, 100_000_000_000)); + if let Some((is_buy, amount)) = trades.get(&block_num) { + if *is_buy { + assert_ok!(LBPPallet::buy( + Origin::signed(lbp_participant), + accumulated_asset, + sold_asset, + *amount, + amount.saturating_mul(trade_limit_factor) + )); + } else { + assert_ok!(LBPPallet::sell( + Origin::signed(lbp_participant), + accumulated_asset, + sold_asset, + *amount, + amount.checked_div(trade_limit_factor).unwrap() + )); + } + } + } + + // end LBP and consolidate results + set_block_number(sale_end.checked_add(1).unwrap()); + + let pool_account_result_asset_in = Currency::free_balance(accumulated_asset, &pool_account); + let pool_account_result_asset_out = Currency::free_balance(sold_asset, &pool_account); + + assert_eq!(Currency::free_balance(accumulated_asset, &pool_owner), initial_balance); + assert_eq!(Currency::free_balance(sold_asset, &pool_owner), initial_balance); + + assert_eq!(Currency::free_balance(accumulated_asset, &pool_account), 4_970_435); + assert_eq!(Currency::free_balance(sold_asset, &pool_account), 125_000_009); + + assert_eq!( + Currency::free_balance(accumulated_asset, &lbp_participant), + 999_995_984_267 + ); + assert_eq!(Currency::free_balance(sold_asset, &lbp_participant), 1_000_374_999_991); + + // remove liquidity from the pool + assert_ok!(LBPPallet::remove_liquidity(Origin::signed(pool_owner), pool_account)); + + assert_eq!(Currency::free_balance(accumulated_asset, &pool_account), 0); + assert_eq!(Currency::free_balance(sold_asset, &pool_account), 0); + + assert_eq!( + Currency::free_balance(accumulated_asset, &pool_owner), + initial_balance.checked_add(pool_account_result_asset_in).unwrap() + ); + assert_eq!( + Currency::free_balance(sold_asset, &pool_owner), + initial_balance.checked_add(pool_account_result_asset_out).unwrap() + ); + + assert_eq!(Currency::free_balance(accumulated_asset, &fee_collector), 45_298); + assert_eq!(Currency::free_balance(sold_asset, &fee_collector), 0); + }); +} +mod spot_price_calculation { + use super::*; + use crate::mock::RuntimeOrigin; + use basilisk_traits::router::PoolType; + use basilisk_traits::router::TradeExecution; + use frame_support::storage::with_transaction; + use hydradx_traits::pools::SpotPriceProvider; + use sp_runtime::FixedPointNumber; + use sp_runtime::{FixedU128, TransactionOutcome}; + use test_utils::assert_eq_approx; + + pub const ONE: u128 = 1_000_000_000_000u128; + + #[test] + pub fn compare_spot_price_with_and_without_fee_when_pool_pays_fee() { + predefined_test_ext().execute_with(|| { + let asset_a = BSX; + let asset_b = KUSD; + + let sell_amount = 8_000_000_u128; + + //start sale + set_block_number(11); + + let received = with_transaction::(|| { + let balance_before = Currency::free_balance(asset_b, &ALICE); + assert_ok!(LBPPallet::sell( + RuntimeOrigin::signed(ALICE), + asset_a, + asset_b, + sell_amount, + u128::MIN + )); + let balance_after = Currency::free_balance(asset_b, &ALICE); + let received = balance_after - balance_before; + TransactionOutcome::Rollback(Ok(received)) + }) + .unwrap(); + + //Check spot price without fee + let spot_price_without_fee = LBPPallet::spot_price(asset_a, asset_b).unwrap(); + let calculated_amount_out_without_fee = spot_price_without_fee + .reciprocal() + .unwrap() + .checked_mul_int(sell_amount) + .unwrap(); + let difference = calculated_amount_out_without_fee - received; + let relative_difference_without_fee = FixedU128::from_rational(difference, received); + let tolerated_difference = FixedU128::from_rational(2, 100); + + // The difference of the amount out calculated with spot price should be less than 2% + assert_eq_approx!( + relative_difference_without_fee, + FixedU128::from_float(0.011128473641983631), + FixedU128::from((2, (ONE / 10_000))), + "the relative difference is not as expected" + ); + assert!(relative_difference_without_fee < tolerated_difference); + + //Check spot price with fee + let spot_price_with_fee = + LBPPallet::calculate_spot_price_with_fee(PoolType::LBP, asset_a, asset_b).unwrap(); + let calculated_amount_out_with_fee = spot_price_with_fee + .reciprocal() + .unwrap() + .checked_mul_int(sell_amount) + .unwrap(); + let difference = calculated_amount_out_with_fee - received; + let relative_difference_with_fee = FixedU128::from_rational(difference, received); + let tolerated_difference = FixedU128::from_rational(1, 100); + + assert_eq_approx!( + relative_difference_with_fee, + FixedU128::from_float(0.009106190742401841), + FixedU128::from((2, (ONE / 10_000))), + "the relative difference is not as expected" + ); + // The difference of the amount out calculated with spot price should be less than 0.1% + assert!(relative_difference_with_fee < tolerated_difference); + + //Compare the two price + assert!(relative_difference_with_fee < relative_difference_without_fee); + + assert!( + spot_price_with_fee > spot_price_without_fee, + "Spot price with fee should be smaller than without fee" + ); + }) + } + + #[test] + pub fn spot_price_with_and_without_fee_should_be_the_same_when_distributed_asset_bought() { + predefined_test_ext().execute_with(|| { + let asset_a = KUSD; + let asset_b = BSX; + let sell_amount = 100000_u128; + + //start sale + set_block_number(11); + + let received = with_transaction::(|| { + let balance_before = Currency::free_balance(asset_b, &ALICE); + assert_ok!(LBPPallet::sell( + RuntimeOrigin::signed(ALICE), + asset_a, + asset_b, + sell_amount, + u128::MIN + )); + let balance_after = Currency::free_balance(asset_b, &ALICE); + let received = balance_after - balance_before; + TransactionOutcome::Rollback(Ok(received)) + }) + .unwrap(); + + //Check spot price without fee + let spot_price_without_fee = LBPPallet::spot_price(asset_a, asset_b).unwrap(); + let calculated_amount_out_without_fee = spot_price_without_fee + .reciprocal() + .unwrap() + .checked_mul_int(sell_amount) + .unwrap(); + let difference = calculated_amount_out_without_fee - received; + let relative_difference_without_fee = FixedU128::from_rational(difference, received); + let tolerated_difference = FixedU128::from_rational(1, 1000); + + // The difference of the amount out calculated with spot price should be less than 0.1% + assert_eq_approx!( + relative_difference_without_fee, + FixedU128::from_float(0.000070914441726058), + FixedU128::from((2, (ONE / 10_000))), + "the relative difference is not as expected" + ); + assert!(relative_difference_without_fee < tolerated_difference); + + //Check spot price with fee + let spot_price_with_fee = + LBPPallet::calculate_spot_price_with_fee(PoolType::LBP, asset_a, asset_b).unwrap(); + assert_eq_approx!( + spot_price_without_fee, + spot_price_with_fee, + FixedU128::from((2, (ONE / 10_000))), + "the relative difference is not as expected" + ); + }) + } + + #[test] + pub fn compare_spot_price_with_and_without_fee_when_repay_fee_paid() { + predefined_test_ext_with_repay_target().execute_with(|| { + let asset_a = BSX; + let asset_b = KUSD; + + let sell_amount = 100000_u128; + + //start sale + set_block_number(11); + + let received = with_transaction::(|| { + let balance_before = Currency::free_balance(asset_b, &ALICE); + assert_ok!(LBPPallet::sell( + RuntimeOrigin::signed(ALICE), + asset_a, + asset_b, + sell_amount, + u128::MIN + )); + let balance_after = Currency::free_balance(asset_b, &ALICE); + let received = balance_after - balance_before; + TransactionOutcome::Rollback(Ok(received)) + }) + .unwrap(); + + //Check spot price without fee + let spot_price_without_fee = LBPPallet::spot_price(asset_a, asset_b).unwrap(); + let calculated_amount_out_without_fee = spot_price_without_fee + .reciprocal() + .unwrap() + .checked_mul_int(sell_amount) + .unwrap(); + let difference = calculated_amount_out_without_fee - received; + let relative_difference_without_fee = FixedU128::from_rational(difference, received); + + // The difference of the amount out calculated with spot price should be less than 3% + assert_eq_approx!( + relative_difference_without_fee, + FixedU128::from_float(0.250016980235006452), + FixedU128::from((2, (ONE / 10_000))), + "the relative difference is not as expected" + ); + + //Check spot price with fee + let spot_price_with_fee = + LBPPallet::calculate_spot_price_with_fee(PoolType::LBP, asset_a, asset_b).unwrap(); + let calculated_amount_out_with_fee = spot_price_with_fee + .reciprocal() + .unwrap() + .checked_mul_int(sell_amount) + .unwrap(); + let difference = calculated_amount_out_with_fee - received; + let relative_difference_with_fee = FixedU128::from_rational(difference, received); + let tolerated_difference = FixedU128::from_rational(1, 1000); + + assert_eq_approx!( + relative_difference_with_fee, + FixedU128::from_float(0.000019405982864517), + FixedU128::from((2, (ONE / 10_000))), + "the relative difference is not as expected" + ); + // The difference of the amount out calculated with spot price should be less than 0.1% + assert!(relative_difference_with_fee < tolerated_difference); + + //Compare the two price + assert!(relative_difference_with_fee < relative_difference_without_fee); + + assert!( + spot_price_with_fee > spot_price_without_fee, + "Spot price with fee should be smaller than without fee" + ); + }) + } +} diff --git a/pallets/lbp/src/trade_execution.rs b/pallets/lbp/src/trade_execution.rs new file mode 100644 index 00000000000..d750c24fb91 --- /dev/null +++ b/pallets/lbp/src/trade_execution.rs @@ -0,0 +1,199 @@ +use crate::*; +use basilisk_traits::router::{ExecutorError, PoolType, TradeExecution}; +use hydradx_traits::AMM; +use orml_traits::MultiCurrency; +use sp_runtime::traits::BlockNumberProvider; +use sp_runtime::DispatchError::Corruption; +use sp_runtime::{ArithmeticError, DispatchError, FixedPointNumber, FixedU128}; + +impl TradeExecution for Pallet { + type Error = DispatchError; + + fn calculate_sell( + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_in: Balance, + ) -> Result> { + if pool_type != PoolType::LBP { + return Err(ExecutorError::NotSupported); + } + + let assets = AssetPair { asset_in, asset_out }; + let pool_id = Self::get_pair_id(assets); + let pool_data = + >::try_get(&pool_id).map_err(|_| ExecutorError::Error(Error::::PoolNotFound.into()))?; + + let now = T::BlockNumberProvider::current_block_number(); + let (weight_in, weight_out) = Self::get_sorted_weight(assets.asset_in, now, &pool_data) + .map_err(|err| ExecutorError::Error(err.into()))?; + let asset_in_reserve = T::MultiCurrency::free_balance(assets.asset_in, &pool_id); + let asset_out_reserve = T::MultiCurrency::free_balance(assets.asset_out, &pool_id); + + let amount_out = hydra_dx_math::lbp::calculate_out_given_in( + asset_in_reserve, + asset_out_reserve, + weight_in, + weight_out, + amount_in, + ) + .map_err(|_| ExecutorError::Error(Error::::Overflow.into()))?; + + let fee_asset = pool_data.assets.0; + if fee_asset == assets.asset_in { + Ok(amount_out) //amount with fee applied as the user is responsible to send fee to the fee collector + } else { + let fee = Self::calculate_fees(&pool_data, amount_out).map_err(ExecutorError::Error)?; + let amount_out_without_fee = amount_out + .checked_sub(fee) + .ok_or_else(|| ExecutorError::Error(Error::::Overflow.into()))?; + + Ok(amount_out_without_fee) //amount without fee as the pool is responsible to send fee to the fee collector + } + } + + fn calculate_buy( + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_out: Balance, + ) -> Result> { + if pool_type != PoolType::LBP { + return Err(ExecutorError::NotSupported); + } + + let assets = AssetPair { asset_in, asset_out }; + let pool_id = Self::get_pair_id(assets); + let pool_data = + >::try_get(&pool_id).map_err(|_| ExecutorError::Error(Error::::PoolNotFound.into()))?; + + let now = T::BlockNumberProvider::current_block_number(); + let (weight_in, weight_out) = Self::get_sorted_weight(assets.asset_in, now, &pool_data) + .map_err(|err| ExecutorError::Error(err.into()))?; + let asset_in_reserve = T::MultiCurrency::free_balance(assets.asset_in, &pool_id); + let asset_out_reserve = T::MultiCurrency::free_balance(assets.asset_out, &pool_id); + + let fee_asset = pool_data.assets.0; + if fee_asset == assets.asset_out { + let fee = Self::calculate_fees(&pool_data, amount_out).map_err(ExecutorError::Error)?; + let amount_out_plus_fee = amount_out + .checked_add(fee) + .ok_or_else(|| ExecutorError::Error(Error::::Overflow.into()))?; + + let calculated_in = hydra_dx_math::lbp::calculate_in_given_out( + asset_in_reserve, + asset_out_reserve, + weight_in, + weight_out, + amount_out_plus_fee, + ) + .map_err(|_| ExecutorError::Error(Error::::Overflow.into()))?; + + Ok(calculated_in) //TODO: Double check with someone if this is correct + } else { + let calculated_in = hydra_dx_math::lbp::calculate_in_given_out( + asset_in_reserve, + asset_out_reserve, + weight_in, + weight_out, + amount_out, + ) + .map_err(|_| ExecutorError::Error(Error::::Overflow.into()))?; + + Ok(calculated_in) //amount with fee applied as the user is responsible to send fee to the fee collector + } + } + + fn execute_sell( + who: T::RuntimeOrigin, + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_in: Balance, + min_limit: Balance, + ) -> Result<(), ExecutorError> { + if pool_type != PoolType::LBP { + return Err(ExecutorError::NotSupported); + } + + Self::sell(who, asset_in, asset_out, amount_in, min_limit).map_err(ExecutorError::Error) + } + + fn execute_buy( + who: T::RuntimeOrigin, + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_out: Balance, + max_limit: Balance, + ) -> Result<(), ExecutorError> { + if pool_type != PoolType::LBP { + return Err(ExecutorError::NotSupported); + } + + Self::buy(who, asset_out, asset_in, amount_out, max_limit).map_err(ExecutorError::Error) + } + + fn get_liquidity_depth( + pool_type: PoolType, + asset_a: AssetId, + asset_b: AssetId, + ) -> Result> { + if pool_type != PoolType::LBP { + return Err(ExecutorError::NotSupported); + } + + let asset_pair = AssetPair::new(asset_a, asset_b); + let pair_account = Self::get_pair_id(asset_pair); + + let liquidty = T::MultiCurrency::free_balance(asset_a, &pair_account); + + Ok(liquidty) + } + + fn calculate_spot_price_with_fee( + pool_type: PoolType, + asset_a: AssetId, + asset_b: AssetId, + ) -> Result> { + if pool_type != PoolType::LBP { + return Err(ExecutorError::NotSupported); + } + + let assets = AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }; + let pool_id = Self::get_pair_id(assets); + let pool_data = + >::try_get(&pool_id).map_err(|_| ExecutorError::Error(Error::::PoolNotFound.into()))?; + let now = T::BlockNumberProvider::current_block_number(); + + let (weight_in, weight_out) = + Self::get_sorted_weight(asset_a, now, &pool_data).map_err(|err| ExecutorError::Error(err.into()))?; + let fee_asset = pool_data.assets.0; + + let fee = if Self::is_repay_fee_applied(&pool_data) { + Self::repay_fee() + } else { + pool_data.fee + }; + + let asset_in_reserve = T::MultiCurrency::free_balance(asset_a, &pool_id); + let asset_out_reserve = T::MultiCurrency::free_balance(asset_b, &pool_id); + let spot_price_with_fee = hydra_dx_math::lbp::calculate_spot_price_with_fee( + asset_in_reserve, + asset_out_reserve, + weight_in, + weight_out, + fee_asset, + asset_b, + Some(fee), + ) + .map_err(|_| ExecutorError::Error(ArithmeticError::Overflow.into()))? + .reciprocal() + .ok_or(ExecutorError::Error(Corruption))?; + + Ok(spot_price_with_fee) + } +} diff --git a/pallets/lbp/src/types.rs b/pallets/lbp/src/types.rs new file mode 100644 index 00000000000..7d1dcf9f0e8 --- /dev/null +++ b/pallets/lbp/src/types.rs @@ -0,0 +1,67 @@ +// This file is part of HydraDX-node. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub type AssetId = u32; +pub type Amount = i128; +pub type Balance = u128; + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_std::vec::Vec; + +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; + +/// Asset Pair representation for AMM trades +/// `( asset_a, asset_b )` combination where `asset_a` is meant to be exchanged for asset_b +/// +/// `asset_in` represents asset coming into the pool +/// `asset_out` represents asset coming out of the pool +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Debug, Encode, Decode, Copy, Clone, PartialEq, Eq, Default, TypeInfo)] +pub struct AssetPair { + pub asset_in: AssetId, + pub asset_out: AssetId, +} + +impl AssetPair { + pub fn new(asset_in: AssetId, asset_out: AssetId) -> Self { + Self { asset_in, asset_out } + } + + /// Return ordered asset tuple (A,B) where A < B + /// Used in storage + pub fn ordered_pair(&self) -> (AssetId, AssetId) { + match self.asset_in <= self.asset_out { + true => (self.asset_in, self.asset_out), + false => (self.asset_out, self.asset_in), + } + } + + /// Return share token name + pub fn name(&self) -> Vec { + let mut buf: Vec = Vec::new(); + + let (asset_a, asset_b) = self.ordered_pair(); + + buf.extend_from_slice(&asset_a.to_le_bytes()); + buf.extend_from_slice(b"HDT"); + buf.extend_from_slice(&asset_b.to_le_bytes()); + + buf + } +} diff --git a/pallets/lbp/src/weights.rs b/pallets/lbp/src/weights.rs new file mode 100644 index 00000000000..758dfd5a232 --- /dev/null +++ b/pallets/lbp/src/weights.rs @@ -0,0 +1,268 @@ +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_lbp. +pub trait WeightInfo { + fn create_pool() -> Weight; + fn update_pool_data() -> Weight; + fn add_liquidity() -> Weight; + fn remove_liquidity() -> Weight; + fn sell() -> Weight; + fn buy() -> Weight; + fn router_execution_sell(c: u32, e: u32) -> Weight; + fn router_execution_buy(c: u32, e: u32) -> Weight; + fn calculate_buy() -> Weight; + fn calculate_spot_price_with_fee() -> Weight; +} + +/// Weights for pallet_lbp using the hydraDX node and recommended hardware. +impl WeightInfo for () { + /// Storage: `LBP::PoolData` (r:1 w:1) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `LBP::FeeCollectorWithAsset` (r:1 w:1) + /// Proof: `LBP::FeeCollectorWithAsset` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:4 w:4) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:1 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:1 w:1) + /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AcceptedCurrencies` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AcceptedCurrencies` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn create_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `1586` + // Estimated: `11322` + // Minimum execution time: 168_852_000 picoseconds. + Weight::from_parts(169_826_000, 11322) + .saturating_add(RocksDbWeight::get().reads(16_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) + } + /// Storage: `LBP::PoolData` (r:1 w:1) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `LBP::FeeCollectorWithAsset` (r:1 w:2) + /// Proof: `LBP::FeeCollectorWithAsset` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + fn update_pool_data() -> Weight { + // Proof Size summary in bytes: + // Measured: `417` + // Estimated: `3628` + // Minimum execution time: 30_046_000 picoseconds. + Weight::from_parts(30_632_000, 3628) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + } + /// Storage: `LBP::PoolData` (r:1 w:0) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:4 w:4) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:1 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn add_liquidity() -> Weight { + // Proof Size summary in bytes: + // Measured: `1846` + // Estimated: `11322` + // Minimum execution time: 133_474_000 picoseconds. + Weight::from_parts(134_292_000, 11322) + .saturating_add(RocksDbWeight::get().reads(12_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) + } + /// Storage: `LBP::PoolData` (r:1 w:1) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:4 w:4) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:1 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:1 w:1) + /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Locks` (r:1 w:0) + /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `LBP::FeeCollectorWithAsset` (r:0 w:1) + /// Proof: `LBP::FeeCollectorWithAsset` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + fn remove_liquidity() -> Weight { + // Proof Size summary in bytes: + // Measured: `1962` + // Estimated: `11322` + // Minimum execution time: 168_745_000 picoseconds. + Weight::from_parts(169_823_000, 11322) + .saturating_add(RocksDbWeight::get().reads(14_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) + } + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:5 w:5) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `LBP::PoolData` (r:1 w:0) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Locks` (r:1 w:1) + /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:2 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn sell() -> Weight { + // Proof Size summary in bytes: + // Measured: `2251` + // Estimated: `13905` + // Minimum execution time: 278_405_000 picoseconds. + Weight::from_parts(280_656_000, 13905) + .saturating_add(RocksDbWeight::get().reads(17_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) + } + /// Storage: `LBP::PoolData` (r:1 w:0) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:5 w:5) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Locks` (r:1 w:1) + /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:2 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn buy() -> Weight { + // Proof Size summary in bytes: + // Measured: `2251` + // Estimated: `13905` + // Minimum execution time: 278_628_000 picoseconds. + Weight::from_parts(280_382_000, 13905) + .saturating_add(RocksDbWeight::get().reads(17_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) + } + /// Storage: `LBP::PoolData` (r:1 w:0) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:5 w:5) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Locks` (r:1 w:1) + /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:2 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `c` is `[1, 2]`. + /// The range of component `e` is `[0, 1]`. + fn router_execution_sell(c: u32, e: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1052 + e * (1199 ±0)` + // Estimated: `8799 + e * (7749 ±0)` + // Minimum execution time: 102_791_000 picoseconds. + Weight::from_parts(103_541_000, 8799) + // Standard Error: 232_924 + .saturating_add(Weight::from_parts(979_511, 0).saturating_mul(c.into())) + // Standard Error: 518_787 + .saturating_add(Weight::from_parts(178_064_307, 0).saturating_mul(e.into())) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().reads((12_u64).saturating_mul(e.into()))) + .saturating_add(RocksDbWeight::get().writes((7_u64).saturating_mul(e.into()))) + .saturating_add(Weight::from_parts(0, 7749).saturating_mul(e.into())) + } + /// Storage: `LBP::PoolData` (r:1 w:0) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:5 w:5) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Locks` (r:1 w:1) + /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:2 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `c` is `[1, 3]`. + /// The range of component `e` is `[0, 1]`. + fn router_execution_buy(c: u32, e: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1052 + e * (1199 ±0)` + // Estimated: `6190 + e * (8544 ±14_296_005_195_177_084)` + // Minimum execution time: 177_688_000 picoseconds. + Weight::from_parts(178_851_000, 6190) + // Standard Error: 450_328 + .saturating_add(Weight::from_parts(2_999_206, 0).saturating_mul(c.into())) + // Standard Error: 1_518_653 + .saturating_add(Weight::from_parts(137_463_885, 0).saturating_mul(e.into())) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().reads((12_u64).saturating_mul(e.into()))) + .saturating_add(RocksDbWeight::get().writes((7_u64).saturating_mul(e.into()))) + .saturating_add(Weight::from_parts(0, 8544).saturating_mul(e.into())) + } + /// Storage: `LBP::PoolData` (r:1 w:0) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:2 w:0) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + fn calculate_buy() -> Weight { + // Proof Size summary in bytes: + // Measured: `1052` + // Estimated: `6190` + // Minimum execution time: 104_405_000 picoseconds. + Weight::from_parts(104_910_000, 6190) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + } + /// Storage: `LBP::PoolData` (r:1 w:0) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Locks` (r:1 w:0) + /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:2 w:0) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + fn calculate_spot_price_with_fee() -> Weight { + // Proof Size summary in bytes: + // Measured: `1052` + // Estimated: `6190` + // Minimum execution time: 42_800_000 picoseconds. + Weight::from_parts(43_263_000, 6190) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + } +} diff --git a/pallets/marketplace/Cargo.toml b/pallets/marketplace/Cargo.toml index e04a337bf76..f589beb35d7 100644 --- a/pallets/marketplace/Cargo.toml +++ b/pallets/marketplace/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-marketplace" -version = "5.0.20" +version = "5.1.0" authors = ["GalacticCoucil"] description = "The marketplace for trading NFTs" edition = "2018" diff --git a/pallets/marketplace/src/mock.rs b/pallets/marketplace/src/mock.rs index a4d3b4c7ee1..e3b694c81dc 100644 --- a/pallets/marketplace/src/mock.rs +++ b/pallets/marketplace/src/mock.rs @@ -84,6 +84,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type RuntimeFreezeReason = (); + type DoneSlashHandler = (); } impl system::Config for Test { @@ -116,6 +117,7 @@ impl system::Config for Test { type PreInherents = (); type PostInherents = (); type PostTransactions = (); + type ExtensionsWeightInfo = (); } parameter_types! { @@ -211,6 +213,7 @@ impl ExtBuilder { .iter() .flat_map(|(x, asset)| vec![(x.clone(), *asset)]) .collect(), + dev_accounts: Default::default(), } .assimilate_storage(t) .unwrap(); diff --git a/pallets/route-executor/Cargo.toml b/pallets/route-executor/Cargo.toml new file mode 100644 index 00000000000..389f19559a5 --- /dev/null +++ b/pallets/route-executor/Cargo.toml @@ -0,0 +1,69 @@ +[package] +name = "pallet-route-executor" +version = "2.8.0" +description = "A pallet to execute a route containing a sequence of trades" +authors = ["GalacticCouncil"] +edition = "2021" +license = "Apache 2.0" +repository = "https://github.com/galacticcouncil/HydraDX-node/tree/master/route-executor" + +[dependencies] +codec = { workspace = true } +scale-info = { workspace = true } +serde = { workspace = true } + +basilisk-math = { workspace = true } +basilisk-traits = { workspace = true } + +# HydraDX dependencies +hydradx-traits = { workspace = true } +hydra-dx-math = { workspace = true } +pallet-broadcast = { workspace = true } +primitives = { workspace = true } + +# ORML dependencies +orml-traits = { workspace = true } + +# Substrate dependencies +frame-benchmarking = { workspace = true, optional = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +sp-std = { workspace = true } +sp-core = { workspace = true } +sp-runtime = { workspace = true } +pallet-balances = { workspace = true } + +[dev-dependencies] +sp-io = { workspace = true } +pretty_assertions = { workspace = true } +orml-tokens = { workspace = true } +pallet-currencies = { workspace = true } +basilisk-adapters = { workspace = true } +test-utils = { workspace = true } + +[features] +default = ["std"] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "frame-support/runtime-benchmarks", +] +std = [ + "serde/std", + "codec/std", + "scale-info/std", + "sp-std/std", + "frame-support/std", + "frame-system/std", + "orml-tokens/std", + "orml-traits/std", + "basilisk-adapters/std", + "pallet-balances/std", + "pallet-broadcast/std", + "hydradx-traits/std", + "hydra-dx-math/std", + "frame-benchmarking/std", + "sp-core/std", + "sp-runtime/std", +] +try-runtime = ["frame-support/try-runtime"] diff --git a/pallets/route-executor/README.md b/pallets/route-executor/README.md new file mode 100644 index 00000000000..d732cbd27ed --- /dev/null +++ b/pallets/route-executor/README.md @@ -0,0 +1,42 @@ +# Route executor + +## Overview + +### Storing routes +This pallet is responsible for storing the best routes for asset pairs. + +The new route is validated by being executed it in a dry-run mode + +If there is no route explicitly set for an asset pair, then we use the omnipool route as default. + +When a new route is set, we compare it to the existing (or default) route. +The comparison happens by calculating sell amount_outs for the routes, but also for the inversed routes. + +The route is stored in an ordered manner, based on the oder of the ids in the asset pair. + +If the route is set successfully, then the fee is paid back. + +If the route setting fails, it emits event `RouteUpdateIsNotSuccessful` + +### Force insert route +The route can be force inserted for any asset pair by technical origin without involving any validation. + +### Providing routes +This pallet is also responsible for providing the best routes for asset pairs. + +If no on-chain route present, then omnipool route is provided as default. + +### Executing routes +This pallet is also responsible for executing a series of trades specified in the route. +The specific price calculations and execution logics are implemented by the AMM pools +configured for the pallet. + +If no route is specified for a route execution, then the on-chain route is used. +If not on-chain is present, then omnipool is used as default + +Both buy and sell trades are supported. + +There is also a `sell_all` extrinsic, which sells all the reducible `asset_in` balance of the user. + +### Weight calculation +The extrinsic weights are calculated based on the size of the route. diff --git a/pallets/route-executor/src/lib.rs b/pallets/route-executor/src/lib.rs new file mode 100644 index 00000000000..96c437ff96f --- /dev/null +++ b/pallets/route-executor/src/lib.rs @@ -0,0 +1,1052 @@ +// This file is part of pallet-route-executor. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::manual_inspect)] + +use codec::MaxEncodedLen; +use frame_support::storage::with_transaction; +use frame_support::traits::fungibles::Mutate; +use frame_support::traits::tokens::{Fortitude, Preservation}; +use frame_support::PalletId; +use frame_support::{ + ensure, + pallet_prelude::*, + traits::{fungibles::Inspect, Get}, + transactional, +}; +use hydra_dx_math::support::rational::{round_u512_to_rational, Rounding}; + +use basilisk_traits::router::{ + inverse_route, AssetPair, RefundEdCalculator, RouteProvider, RouteSpotPriceProvider, TradeExecution, +}; +pub use basilisk_traits::router::{AmmTradeWeights, AmountInAndOut, ExecutorError, PoolType, RouterT, Trade}; +use frame_system::pallet_prelude::OriginFor; +use frame_system::{ensure_signed, Origin}; +use hydradx_traits::registry::Inspect as RegistryInspect; + +use orml_traits::arithmetic::{CheckedAdd, CheckedSub}; +use pallet_broadcast::types::IncrementalIdType; +pub use pallet_broadcast::types::{ExecutionType, Fee}; +use sp_core::U512; +use sp_runtime::traits::{AccountIdConversion, CheckedDiv}; +use sp_runtime::{ArithmeticError, DispatchError, FixedPointNumber, FixedU128, Saturating, TransactionOutcome}; +use sp_std::{vec, vec::Vec}; + +#[cfg(test)] +mod tests; +pub mod weights; + +mod types; + +pub use weights::WeightInfo; + +// Re-export pallet items so that they can be accessed from the crate namespace. +pub use pallet::*; + +pub const MAX_NUMBER_OF_TRADES: u32 = 5; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use basilisk_math::ema::EmaPrice; + use basilisk_traits::oracle::{OraclePeriod, PriceOracle}; + use basilisk_traits::router::ExecutorError; + use frame_support::traits::fungibles::Mutate; + use frame_system::pallet_prelude::OriginFor; + use sp_runtime::traits::{AtLeast32BitUnsigned, CheckedDiv, Zero}; + use sp_runtime::Saturating; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config + pallet_broadcast::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// Asset id type + type AssetId: Parameter + Member + Copy + MaybeSerializeDeserialize + MaxEncodedLen + AtLeast32BitUnsigned; + + /// Balance type + type Balance: Parameter + + Member + + Copy + + PartialOrd + + MaybeSerializeDeserialize + + From + + Default + + CheckedSub + + CheckedAdd + + CheckedDiv + + Saturating + + Zero; + + /// Native Asset Id + #[pallet::constant] + type NativeAssetId: Get; + + /// Currency for checking balances and temporarily minting tokens + type Currency: Inspect + + Mutate; + + type InspectRegistry: hydradx_traits::registry::Inspect; + + /// Handlers for AMM pools to calculate and execute trades + type AMM: TradeExecution< + ::RuntimeOrigin, + Self::AccountId, + Self::AssetId, + Self::Balance, + Error = DispatchError, + >; + + ///Calculate ED for tolerating currency balance difference + type EdToRefundCalculator: RefundEdCalculator; + + ///Oracle price provider to validate if new route has oracle price data + type OraclePriceProvider: PriceOracle; + + /// Oracle's price aggregation period. + #[pallet::constant] + type OraclePeriod: Get; + + /// Pool type used in the default route + type DefaultRoutePoolType: Get>; + + /// Origin able to set route without validation + type ForceInsertOrigin: EnsureOrigin; + + /// Weight information for the extrinsics. + type WeightInfo: AmmTradeWeights>; + } + + #[pallet::event] + #[pallet::generate_deposit(pub(crate) fn deposit_event)] + pub enum Event { + ///The route with trades has been successfully executed + Executed { + asset_in: T::AssetId, + asset_out: T::AssetId, + amount_in: T::Balance, + amount_out: T::Balance, + event_id: IncrementalIdType, + }, + ///The route with trades has been successfully executed + RouteUpdated { asset_ids: Vec }, + } + + #[pallet::error] + pub enum Error { + ///The trading limit has been reached + TradingLimitReached, + ///The the max number of trades limit is reached + MaxTradesExceeded, + ///The AMM pool is not supported for executing trades + PoolNotSupported, + ///The user has not enough balance to execute the trade + InsufficientBalance, + ///The calculation of route trade amounts failed in the underlying AMM + RouteCalculationFailed, + ///The route is invalid + InvalidRoute, + ///The route update was not successful + RouteUpdateIsNotSuccessful, + ///Route contains assets that has no oracle data + RouteHasNoOracle, + ///The route execution failed in the underlying AMM + InvalidRouteExecution, + /// Trading same assets is not allowed. + NotAllowed, + } + + ///Flag to indicate when to skip ED handling + #[pallet::storage] + #[pallet::getter(fn last_trade_position)] + pub type SkipEd = StorageValue<_, types::SkipEd, OptionQuery>; + + /// Storing routes for asset pairs + #[pallet::storage] + #[pallet::getter(fn route)] + pub type Routes = StorageMap< + _, + Blake2_128Concat, + AssetPair, + BoundedVec, ConstU32>, + >; + + #[pallet::call] + impl Pallet { + /// Executes a sell with a series of trades specified in the route. + /// The price for each trade is determined by the corresponding AMM. + /// + /// - `origin`: The executor of the trade + /// - `asset_in`: The identifier of the asset to sell + /// - `asset_out`: The identifier of the asset to receive + /// - `amount_in`: The amount of `asset_in` to sell + /// - `min_amount_out`: The minimum amount of `asset_out` to receive. + /// - `route`: Series of [`Trade`] to be executed. A [`Trade`] specifies the asset pair (`asset_in`, `asset_out`) and the AMM (`pool`) in which the trade is executed. + /// If not specified, than the on-chain route is used. + /// If no on-chain is present, then omnipool route is used as default + /// + /// Emits `RouteExecuted` when successful. + #[pallet::call_index(0)] + #[pallet::weight(T::WeightInfo::sell_weight(route))] + #[transactional] + pub fn sell( + origin: OriginFor, + asset_in: T::AssetId, + asset_out: T::AssetId, + amount_in: T::Balance, + min_amount_out: T::Balance, + route: Vec>, + ) -> DispatchResult { + Self::do_sell(origin, asset_in, asset_out, amount_in, min_amount_out, route) + } + + /// Executes a buy with a series of trades specified in the route. + /// The price for each trade is determined by the corresponding AMM. + /// + /// - `origin`: The executor of the trade + /// - `asset_in`: The identifier of the asset to be swapped to buy `asset_out` + /// - `asset_out`: The identifier of the asset to buy + /// - `amount_out`: The amount of `asset_out` to buy + /// - `max_amount_in`: The max amount of `asset_in` to spend on the buy. + /// - `route`: Series of [`Trade`] to be executed. A [`Trade`] specifies the asset pair (`asset_in`, `asset_out`) and the AMM (`pool`) in which the trade is executed. + /// If not specified, than the on-chain route is used. + /// If no on-chain is present, then omnipool route is used as default + /// + /// Emits `RouteExecuted` when successful. + #[pallet::call_index(1)] + #[pallet::weight(T::WeightInfo::buy_weight(route))] + #[transactional] + pub fn buy( + origin: OriginFor, + asset_in: T::AssetId, + asset_out: T::AssetId, + amount_out: T::Balance, + max_amount_in: T::Balance, + route: Vec>, + ) -> DispatchResult { + let who = ensure_signed(origin.clone())?; + + ensure!(asset_in != asset_out, Error::::NotAllowed); + Self::ensure_route_size(route.len())?; + + let asset_pair = AssetPair::new(asset_in, asset_out); + let route = Self::get_route_or_default(route, asset_pair)?; + Self::ensure_route_arguments(&asset_pair, &route)?; + + let user_balance_of_asset_in_before_trade = + T::Currency::reducible_balance(asset_in, &who, Preservation::Expendable, Fortitude::Polite); + + let trade_amounts = Self::calculate_buy_trade_amounts(&route, amount_out)?; + + let first_trade = trade_amounts.last().ok_or(Error::::RouteCalculationFailed)?; + ensure!(first_trade.amount_in <= max_amount_in, Error::::TradingLimitReached); + + let route_length = route.len(); + + let next_event_id = pallet_broadcast::Pallet::::add_to_context(ExecutionType::Router)?; + + for (trade_index, (trade_amount, trade)) in trade_amounts.iter().rev().zip(route).enumerate() { + Self::disable_ed_handling_for_insufficient_assets(route_length, trade_index, trade); + let user_balance_of_asset_out_before_trade = + T::Currency::reducible_balance(trade.asset_out, &who, Preservation::Preserve, Fortitude::Polite); + let execution_result = T::AMM::execute_buy( + origin.clone(), + trade.pool, + trade.asset_in, + trade.asset_out, + trade_amount.amount_out, + trade_amount.amount_in, + ); + + handle_execution_error!(execution_result); + + Self::ensure_that_user_received_asset_out_at_most( + who.clone(), + trade.asset_in, + trade.asset_out, + user_balance_of_asset_out_before_trade, + trade_amount.amount_out, + )?; + } + + SkipEd::::kill(); + + Self::ensure_that_user_spent_asset_in_at_least( + who, + asset_in, + user_balance_of_asset_in_before_trade, + first_trade.amount_in, + )?; + + //TODO: we want to deprecate it once unified events are working fine + Self::deposit_event(Event::Executed { + asset_in, + asset_out, + amount_in: first_trade.amount_in, + amount_out, + event_id: next_event_id, + }); + + let _ = pallet_broadcast::Pallet::::remove_from_context(); + + Ok(()) + } + + /// Sets the on-chain route for a given asset pair. + /// + /// The new route is validated by being executed in a dry-run mode + /// + /// If there is no route explicitly set for an asset pair, then we use the omnipool route as default. + /// + /// When a new route is set, we compare it to the existing (or default) route. + /// The comparison happens by calculating sell amount_outs for the routes, but also for the inversed routes. + /// + /// The route is stored in an ordered manner, based on the oder of the ids in the asset pair. + /// + /// If the route is set successfully, then the fee is payed back. + /// + /// - `origin`: The origin of the route setter + /// - `asset_pair`: The identifier of the asset-pair for which the route is set + /// - `new_route`: Series of [`Trade`] to be executed. A [`Trade`] specifies the asset pair (`asset_in`, `asset_out`) and the AMM (`pool`) in which the trade is executed. + /// + /// Emits `RouteUpdated` when successful. + /// + /// Fails with `RouteUpdateIsNotSuccessful` error when failed to set the route + /// + #[pallet::call_index(2)] + #[pallet::weight(T::WeightInfo::set_route_weight(new_route))] + #[transactional] + pub fn set_route( + origin: OriginFor, + mut asset_pair: AssetPair, + mut new_route: Vec>, + ) -> DispatchResultWithPostInfo { + let _ = ensure_signed(origin.clone())?; + Self::ensure_route_size(new_route.len())?; + Self::ensure_route_arguments(&asset_pair, &new_route)?; + T::OraclePriceProvider::price(&new_route, T::OraclePeriod::get()).ok_or(Error::::RouteHasNoOracle)?; + + if !asset_pair.is_ordered() { + asset_pair = asset_pair.ordered_pair(); + new_route = inverse_route(new_route) + } + + let existing_route = Self::get_route(asset_pair); + + match Self::validate_route(&existing_route) { + Ok((reference_amount_in, reference_amount_in_for_inverse)) => { + let new_route_validation = Self::validate_sell(new_route.clone(), reference_amount_in); + + let inverse_new_route = inverse_route(new_route.to_vec()); + let inverse_new_route_validation = + Self::validate_sell(inverse_new_route.clone(), reference_amount_in_for_inverse); + + match (new_route_validation, inverse_new_route_validation) { + (Ok(_), Ok(_)) => (), + (Err(_), Ok(amount_out)) => { + Self::validate_sell(new_route.to_vec(), amount_out).map(|_| ())?; + } + (Ok(amount_out), Err(_)) => { + Self::validate_sell(inverse_new_route.clone(), amount_out).map(|_| ())?; + } + (Err(err), Err(_)) => return Err(err.into()), + } + + let amount_out_for_existing_route = + Self::calculate_expected_amount_out(&existing_route, reference_amount_in)?; + let amount_out_for_new_route = + Self::calculate_expected_amount_out(&new_route, reference_amount_in)?; + + let inverse_existing_route = inverse_route(existing_route.to_vec()); + let amount_out_for_existing_inversed_route = + Self::calculate_expected_amount_out(&inverse_existing_route, reference_amount_in_for_inverse)?; + let amount_out_for_new_inversed_route = + Self::calculate_expected_amount_out(&inverse_new_route, reference_amount_in_for_inverse)?; + + if amount_out_for_new_route > amount_out_for_existing_route + && amount_out_for_new_inversed_route > amount_out_for_existing_inversed_route + { + return Self::insert_route(asset_pair, new_route); + } + } + Err(_) => { + Self::validate_route(&new_route)?; + + return Self::insert_route(asset_pair, new_route); + } + } + + Err(Error::::RouteUpdateIsNotSuccessful.into()) + } + + /// Force inserts the on-chain route for a given asset pair, so there is no any validation for the route + /// + /// Can only be called by T::ForceInsertOrigin + /// + /// The route is stored in an ordered manner, based on the oder of the ids in the asset pair. + /// + /// If the route is set successfully, then the fee is payed back. + /// + /// - `origin`: The origin of the route setter + /// - `asset_pair`: The identifier of the asset-pair for which the route is set + /// - `new_route`: Series of [`Trade`] to be executed. A [`Trade`] specifies the asset pair (`asset_in`, `asset_out`) and the AMM (`pool`) in which the trade is executed. + /// + /// Emits `RouteUpdated` when successful. + /// + #[pallet::call_index(3)] + #[pallet::weight(T::WeightInfo::force_insert_route_weight())] + #[transactional] + pub fn force_insert_route( + origin: OriginFor, + mut asset_pair: AssetPair, + mut new_route: Vec>, + ) -> DispatchResultWithPostInfo { + T::ForceInsertOrigin::ensure_origin(origin)?; + + if !asset_pair.is_ordered() { + asset_pair = asset_pair.ordered_pair(); + new_route = inverse_route(new_route) + } + + Self::insert_route(asset_pair, new_route) + } + + /// Executes a sell with a series of trades specified in the route. + /// It sells all reducible user balance of `asset_in` + /// The price for each trade is determined by the corresponding AMM. + /// + /// - `origin`: The executor of the trade + /// - `asset_in`: The identifier of the asset to sell + /// - `asset_out`: The identifier of the asset to receive + /// - `min_amount_out`: The minimum amount of `asset_out` to receive. + /// - `route`: Series of [`Trade`] to be executed. A [`Trade`] specifies the asset pair (`asset_in`, `asset_out`) and the AMM (`pool`) in which the trade is executed. + /// If not specified, than the on-chain route is used. + /// If no on-chain is present, then omnipool route is used as default + /// + /// Emits `RouteExecuted` when successful. + /// + #[pallet::call_index(4)] + #[pallet::weight(T::WeightInfo::sell_weight(route))] + #[transactional] + pub fn sell_all( + origin: OriginFor, + asset_in: T::AssetId, + asset_out: T::AssetId, + min_amount_out: T::Balance, + route: Vec>, + ) -> DispatchResult { + let who = ensure_signed(origin.clone())?; + let amount_in = T::Currency::reducible_balance(asset_in, &who, Preservation::Expendable, Fortitude::Polite); + + Self::do_sell(origin, asset_in, asset_out, amount_in, min_amount_out, route) + } + } +} + +impl Pallet { + /// Pallet account address for do dry-run sell execution as validation + pub fn router_account() -> T::AccountId { + PalletId(*b"routerex").into_account_truncating() + } + + fn do_sell( + origin: T::RuntimeOrigin, + asset_in: T::AssetId, + asset_out: T::AssetId, + amount_in: T::Balance, + min_amount_out: T::Balance, + route: Vec>, + ) -> Result<(), DispatchError> { + let who = ensure_signed(origin.clone())?; + + ensure!(asset_in != asset_out, Error::::NotAllowed); + + Self::ensure_route_size(route.len())?; + + let asset_pair = AssetPair::new(asset_in, asset_out); + let route = Self::get_route_or_default(route, asset_pair)?; + Self::ensure_route_arguments(&asset_pair, &route)?; + + let user_balance_of_asset_out_before_trade = + T::Currency::reducible_balance(asset_out, &who, Preservation::Preserve, Fortitude::Polite); + + let trade_amounts = Self::calculate_sell_trade_amounts(&route, amount_in)?; + + let last_trade_amount = trade_amounts.last().ok_or(Error::::RouteCalculationFailed)?; + ensure!( + last_trade_amount.amount_out >= min_amount_out, + Error::::TradingLimitReached + ); + + let route_length = route.len(); + + let next_event_id = pallet_broadcast::Pallet::::add_to_context(ExecutionType::Router)?; + + for (trade_index, (trade_amount, trade)) in trade_amounts.iter().zip(route.clone()).enumerate() { + Self::disable_ed_handling_for_insufficient_assets(route_length, trade_index, trade); + + let user_balance_of_asset_in_before_trade = + T::Currency::reducible_balance(trade.asset_in, &who, Preservation::Expendable, Fortitude::Polite); + + let execution_result = T::AMM::execute_sell( + origin.clone(), + trade.pool, + trade.asset_in, + trade.asset_out, + trade_amount.amount_in, + trade_amount.amount_out, + ); + + handle_execution_error!(execution_result); + + Self::ensure_that_user_spent_asset_in_at_least( + who.clone(), + trade.asset_in, + user_balance_of_asset_in_before_trade, + trade_amount.amount_in, + )?; + } + + SkipEd::::kill(); + + Self::ensure_that_user_received_asset_out_at_most( + who, + asset_in, + asset_out, + user_balance_of_asset_out_before_trade, + last_trade_amount.amount_out, + )?; + + Self::deposit_event(Event::Executed { + asset_in, + asset_out, + amount_in, + amount_out: last_trade_amount.amount_out, + event_id: next_event_id, + }); + + let _ = pallet_broadcast::Pallet::::remove_from_context(); + + Ok(()) + } + + fn ensure_route_size(route_length: usize) -> Result<(), DispatchError> { + ensure!( + (route_length as u32) <= MAX_NUMBER_OF_TRADES, + Error::::MaxTradesExceeded + ); + + Ok(()) + } + + fn ensure_route_arguments( + asset_pair: &AssetPair, + route: &[Trade], + ) -> Result<(), DispatchError> { + ensure!( + asset_pair.asset_in == route.first().ok_or(Error::::InvalidRoute)?.asset_in, + Error::::InvalidRoute + ); + ensure!( + asset_pair.asset_out == route.last().ok_or(Error::::InvalidRoute)?.asset_out, + Error::::InvalidRoute + ); + + for i in 0..route.len().saturating_sub(1) { + let asset_out = route.get(i).ok_or(Error::::InvalidRoute)?.asset_out; + let next_trade_asset_in = route.get(i.saturating_add(1)).ok_or(Error::::InvalidRoute)?.asset_in; + + ensure!(asset_out == next_trade_asset_in, Error::::InvalidRoute) + } + + Ok(()) + } + + fn ensure_that_user_received_asset_out_at_most( + who: T::AccountId, + asset_in: T::AssetId, + asset_out: T::AssetId, + user_balance_of_asset_out_before_trade: T::Balance, + expected_received_amount: T::Balance, + ) -> Result<(), DispatchError> { + let user_balance_of_asset_out_after_trade = + T::Currency::reducible_balance(asset_out, &who, Preservation::Preserve, Fortitude::Polite); + + let actual_received_amount = user_balance_of_asset_out_after_trade + .checked_sub(&user_balance_of_asset_out_before_trade) + .ok_or(Error::::InvalidRouteExecution)?; + + if !T::InspectRegistry::is_sufficient(asset_in) && asset_out == T::NativeAssetId::get() { + // In case of selling all insufficient asset, ED in HDX is refund to user, so end-balance will be more with ED + // In this case we check if the user does not receive more than ED + let diff = actual_received_amount.saturating_sub(expected_received_amount); + let ed_to_refund = T::EdToRefundCalculator::calculate(); + + ensure!(diff <= ed_to_refund, Error::::InvalidRouteExecution); + } else { + ensure!( + actual_received_amount <= expected_received_amount, + Error::::InvalidRouteExecution + ); + } + + Ok(()) + } + + fn ensure_that_user_spent_asset_in_at_least( + who: T::AccountId, + asset_in: T::AssetId, + user_balance_of_asset_in_before_trade: T::Balance, + expected_spent_amount: T::Balance, + ) -> Result<(), DispatchError> { + let user_balance_of_asset_in_after_trade = + T::Currency::reducible_balance(asset_in, &who, Preservation::Preserve, Fortitude::Polite); + + let actual_spent_amount = user_balance_of_asset_in_before_trade + .checked_sub(&user_balance_of_asset_in_after_trade) + .ok_or(Error::::InvalidRouteExecution)?; + + ensure!( + actual_spent_amount >= expected_spent_amount, + Error::::InvalidRouteExecution + ); + + Ok(()) + } + + fn get_route_or_default( + route: Vec>, + asset_pair: AssetPair, + ) -> Result>, DispatchError> { + let route = if !route.is_empty() { + route + } else { + as RouteProvider>::get_route(asset_pair) + }; + Ok(route) + } + + pub fn disable_ed_handling_for_insufficient_assets( + route_length: usize, + trade_index: usize, + trade: Trade, + ) { + if route_length > 1 + && (!T::InspectRegistry::is_sufficient(trade.asset_in) + || !T::InspectRegistry::is_sufficient(trade.asset_out)) + { + //We optimize to set the state for middle trades only once at the first middle trade, then we change no state till the last trade + match trade_index { + 0 => SkipEd::::put(types::SkipEd::Lock), + trade_index if trade_index.saturating_add(1) == route_length => SkipEd::::put(types::SkipEd::Unlock), + 1 => SkipEd::::put(types::SkipEd::LockAndUnlock), + _ => (), + } + } + } + + pub fn skip_ed_lock() -> bool { + if let Ok(v) = SkipEd::::try_get() { + return matches!(v, types::SkipEd::Lock | types::SkipEd::LockAndUnlock); + } + + false + } + + pub fn skip_ed_unlock() -> bool { + if let Ok(v) = SkipEd::::try_get() { + return matches!(v, types::SkipEd::Unlock | types::SkipEd::LockAndUnlock); + } + + false + } + + fn validate_route(route: &[Trade]) -> Result<(T::Balance, T::Balance), DispatchError> { + let reference_amount_in = Self::calculate_reference_amount_in(route)?; + let route_validation = Self::validate_sell(route.to_vec(), reference_amount_in); + + let inverse_route = inverse_route(route.to_vec()); + let reference_amount_in_for_inverse_route = Self::calculate_reference_amount_in(&inverse_route)?; + let inverse_route_validation = + Self::validate_sell(inverse_route.clone(), reference_amount_in_for_inverse_route); + + match (route_validation, inverse_route_validation) { + (Ok(_), Ok(_)) => Ok((reference_amount_in, reference_amount_in_for_inverse_route)), + (Err(_), Ok(amount_out)) => Self::validate_sell(route.to_vec(), amount_out) + .map(|_| (amount_out, reference_amount_in_for_inverse_route)), + (Ok(amount_out), Err(_)) => { + Self::validate_sell(inverse_route, amount_out).map(|_| (reference_amount_in, amount_out)) + } + (Err(err), Err(_)) => Err(err), + } + } + + fn calculate_reference_amount_in(route: &[Trade]) -> Result { + let first_route = route.first().ok_or(Error::::RouteCalculationFailed)?; + let asset_b = match first_route.pool { + PoolType::Omnipool => T::NativeAssetId::get(), + PoolType::Stableswap(pool_id) => pool_id, + PoolType::XYK => first_route.asset_out, + PoolType::LBP => first_route.asset_out, + }; + + let asset_in_liquidity = T::AMM::get_liquidity_depth(first_route.pool, first_route.asset_in, asset_b); + + let liquidity = match asset_in_liquidity { + Err(ExecutorError::NotSupported) => return Err(Error::::PoolNotSupported.into()), + Err(ExecutorError::Error(dispatch_error)) => return Err(dispatch_error), + Ok(liq) => liq, + }; + + let one_percent_asset_in_liquidity = liquidity + .checked_div(&100u128.into()) + .ok_or(ArithmeticError::Overflow)?; + + Ok(one_percent_asset_in_liquidity) + } + + fn validate_sell(route: Vec>, amount_in: T::Balance) -> Result { + let asset_in = route.first().ok_or(Error::::InvalidRoute)?.asset_in; + let asset_out = route.last().ok_or(Error::::InvalidRoute)?.asset_out; + + with_transaction::(|| { + let origin: OriginFor = Origin::::Signed(Self::router_account()).into(); + let Ok(who) = ensure_signed(origin.clone()) else { + return TransactionOutcome::Rollback(Err(Error::::InvalidRoute.into())); + }; + //NOTE: This is necessary so router's account can pay ED for insufficient assets in the + //route. Value is 10K to make sure we can pay ED for really long routes. + let _ = T::Currency::mint_into( + T::NativeAssetId::get(), + &Self::router_account(), + 10_000_000_000_000_000_u128.into(), + ); + let _ = T::Currency::mint_into(asset_in, &Self::router_account(), amount_in); + + let sell_result = Self::sell(origin, asset_in, asset_out, amount_in, u128::MIN.into(), route.clone()); + let amount_out = + T::Currency::reducible_balance(asset_out, &who, Preservation::Expendable, Fortitude::Polite); + + TransactionOutcome::Rollback(sell_result.map(|_| amount_out)) + }) + } + + fn calculate_expected_amount_out( + route: &[Trade<::AssetId>], + amount_in: T::Balance, + ) -> Result { + let sell_trade_amounts = Self::calculate_sell_trade_amounts(route, amount_in)?; + let amount_out = sell_trade_amounts + .last() + .ok_or(Error::::RouteCalculationFailed)? + .amount_out; + + Ok(amount_out) + } + + fn calculate_sell_trade_amounts( + route: &[Trade], + amount_in: T::Balance, + ) -> Result>, DispatchError> { + let mut amount_in_and_outs = Vec::>::with_capacity(route.len()); + let mut amount_in = amount_in; + + for trade in route.iter() { + let result = T::AMM::calculate_sell(trade.pool, trade.asset_in, trade.asset_out, amount_in); + match result { + Err(ExecutorError::NotSupported) => return Err(Error::::PoolNotSupported.into()), + Err(ExecutorError::Error(dispatch_error)) => return Err(dispatch_error), + Ok(amount_out) => { + amount_in_and_outs.push(AmountInAndOut { amount_in, amount_out }); + amount_in = amount_out; + } + } + } + + Ok(amount_in_and_outs) + } + + fn calculate_buy_trade_amounts( + route: &[Trade], + amount_out: T::Balance, + ) -> Result>, DispatchError> { + let mut amount_in_and_outs = Vec::>::with_capacity(route.len()); + let mut amount_out = amount_out; + + for trade in route.iter().rev() { + let result = T::AMM::calculate_buy(trade.pool, trade.asset_in, trade.asset_out, amount_out); + + match result { + Err(ExecutorError::NotSupported) => return Err(Error::::PoolNotSupported.into()), + Err(ExecutorError::Error(dispatch_error)) => return Err(dispatch_error), + Ok(amount_in) => { + amount_in_and_outs.push(AmountInAndOut { amount_in, amount_out }); + amount_out = amount_in; + } + } + } + + Ok(amount_in_and_outs) + } + + fn insert_route(asset_pair: AssetPair, route: Vec>) -> DispatchResultWithPostInfo { + let route_as_bounded_vec: BoundedVec, sp_runtime::traits::ConstU32> = + route.try_into().map_err(|_| Error::::MaxTradesExceeded)?; + + Routes::::insert(asset_pair, route_as_bounded_vec); + + Self::deposit_event(Event::RouteUpdated { + asset_ids: asset_pair.to_ordered_vec(), + }); + + Ok(Pays::No.into()) + } +} + +impl RouterT, AmountInAndOut> + for Pallet +{ + fn sell( + origin: T::RuntimeOrigin, + asset_in: T::AssetId, + asset_out: T::AssetId, + amount_in: T::Balance, + min_amount_out: T::Balance, + route: Vec>, + ) -> DispatchResult { + Pallet::::sell(origin, asset_in, asset_out, amount_in, min_amount_out, route) + } + + fn sell_all( + origin: T::RuntimeOrigin, + asset_in: T::AssetId, + asset_out: T::AssetId, + min_amount_out: T::Balance, + route: Vec>, + ) -> DispatchResult { + Pallet::::sell_all(origin, asset_in, asset_out, min_amount_out, route) + } + + fn buy( + origin: T::RuntimeOrigin, + asset_in: T::AssetId, + asset_out: T::AssetId, + amount_out: T::Balance, + max_amount_in: T::Balance, + route: Vec>, + ) -> DispatchResult { + Pallet::::buy(origin, asset_in, asset_out, amount_out, max_amount_in, route) + } + + fn calculate_sell_trade_amounts( + route: &[Trade], + amount_in: T::Balance, + ) -> Result>, DispatchError> { + Pallet::::calculate_sell_trade_amounts(route, amount_in) + } + + fn calculate_buy_trade_amounts( + route: &[Trade], + amount_out: T::Balance, + ) -> Result>, DispatchError> { + Pallet::::calculate_buy_trade_amounts(route, amount_out) + } + + fn set_route( + origin: T::RuntimeOrigin, + asset_pair: AssetPair, + route: Vec>, + ) -> DispatchResultWithPostInfo { + Pallet::::set_route(origin, asset_pair, route) + } + + fn force_insert_route( + origin: T::RuntimeOrigin, + asset_pair: AssetPair, + route: Vec>, + ) -> DispatchResultWithPostInfo { + Pallet::::force_insert_route(origin, asset_pair, route) + } +} + +pub struct DummyRouter(PhantomData); +impl RouterT, AmountInAndOut> + for DummyRouter +{ + fn sell( + _origin: T::RuntimeOrigin, + _asset_in: T::AssetId, + _asset_out: T::AssetId, + _amount_in: T::Balance, + _min_amount_out: T::Balance, + _route: Vec>, + ) -> DispatchResult { + Ok(()) + } + + fn sell_all( + _origin: T::RuntimeOrigin, + _asset_in: T::AssetId, + _asset_out: T::AssetId, + _min_amount_out: T::Balance, + _route: Vec>, + ) -> sp_runtime::DispatchResult { + Ok(()) + } + + fn buy( + _origin: T::RuntimeOrigin, + _asset_in: T::AssetId, + _asset_out: T::AssetId, + _amount_out: T::Balance, + _max_amount_in: T::Balance, + _route: Vec>, + ) -> DispatchResult { + Ok(()) + } + + fn calculate_sell_trade_amounts( + _route: &[Trade], + amount_in: T::Balance, + ) -> Result>, DispatchError> { + Ok(vec![AmountInAndOut:: { + amount_in, + amount_out: amount_in, + }]) + } + + fn calculate_buy_trade_amounts( + _route: &[Trade], + amount_out: T::Balance, + ) -> Result>, DispatchError> { + Ok(vec![AmountInAndOut:: { + amount_in: amount_out, + amount_out, + }]) + } + + fn set_route( + _origin: T::RuntimeOrigin, + _asset_pair: AssetPair, + _route: Vec>, + ) -> DispatchResultWithPostInfo { + Ok(Pays::Yes.into()) + } + + fn force_insert_route( + _origin: T::RuntimeOrigin, + _asset_pair: AssetPair, + _route: Vec>, + ) -> DispatchResultWithPostInfo { + Ok(Pays::Yes.into()) + } +} + +impl RouteSpotPriceProvider for DummyRouter { + fn spot_price_with_fee(_route: &[Trade]) -> Option { + Some(FixedU128::from_u32(2)) + } +} + +impl RouteProvider for DummyRouter { + fn get_route(asset_pair: AssetPair) -> Vec> { + vec![Trade { + pool: T::DefaultRoutePoolType::get(), + asset_in: asset_pair.asset_in, + asset_out: asset_pair.asset_out, + }] + } +} + +#[macro_export] +macro_rules! handle_execution_error { + ($execution_result:expr) => {{ + if let Err(error) = $execution_result { + return match error { + ExecutorError::NotSupported => Err(Error::::PoolNotSupported.into()), + ExecutorError::Error(dispatch_error) => Err(dispatch_error), + }; + } + }}; +} + +impl RouteProvider for Pallet { + fn get_route(asset_pair: AssetPair) -> Vec> { + let onchain_route = Routes::::get(asset_pair.ordered_pair()); + + let default_route = vec![Trade { + pool: T::DefaultRoutePoolType::get(), + asset_in: asset_pair.asset_in, + asset_out: asset_pair.asset_out, + }]; + + match onchain_route { + Some(route) => { + if asset_pair.is_ordered() { + route.to_vec() + } else { + inverse_route(route.to_vec()) + } + } + None => default_route, + } + } +} + +impl RouteSpotPriceProvider for Pallet { + fn spot_price_with_fee(route: &[Trade]) -> Option { + if route.is_empty() { + return None; + } + + let mut nominator = U512::from(1u128); + let mut denominator = U512::from(1u128); + + // We aggregate the prices after every 4 hops to prevent overflow of U512 + for chunk_with_4_hops in route.chunks(4) { + let mut prices: Vec = Vec::with_capacity(chunk_with_4_hops.len()); + for trade in chunk_with_4_hops { + let spot_price_result = + T::AMM::calculate_spot_price_with_fee(trade.pool, trade.asset_in, trade.asset_out); + match spot_price_result { + Ok(spot_price) => prices.push(spot_price), + Err(_) => return None, + } + } + + // Calculate the nominator and denominator for the current chunk + let chunk_nominator = prices.iter().try_fold(U512::from(1u128), |acc, price| { + acc.checked_mul(U512::from(price.into_inner())) + })?; + + let chunk_denominator = prices.iter().try_fold(U512::from(1u128), |acc, _price| { + acc.checked_mul(U512::from(FixedU128::DIV)) + })?; + + // Combine the chunk results with the final results + nominator = nominator.checked_mul(chunk_nominator)?; + denominator = denominator.checked_mul(chunk_denominator)?; + } + + let rat_as_u128 = round_u512_to_rational((nominator, denominator), Rounding::Nearest); + + FixedU128::checked_from_rational(rat_as_u128.0, rat_as_u128.1) + } +} diff --git a/pallets/route-executor/src/tests/buy.rs b/pallets/route-executor/src/tests/buy.rs new file mode 100644 index 00000000000..f0c5e23aaa4 --- /dev/null +++ b/pallets/route-executor/src/tests/buy.rs @@ -0,0 +1,528 @@ +// This file is part of HydraDX. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::tests::mock::*; +use crate::{Error, Event, Trade}; +use basilisk_traits::router::AssetPair; +use basilisk_traits::router::PoolType; +use frame_support::{assert_noop, assert_ok}; +use pretty_assertions::assert_eq; +use sp_runtime::DispatchError; + +#[test] +fn buy_should_work_when_route_has_single_trade() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let amount_to_buy = 10; + let limit = 5; + + let trades = vec![HDX_AUSD_TRADE_IN_XYK]; + + //Act + assert_ok!(Router::buy( + RuntimeOrigin::signed(ALICE), + HDX, + AUSD, + amount_to_buy, + limit, + trades + )); + + //Assert + assert_executed_buy_trades(vec![(PoolType::XYK, amount_to_buy, HDX, AUSD)]); + expect_events(vec![Event::Executed { + asset_in: HDX, + asset_out: AUSD, + amount_in: XYK_BUY_CALCULATION_RESULT, + amount_out: amount_to_buy, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn buy_should_work_with_omnipool_when_no_route_or_onchain_route_exist() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let amount_to_buy = 10; + let limit = 5; + + //Act + assert_ok!(Router::buy( + RuntimeOrigin::signed(ALICE), + HDX, + DOT, + amount_to_buy, + limit, + vec![] + )); + + //Assert + assert_executed_buy_trades(vec![(PoolType::Omnipool, amount_to_buy, HDX, DOT)]); + expect_events(vec![Event::Executed { + asset_in: HDX, + asset_out: DOT, + amount_in: OMNIPOOL_BUY_CALCULATION_RESULT, + amount_out: amount_to_buy, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn buy_should_work_when_onchain_route_present_in_reverse_order() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, KSM, 1000)]) + .build() + .execute_with(|| { + //Arrange + let amount_to_buy = 10; + let limit = 5; + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: MOVR, + }; + let trade2 = Trade { + pool: PoolType::Stableswap(AUSD), + asset_in: MOVR, + asset_out: AUSD, + }; + let trade3 = Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: KSM, + }; + let trades = vec![trade1, trade2, trade3]; + + assert_ok!(Router::set_route( + RuntimeOrigin::signed(ALICE), + AssetPair::new(HDX, KSM), + trades, + )); + + //Act + assert_ok!(Router::buy( + RuntimeOrigin::signed(ALICE), + KSM, + HDX, + amount_to_buy, + limit, + vec![] + )); + + //Assert + assert_executed_buy_trades(vec![ + (PoolType::XYK, STABLESWAP_BUY_CALCULATION_RESULT, KSM, AUSD), + (PoolType::Stableswap(AUSD), XYK_BUY_CALCULATION_RESULT, AUSD, MOVR), + (PoolType::XYK, amount_to_buy, MOVR, HDX), + ]); + + expect_events(vec![Event::Executed { + asset_in: KSM, + asset_out: HDX, + amount_in: XYK_BUY_CALCULATION_RESULT, + amount_out: amount_to_buy, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn buy_should_work_when_route_has_single_trade_without_native_balance() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, AUSD, 1000)]) + .build() + .execute_with(|| { + //Arrange + let amount_to_buy = 10; + let limit = 5; + + let trades = vec![Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: KSM, + }]; + + //Act + assert_ok!(Router::buy( + RuntimeOrigin::signed(ALICE), + AUSD, + KSM, + amount_to_buy, + limit, + trades + )); + + //Assert + assert_executed_buy_trades(vec![(PoolType::XYK, amount_to_buy, AUSD, KSM)]); + }); +} + +#[test] +fn buy_should_fail_when_max_limit_for_trade_reached() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, RMRK, 1000)]) + .build() + .execute_with(|| { + //Arrange + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }; + let trade2 = Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: MOVR, + }; + let trade3 = Trade { + pool: PoolType::XYK, + asset_in: MOVR, + asset_out: KSM, + }; + let trade4 = Trade { + pool: PoolType::XYK, + asset_in: KSM, + asset_out: RMRK, + }; + let trade5 = Trade { + pool: PoolType::XYK, + asset_in: RMRK, + asset_out: SDN, + }; + let trade6 = Trade { + pool: PoolType::XYK, + asset_in: SDN, + asset_out: STABLE_SHARE_ASSET, + }; + let trades = vec![trade1, trade2, trade3, trade4, trade5, trade6]; + + //Act and Assert + assert_noop!( + Router::buy(RuntimeOrigin::signed(ALICE), HDX, RMRK, 10, 5, trades), + Error::::MaxTradesExceeded + ); + }); +} + +#[test] +fn buy_should_fail_when_route_has_single_trade_producing_calculation_error() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, AUSD, INVALID_CALCULATION_AMOUNT)]) + .build() + .execute_with(|| { + //Arrange + let limit = 5; + + let trades = vec![HDX_AUSD_TRADE_IN_XYK]; + + //Act and Assert + assert_noop!( + Router::buy( + RuntimeOrigin::signed(ALICE), + HDX, + AUSD, + INVALID_CALCULATION_AMOUNT, + limit, + trades + ), + DispatchError::Other("Some error happened") + ); + }); +} + +#[test] +fn buy_should_when_route_has_multiple_trades_with_same_pool_type() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, KSM, 1000)]) + .build() + .execute_with(|| { + //Arrange + let amount_to_buy = 10; + let limit = 5; + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }; + let trade2 = Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: MOVR, + }; + let trade3 = Trade { + pool: PoolType::XYK, + asset_in: MOVR, + asset_out: KSM, + }; + let trades = vec![trade1, trade2, trade3]; + + //Act + assert_ok!(Router::buy( + RuntimeOrigin::signed(ALICE), + HDX, + KSM, + amount_to_buy, + limit, + trades + )); + + //Assert + assert_executed_buy_trades(vec![ + (PoolType::XYK, XYK_BUY_CALCULATION_RESULT, HDX, AUSD), + (PoolType::XYK, XYK_BUY_CALCULATION_RESULT, AUSD, MOVR), + (PoolType::XYK, amount_to_buy, MOVR, KSM), + ]); + + expect_events(vec![Event::Executed { + asset_in: HDX, + asset_out: KSM, + amount_in: XYK_BUY_CALCULATION_RESULT, + amount_out: amount_to_buy, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn buy_should_work_when_route_has_multiple_trades_with_different_pool_type() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, KSM, 1000)]) + .build() + .execute_with(|| { + //Arrange + let amount_to_buy = 10; + let limit = 5; + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: MOVR, + }; + let trade2 = Trade { + pool: PoolType::Stableswap(AUSD), + asset_in: MOVR, + asset_out: AUSD, + }; + let trade3 = Trade { + pool: PoolType::Omnipool, + asset_in: AUSD, + asset_out: KSM, + }; + let trades = vec![trade1, trade2, trade3]; + + //Act + assert_ok!(Router::buy( + RuntimeOrigin::signed(ALICE), + HDX, + KSM, + amount_to_buy, + limit, + trades + )); + + //Assert + assert_executed_buy_trades(vec![ + (PoolType::XYK, STABLESWAP_BUY_CALCULATION_RESULT, HDX, MOVR), + (PoolType::Stableswap(AUSD), OMNIPOOL_BUY_CALCULATION_RESULT, MOVR, AUSD), + (PoolType::Omnipool, amount_to_buy, AUSD, KSM), + ]); + + expect_events(vec![Event::Executed { + asset_in: HDX, + asset_out: KSM, + amount_in: XYK_BUY_CALCULATION_RESULT, + amount_out: amount_to_buy, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn buy_should_work_with_onchain_route_when_no_route_specified() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, KSM, 1000)]) + .build() + .execute_with(|| { + //Arrange + let amount_to_buy = 10; + let limit = 5; + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: MOVR, + }; + let trade2 = Trade { + pool: PoolType::Stableswap(AUSD), + asset_in: MOVR, + asset_out: AUSD, + }; + let trade3 = Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: KSM, + }; + let trades = vec![trade1, trade2, trade3]; + + assert_ok!(Router::set_route( + RuntimeOrigin::signed(ALICE), + AssetPair::new(HDX, KSM), + trades, + )); + + //Act + assert_ok!(Router::buy( + RuntimeOrigin::signed(ALICE), + HDX, + KSM, + amount_to_buy, + limit, + vec![] + )); + + //Assert + assert_executed_buy_trades(vec![ + (PoolType::XYK, STABLESWAP_BUY_CALCULATION_RESULT, HDX, MOVR), + (PoolType::Stableswap(AUSD), XYK_BUY_CALCULATION_RESULT, MOVR, AUSD), + (PoolType::XYK, amount_to_buy, AUSD, KSM), + ]); + + expect_events(vec![Event::Executed { + asset_in: HDX, + asset_out: KSM, + amount_in: XYK_BUY_CALCULATION_RESULT, + amount_out: amount_to_buy, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn buy_should_work_when_first_trade_is_not_supported_in_the_first_pool() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, KSM, 1000)]) + .build() + .execute_with(|| { + //Arrange + let amount_to_buy = 10; + let limit = 5; + let trade1 = Trade { + pool: PoolType::Stableswap(AUSD), + asset_in: HDX, + asset_out: AUSD, + }; + let trade2 = Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: KSM, + }; + let trades = vec![trade1, trade2]; + + //Act + assert_ok!(Router::buy( + RuntimeOrigin::signed(ALICE), + HDX, + KSM, + amount_to_buy, + limit, + trades + )); + + //Assert + assert_executed_buy_trades(vec![ + (PoolType::Stableswap(AUSD), XYK_BUY_CALCULATION_RESULT, HDX, AUSD), + (PoolType::XYK, amount_to_buy, AUSD, KSM), + ]); + }); +} + +#[test] +fn buy_should_fail_when_called_with_non_signed_origin() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, AUSD, 1000)]) + .build() + .execute_with(|| { + //Arrange + let amount_to_buy = 10; + let limit = 5; + + let trades = vec![HDX_AUSD_TRADE_IN_XYK]; + + //Act and Assert + assert_noop!( + Router::buy(RuntimeOrigin::none(), HDX, AUSD, amount_to_buy, limit, trades), + sp_runtime::DispatchError::BadOrigin + ); + }); +} + +#[test] +fn buy_should_fail_when_max_limit_to_spend_is_reached() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, AUSD, 1000)]) + .build() + .execute_with(|| { + //Arrange + let amount_to_buy = 10; + let limit = XYK_BUY_CALCULATION_RESULT - 1; + + let trades = vec![HDX_AUSD_TRADE_IN_XYK]; + + //Act and Assert + assert_noop!( + Router::buy(RuntimeOrigin::signed(ALICE), HDX, AUSD, amount_to_buy, limit, trades), + Error::::TradingLimitReached + ); + }); +} + +#[test] +fn buy_should_fail_when_assets_dont_correspond_to_route() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, AUSD, 1000)]) + .build() + .execute_with(|| { + //Arrange + let amount_to_buy = 10; + let limit = 5; + + let trades = vec![ + Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: HDX, + }, + Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: MOVR, + }, + ]; + + //Act + assert_noop!( + Router::buy(RuntimeOrigin::signed(ALICE), MOVR, AUSD, amount_to_buy, limit, trades), + Error::::InvalidRoute + ); + }); +} diff --git a/pallets/route-executor/src/tests/force_insert_route.rs b/pallets/route-executor/src/tests/force_insert_route.rs new file mode 100644 index 00000000000..ffd033f9926 --- /dev/null +++ b/pallets/route-executor/src/tests/force_insert_route.rs @@ -0,0 +1,110 @@ +// This file is part of HydraDX. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::tests::mock::*; +use crate::{Error, Trade}; +use basilisk_traits::router::{AssetPair, PoolType}; +use frame_support::pallet_prelude::*; +use frame_support::{assert_noop, assert_ok}; +use pretty_assertions::assert_eq; +use sp_runtime::DispatchError::BadOrigin; + +#[test] +fn force_insert_should_not_work_when_called_with_non_technical_origin() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, AUSD); + let route = vec![Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }]; + + //Act + assert_noop!( + Router::force_insert_route(RuntimeOrigin::signed(ALICE), asset_pair, route), + BadOrigin + ); + }); +} + +#[test] +fn force_insert_should_work_when_called_with_technical_origin() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, AUSD); + let route = vec![Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }]; + + //Act + assert_ok!( + Router::force_insert_route(RuntimeOrigin::root(), asset_pair, route), + Pays::No.into() + ); + }); +} + +#[test] +fn force_insert_should_fail_when_called_with_too_big_route() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, AUSD); + let route = vec![ + Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }, + Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }, + Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }, + Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }, + Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }, + Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }, + ]; + + //Act + assert_noop!( + Router::force_insert_route(RuntimeOrigin::root(), asset_pair, route), + Error::::MaxTradesExceeded + ); + }); +} + +//TODO: add test that it can add insuffucient asset diff --git a/pallets/route-executor/src/tests/mock.rs b/pallets/route-executor/src/tests/mock.rs new file mode 100644 index 00000000000..f10290f2655 --- /dev/null +++ b/pallets/route-executor/src/tests/mock.rs @@ -0,0 +1,563 @@ +// This file is part of HydraDX. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate as router; +use crate::{Config, Trade}; +use basilisk_math::ratio::Ratio; +use basilisk_traits::router::{ExecutorError, PoolType, RefundEdCalculator, TradeExecution}; +use frame_support::{ + parameter_types, + traits::{Everything, Nothing}, +}; +use frame_system::EnsureRoot; +use frame_system::{ensure_signed, pallet_prelude::OriginFor}; +use orml_traits::parameter_type_with_key; +use pallet_currencies::{fungibles::FungibleCurrencies, BasicCurrencyAdapter, MockBoundErc20, MockErc20Currency}; +use pretty_assertions::assert_eq; +use sp_core::H256; +use sp_runtime::FixedU128; +use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, + BuildStorage, DispatchError, +}; +use std::cell::RefCell; +use std::ops::Deref; + +type Block = frame_system::mocking::MockBlock; + +pub type AssetId = u32; +pub type Balance = u128; + +frame_support::construct_runtime!( + pub enum Test + { + System: frame_system, + Router: router, + Tokens: orml_tokens, + Balances: pallet_balances, + Currencies: pallet_currencies, + Broadcast: pallet_broadcast, + } +); + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 63; +} + +impl frame_system::Config for Test { + type BaseCallFilter = Everything; + type BlockWeights = (); + type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; + type Nonce = u64; + type Block = Block; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; + type SingleBlockMigrations = (); + type MultiBlockMigrator = (); + type PreInherents = (); + type PostInherents = (); + type PostTransactions = (); + type ExtensionsWeightInfo = (); +} + +pub type Amount = i128; + +parameter_type_with_key! { + pub ExistentialDeposits: |_currency_id: AssetId| -> Balance { + 1 + }; +} + +impl orml_tokens::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type Amount = Amount; + type CurrencyId = AssetId; + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; + type MaxLocks = (); + type DustRemovalWhitelist = Nothing; + type ReserveIdentifier = (); + type MaxReserves = (); + type CurrencyHooks = (); +} + +parameter_types! { + pub const ExistentialDeposit: u128 = 1; + pub const MaxReserves: u32 = 50; +} + +impl pallet_balances::Config for Test { + type MaxLocks = (); + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = frame_system::Pallet; + type WeightInfo = (); + type MaxReserves = (); + type ReserveIdentifier = (); + type FreezeIdentifier = (); + type MaxFreezes = (); + type RuntimeHoldReason = (); + type RuntimeFreezeReason = (); + type DoneSlashHandler = (); +} + +impl pallet_currencies::Config for Test { + type RuntimeEvent = RuntimeEvent; + type MultiCurrency = Tokens; + type NativeCurrency = BasicCurrencyAdapter; + type Erc20Currency = MockErc20Currency; + type BoundErc20 = MockBoundErc20; + type GetNativeCurrencyId = NativeCurrencyId; + type WeightInfo = (); + type ReserveAccount = (); +} + +impl pallet_broadcast::Config for Test { + type RuntimeEvent = RuntimeEvent; +} + +type Pools = (XYK, StableSwap, OmniPool, LBP); + +parameter_types! { + pub NativeCurrencyId: AssetId = HDX; + pub DefaultRoutePoolType: PoolType = PoolType::Omnipool; + pub const RouteValidationOraclePeriod: OraclePeriod = OraclePeriod::TenMinutes; + +} + +impl Config for Test { + type RuntimeEvent = RuntimeEvent; + type AssetId = AssetId; + type Balance = Balance; + type NativeAssetId = NativeCurrencyId; + type Currency = FungibleCurrencies; + type InspectRegistry = MockedAssetRegistry; + type AMM = Pools; + type EdToRefundCalculator = MockedEdCalculator; + type OraclePriceProvider = PriceProviderMock; + type OraclePeriod = RouteValidationOraclePeriod; + type DefaultRoutePoolType = DefaultRoutePoolType; + type ForceInsertOrigin = EnsureRoot; + type WeightInfo = (); +} + +pub struct MockedEdCalculator; + +impl RefundEdCalculator for MockedEdCalculator { + fn calculate() -> Balance { + 1_000_000_000_000 + } +} + +pub struct PriceProviderMock {} + +impl PriceOracle for PriceProviderMock { + type Price = Ratio; + + fn price(route: &[Trade], _: OraclePeriod) -> Option { + let has_insufficient_asset = route.iter().any(|t| t.asset_in > 2000 || t.asset_out > 2000); + if has_insufficient_asset { + return None; + } + Some(Ratio::new(88, 100)) + } +} + +use basilisk_traits::oracle::{OraclePeriod, PriceOracle}; +use hydradx_traits::AssetKind; +pub struct MockedAssetRegistry; + +impl hydradx_traits::registry::Inspect for MockedAssetRegistry { + type AssetId = AssetId; + type Location = (); + + fn is_sufficient(id: Self::AssetId) -> bool { + id <= 2000 + } + + fn exists(_id: Self::AssetId) -> bool { + unimplemented!() + } + + fn decimals(_id: Self::AssetId) -> Option { + unimplemented!() + } + + fn asset_type(_id: Self::AssetId) -> Option { + unimplemented!() + } + + fn is_banned(_id: Self::AssetId) -> bool { + unimplemented!() + } + + fn asset_name(_id: Self::AssetId) -> Option> { + unimplemented!() + } + + fn asset_symbol(_id: Self::AssetId) -> Option> { + unimplemented!() + } + + fn existential_deposit(_id: Self::AssetId) -> Option { + unimplemented!() + } +} + +pub type AccountId = u64; + +pub const ALICE: AccountId = 1; +pub const ASSET_PAIR_ACCOUNT: AccountId = 2; + +pub const HDX: AssetId = 0; +pub const AUSD: AssetId = 1001; +pub const MOVR: AssetId = 1002; +pub const KSM: AssetId = 1003; +pub const RMRK: AssetId = 1004; +pub const SDN: AssetId = 1005; +pub const STABLE_SHARE_ASSET: AssetId = 1006; +pub const DOT: AssetId = 1007; +pub const INSUFFICIENT_ASSET: AssetId = 50000001; + +pub const ALICE_INITIAL_NATIVE_BALANCE: u128 = 1000; + +pub const XYK_SELL_CALCULATION_RESULT: Balance = 13; +pub const LBP_SELL_CALCULATION_RESULT: Balance = 12; +pub const OMNIPOOL_SELL_CALCULATION_RESULT: Balance = 10; +pub const STABLESWAP_SELL_CALCULATION_RESULT: Balance = 4; + +pub const LBP_BUY_CALCULATION_RESULT: Balance = 8; +pub const OMNIPOOL_BUY_CALCULATION_RESULT: Balance = 5; +pub const STABLESWAP_BUY_CALCULATION_RESULT: Balance = 3; +pub const XYK_BUY_CALCULATION_RESULT: Balance = 1; + +pub const INVALID_CALCULATION_AMOUNT: Balance = 999; + +pub fn default_omnipool_route() -> Vec> { + vec![Trade { + pool: PoolType::Omnipool, + asset_in: HDX, + asset_out: AUSD, + }] +} + +pub const HDX_AUSD_TRADE_IN_XYK: Trade = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, +}; + +pub struct ExtBuilder { + endowed_accounts: Vec<(AccountId, AssetId, Balance)>, +} + +// Returns default values for genesis config +impl Default for ExtBuilder { + fn default() -> Self { + Self { + endowed_accounts: vec![(ALICE, HDX, 1000u128)], + } + } +} + +impl ExtBuilder { + pub fn with_endowed_accounts(mut self, accounts: Vec<(AccountId, AssetId, Balance)>) -> Self { + self.endowed_accounts = accounts; + self + } + + pub fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + + pallet_balances::GenesisConfig:: { + balances: vec![ + (ALICE, ALICE_INITIAL_NATIVE_BALANCE), + (ASSET_PAIR_ACCOUNT, ALICE_INITIAL_NATIVE_BALANCE), + ], + dev_accounts: Default::default(), + } + .assimilate_storage(&mut t) + .unwrap(); + + let mut initial_accounts = vec![ + (ASSET_PAIR_ACCOUNT, STABLE_SHARE_ASSET, 1000u128), + (ASSET_PAIR_ACCOUNT, AUSD, 1000u128), + (ASSET_PAIR_ACCOUNT, INSUFFICIENT_ASSET, 1000u128), + (ASSET_PAIR_ACCOUNT, MOVR, 1000u128), + (ASSET_PAIR_ACCOUNT, KSM, 1000u128), + (ASSET_PAIR_ACCOUNT, RMRK, 1000u128), + (ASSET_PAIR_ACCOUNT, SDN, 1000u128), + (ASSET_PAIR_ACCOUNT, DOT, 1000u128), + ]; + + initial_accounts.extend(self.endowed_accounts); + + orml_tokens::GenesisConfig:: { + balances: initial_accounts, + } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext + } +} + +type ExecutedTradeInfo = (PoolType, Balance, AssetId, AssetId); +thread_local! { + pub static EXECUTED_SELLS: RefCell> = RefCell::new(Vec::default()); + pub static EXECUTED_BUYS: RefCell> = RefCell::new(Vec::default()); +} + +type OriginForRuntime = OriginFor; + +macro_rules! impl_fake_executor { + ($pool_struct:ident, $pool_type: pat, $sell_calculation_result: expr, $buy_calculation_result: expr) => { + impl TradeExecution for $pool_struct { + type Error = DispatchError; + + fn calculate_sell( + pool_type: PoolType, + _asset_in: AssetId, + _asset_out: AssetId, + amount_in: Balance, + ) -> Result> { + if !matches!(pool_type, $pool_type) { + return Err(ExecutorError::NotSupported); + } + + if amount_in == INVALID_CALCULATION_AMOUNT { + return Err(ExecutorError::Error(DispatchError::Other("Some error happened"))); + } + + Ok($sell_calculation_result) + } + + fn calculate_buy( + pool_type: PoolType, + _asset_in: AssetId, + _asset_out: AssetId, + amount_out: Balance, + ) -> Result> { + if !matches!(pool_type, $pool_type) { + return Err(ExecutorError::NotSupported); + } + + if amount_out == INVALID_CALCULATION_AMOUNT { + return Err(ExecutorError::Error(DispatchError::Other("Some error happened"))); + } + + Ok($buy_calculation_result) + } + + fn execute_sell( + who: OriginForRuntime, + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_in: Balance, + _min_limit: Balance, + ) -> Result<(), ExecutorError> { + let who = ensure_signed(who).map_err(|_| ExecutorError::Error(DispatchError::Other("Wrong origin")))?; + if !matches!(pool_type, $pool_type) { + return Err(ExecutorError::NotSupported); + } + + EXECUTED_SELLS.with(|v| { + let mut m = v.borrow_mut(); + m.push((pool_type, amount_in, asset_in, asset_out)); + }); + + let amount_out = $sell_calculation_result; + + Currencies::transfer( + RuntimeOrigin::signed(ASSET_PAIR_ACCOUNT), + who, + asset_out, + amount_out, + ) + .map_err(|e| ExecutorError::Error(e))?; + Currencies::transfer( + RuntimeOrigin::signed(who), + ASSET_PAIR_ACCOUNT, + asset_in, + amount_in, + ) + .map_err(|e| ExecutorError::Error(e))?; + + Ok(()) + } + + fn execute_buy( + who: OriginForRuntime, + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_out: Balance, + _max_limit: Balance, + ) -> Result<(), ExecutorError> { + let who = ensure_signed(who).map_err(|_| ExecutorError::Error(DispatchError::Other("Wrong origin")))?; + + if !matches!(pool_type, $pool_type) { + return Err(ExecutorError::NotSupported); + } + EXECUTED_BUYS.with(|v| { + let mut m = v.borrow_mut(); + m.push((pool_type, amount_out, asset_in, asset_out)); + }); + + let amount_in = $buy_calculation_result; + + Currencies::transfer( + RuntimeOrigin::signed(ASSET_PAIR_ACCOUNT), + who, + asset_out, + amount_out, + ) + .map_err(|e| ExecutorError::Error(e))?; + Currencies::transfer( + RuntimeOrigin::signed(who), + ASSET_PAIR_ACCOUNT, + asset_in, + amount_in, + ) + .map_err(|e| ExecutorError::Error(e))?; + + Ok(()) + } + + fn get_liquidity_depth( + _pool_type: PoolType, + _asset_a: AssetId, + _asset_b: AssetId, + ) -> Result> { + Ok(100) + } + + fn calculate_spot_price_with_fee( + _pool_type: PoolType, + _asset_a: AssetId, + _asset_b: AssetId, + ) -> Result> { + Ok(FixedU128::from_rational(1, 10)) + } + } + }; +} + +#[allow(clippy::upper_case_acronyms)] +pub struct XYK; +pub struct StableSwap; +pub struct OmniPool; +#[allow(clippy::upper_case_acronyms)] +pub struct LBP; + +impl_fake_executor!( + XYK, + PoolType::XYK, + XYK_SELL_CALCULATION_RESULT, + XYK_BUY_CALCULATION_RESULT +); +impl_fake_executor!( + StableSwap, + PoolType::Stableswap(_), + STABLESWAP_SELL_CALCULATION_RESULT, + STABLESWAP_BUY_CALCULATION_RESULT +); +impl_fake_executor!( + OmniPool, + PoolType::Omnipool, + OMNIPOOL_SELL_CALCULATION_RESULT, + OMNIPOOL_BUY_CALCULATION_RESULT +); + +impl_fake_executor!( + LBP, + PoolType::LBP, + LBP_SELL_CALCULATION_RESULT, + LBP_BUY_CALCULATION_RESULT +); + +pub fn assert_executed_sell_trades(expected_trades: Vec<(PoolType, Balance, AssetId, AssetId)>) { + EXECUTED_SELLS.with(|v| { + let trades = v.borrow().deref().clone(); + assert_eq!(trades, expected_trades); + }); +} + +pub fn assert_last_executed_sell_trades( + number_of_trades: usize, + expected_trades: Vec<(PoolType, Balance, AssetId, AssetId)>, +) { + EXECUTED_SELLS.with(|v| { + let trades = v.borrow().deref().clone(); + let last_trades = trades.as_slice()[trades.len() - number_of_trades..].to_vec(); + assert_eq!(last_trades, expected_trades); + }); +} + +pub fn assert_executed_buy_trades(expected_trades: Vec<(PoolType, Balance, AssetId, AssetId)>) { + EXECUTED_BUYS.with(|v| { + let trades = v.borrow().deref().clone(); + assert_eq!(trades, expected_trades); + }); +} + +pub fn expect_events(e: Vec) { + test_utils::expect_events::(e); +} + +pub fn expect_no_route_executed_event() { + let last_events = test_utils::last_events::(20); + + let mut events = vec![]; + + for event in &last_events { + let e = event.clone(); + if matches!(e, RuntimeEvent::Router(crate::Event::::Executed { .. })) { + events.push(e); + } + } + + pretty_assertions::assert_eq!( + events.len(), + 0, + "No RouteUpdated event expected, but there is such event emitted" + ); +} diff --git a/pallets/route-executor/src/tests/mod.rs b/pallets/route-executor/src/tests/mod.rs new file mode 100644 index 00000000000..735e9dabe6b --- /dev/null +++ b/pallets/route-executor/src/tests/mod.rs @@ -0,0 +1,7 @@ +pub mod buy; +pub mod force_insert_route; +pub mod mock; +pub mod sell; +pub mod sell_all; +pub mod set_route; +pub mod spot_price; diff --git a/pallets/route-executor/src/tests/sell.rs b/pallets/route-executor/src/tests/sell.rs new file mode 100644 index 00000000000..e6a43dbf712 --- /dev/null +++ b/pallets/route-executor/src/tests/sell.rs @@ -0,0 +1,560 @@ +// This file is part of HydraDX. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::tests::mock::*; +use crate::{Error, Event, Trade}; +use basilisk_traits::router::AssetPair; +use basilisk_traits::router::PoolType; +use frame_support::{assert_noop, assert_ok}; +use pretty_assertions::assert_eq; +use sp_runtime::DispatchError::BadOrigin; +use sp_runtime::{DispatchError, TokenError}; + +#[test] +fn sell_should_work_when_route_has_single_trade() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let amount_to_sell = 10; + let limit = 5; + + let trades = vec![HDX_AUSD_TRADE_IN_XYK]; + + //Act + assert_ok!(Router::sell( + RuntimeOrigin::signed(ALICE), + HDX, + AUSD, + amount_to_sell, + limit, + trades + )); + + //Assert + assert_executed_sell_trades(vec![(PoolType::XYK, amount_to_sell, HDX, AUSD)]); + expect_events(vec![Event::Executed { + asset_in: HDX, + asset_out: AUSD, + amount_in: amount_to_sell, + amount_out: XYK_SELL_CALCULATION_RESULT, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn sell_should_work_with_omnipool_when_no_specified_or_onchain_route_exist() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let amount_to_sell = 10; + let limit = 1; + + //Act + assert_ok!(Router::sell( + RuntimeOrigin::signed(ALICE), + HDX, + AUSD, + amount_to_sell, + limit, + vec![] + )); + + //Assert + assert_executed_sell_trades(vec![(PoolType::Omnipool, amount_to_sell, HDX, AUSD)]); + expect_events(vec![Event::Executed { + asset_in: HDX, + asset_out: AUSD, + amount_in: amount_to_sell, + amount_out: OMNIPOOL_SELL_CALCULATION_RESULT, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn sell_should_work_when_route_has_single_trade_without_native_balance() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, KSM, 1000)]) + .build() + .execute_with(|| { + //Arrange + let amount_to_sell = 10; + let limit = 5; + + let trades = vec![Trade { + pool: PoolType::XYK, + asset_in: KSM, + asset_out: AUSD, + }]; + + //Act + assert_ok!(Router::sell( + RuntimeOrigin::signed(ALICE), + KSM, + AUSD, + amount_to_sell, + limit, + trades + )); + + //Assert + assert_executed_sell_trades(vec![(PoolType::XYK, amount_to_sell, KSM, AUSD)]); + }); +} + +#[test] +fn sell_should_fail_when_route_has_single_trade_producing_calculation_error() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, HDX, INVALID_CALCULATION_AMOUNT)]) + .build() + .execute_with(|| { + //Arrange + let limit = 5; + + let trades = vec![HDX_AUSD_TRADE_IN_XYK]; + + //Act and Assert + assert_noop!( + Router::sell( + RuntimeOrigin::signed(ALICE), + HDX, + AUSD, + INVALID_CALCULATION_AMOUNT, + limit, + trades + ), + DispatchError::Other("Some error happened") + ); + }); +} + +#[test] +fn sell_should_work_when_route_has_multiple_trades_with_same_pooltype() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let amount_to_sell = 10; + let limit = 5; + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }; + let trade2 = Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: MOVR, + }; + let trade3 = Trade { + pool: PoolType::XYK, + asset_in: MOVR, + asset_out: KSM, + }; + let trades = vec![trade1, trade2, trade3]; + + //Act + assert_ok!(Router::sell( + RuntimeOrigin::signed(ALICE), + HDX, + KSM, + amount_to_sell, + limit, + trades + )); + + //Assert + assert_executed_sell_trades(vec![ + (PoolType::XYK, amount_to_sell, HDX, AUSD), + (PoolType::XYK, XYK_SELL_CALCULATION_RESULT, AUSD, MOVR), + (PoolType::XYK, XYK_SELL_CALCULATION_RESULT, MOVR, KSM), + ]); + expect_events(vec![Event::Executed { + asset_in: HDX, + asset_out: KSM, + amount_in: amount_to_sell, + amount_out: XYK_SELL_CALCULATION_RESULT, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn sell_should_work_when_route_has_multiple_trades_with_different_pool_type() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let amount_to_sell = 10; + let limit = 1; + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: MOVR, + }; + let trade2 = Trade { + pool: PoolType::Stableswap(AUSD), + asset_in: MOVR, + asset_out: AUSD, + }; + let trade3 = Trade { + pool: PoolType::Omnipool, + asset_in: AUSD, + asset_out: KSM, + }; + let trades = vec![trade1, trade2, trade3]; + + //Act + assert_ok!(Router::sell( + RuntimeOrigin::signed(ALICE), + HDX, + KSM, + amount_to_sell, + limit, + trades + )); + + //Assert + assert_executed_sell_trades(vec![ + (PoolType::XYK, amount_to_sell, HDX, MOVR), + (PoolType::Stableswap(AUSD), XYK_SELL_CALCULATION_RESULT, MOVR, AUSD), + (PoolType::Omnipool, STABLESWAP_SELL_CALCULATION_RESULT, AUSD, KSM), + ]); + + expect_events(vec![Event::Executed { + asset_in: HDX, + asset_out: KSM, + amount_in: amount_to_sell, + amount_out: OMNIPOOL_SELL_CALCULATION_RESULT, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn sell_should_work_with_onchain_route_when_no_routes_specified() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let amount_to_sell = 10; + let limit = 1; + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: MOVR, + }; + let trade2 = Trade { + pool: PoolType::Stableswap(AUSD), + asset_in: MOVR, + asset_out: AUSD, + }; + let trade3 = Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: KSM, + }; + let trades = vec![trade1, trade2, trade3]; + assert_ok!(Router::set_route( + RuntimeOrigin::signed(ALICE), + AssetPair::new(HDX, KSM), + trades, + )); + + //Act + assert_ok!(Router::sell( + RuntimeOrigin::signed(ALICE), + HDX, + KSM, + amount_to_sell, + limit, + vec![] + )); + + //Assert + assert_last_executed_sell_trades( + 3, + vec![ + (PoolType::XYK, amount_to_sell, HDX, MOVR), + (PoolType::Stableswap(AUSD), XYK_SELL_CALCULATION_RESULT, MOVR, AUSD), + (PoolType::XYK, STABLESWAP_SELL_CALCULATION_RESULT, AUSD, KSM), + ], + ); + + expect_events(vec![Event::Executed { + asset_in: HDX, + asset_out: KSM, + amount_in: amount_to_sell, + amount_out: XYK_SELL_CALCULATION_RESULT, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn sell_should_work_with_onchain_route_when_onchain_route_present_in_reverse_order() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, KSM, 1000)]) + .build() + .execute_with(|| { + //Arrange + let amount_to_sell = 10; + let limit = 1; + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: MOVR, + }; + let trade2 = Trade { + pool: PoolType::Stableswap(AUSD), + asset_in: MOVR, + asset_out: AUSD, + }; + let trade3 = Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: KSM, + }; + let trades = vec![trade1, trade2, trade3]; + assert_ok!(Router::set_route( + RuntimeOrigin::signed(ALICE), + AssetPair::new(HDX, KSM), + trades, + )); + + //Act + //it fails, the amount out is not there after all three trades. + assert_ok!(Router::sell( + RuntimeOrigin::signed(ALICE), + KSM, + HDX, + amount_to_sell, + limit, + vec![] + )); + + //Assert + assert_last_executed_sell_trades( + 3, + vec![ + (PoolType::XYK, amount_to_sell, KSM, AUSD), + (PoolType::Stableswap(AUSD), XYK_SELL_CALCULATION_RESULT, AUSD, MOVR), + (PoolType::XYK, STABLESWAP_SELL_CALCULATION_RESULT, MOVR, HDX), + ], + ); + + expect_events(vec![Event::Executed { + asset_in: KSM, + asset_out: HDX, + amount_in: amount_to_sell, + amount_out: XYK_SELL_CALCULATION_RESULT, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn sell_should_work_when_first_trade_is_not_supported_in_the_first_pool() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let amount_to_sell = 10; + let limit = 5; + let trade1 = Trade { + pool: PoolType::Stableswap(AUSD), + asset_in: HDX, + asset_out: AUSD, + }; + let trade2 = Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: KSM, + }; + let trades = vec![trade1, trade2]; + + //Act + assert_ok!(Router::sell( + RuntimeOrigin::signed(ALICE), + HDX, + KSM, + amount_to_sell, + limit, + trades + )); + + //Assert + assert_executed_sell_trades(vec![ + (PoolType::Stableswap(AUSD), amount_to_sell, HDX, AUSD), + (PoolType::XYK, STABLESWAP_SELL_CALCULATION_RESULT, AUSD, KSM), + ]); + }); +} +#[test] +fn sell_should_fail_when_max_limit_for_trade_reached() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, HDX, 1000)]) + .build() + .execute_with(|| { + //Arrange + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }; + let trade2 = Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: MOVR, + }; + let trade3 = Trade { + pool: PoolType::XYK, + asset_in: MOVR, + asset_out: KSM, + }; + let trade4 = Trade { + pool: PoolType::XYK, + asset_in: KSM, + asset_out: RMRK, + }; + let trade5 = Trade { + pool: PoolType::XYK, + asset_in: RMRK, + asset_out: SDN, + }; + let trade6 = Trade { + pool: PoolType::XYK, + asset_in: SDN, + asset_out: STABLE_SHARE_ASSET, + }; + let trades = vec![trade1, trade2, trade3, trade4, trade5, trade6]; + + //Act and Assert + assert_noop!( + Router::sell(RuntimeOrigin::signed(ALICE), HDX, SDN, 10, 5, trades), + Error::::MaxTradesExceeded + ); + }); +} + +#[test] +fn sell_should_fail_when_called_with_non_signed_origin() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let amount_to_sell = 10; + let limit = 5; + let trades = vec![HDX_AUSD_TRADE_IN_XYK]; + + //Act and Assert + assert_noop!( + Router::sell(RuntimeOrigin::none(), HDX, AUSD, amount_to_sell, limit, trades), + BadOrigin + ); + }); +} + +#[test] +fn sell_should_fail_when_caller_has_not_enough_balance() { + //Arrange + let amount_to_sell = ALICE_INITIAL_NATIVE_BALANCE + 1; + let limit = 5; + let trades = vec![HDX_AUSD_TRADE_IN_XYK]; + + ExtBuilder::default().build().execute_with(|| { + //Act and Assert + assert_noop!( + Router::sell(RuntimeOrigin::signed(ALICE), HDX, AUSD, amount_to_sell, limit, trades), + TokenError::FundsUnavailable + ); + }); +} + +#[test] +fn sell_should_fail_when_min_limit_to_receive_is_not_reached() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let amount_to_sell = 10; + let limit = XYK_SELL_CALCULATION_RESULT + 1; + + let trades = vec![HDX_AUSD_TRADE_IN_XYK]; + + //Act and Assert + assert_noop!( + Router::sell(RuntimeOrigin::signed(ALICE), HDX, AUSD, amount_to_sell, limit, trades), + Error::::TradingLimitReached + ); + }); +} + +#[test] +fn sell_should_fail_when_assets_dont_correspond_to_route() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, AUSD, 1000)]) + .build() + .execute_with(|| { + //Arrange + let amount_to_sell = 10; + let limit = 5; + + let trades = vec![ + Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: HDX, + }, + Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: MOVR, + }, + ]; + + //Act and assert + assert_noop!( + Router::sell(RuntimeOrigin::signed(ALICE), MOVR, AUSD, amount_to_sell, limit, trades), + Error::::InvalidRoute + ); + }); +} + +#[test] +fn sell_should_fail_when_intermediare_assets_are_inconsistent() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let amount_to_sell = 10; + let limit = 5; + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }; + let trade2 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: MOVR, + }; + let trade3 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: KSM, + }; + let trades = vec![trade1, trade2, trade3]; + + //Act + assert_noop!( + Router::sell(RuntimeOrigin::signed(ALICE), HDX, KSM, amount_to_sell, limit, trades), + Error::::InvalidRoute + ); + }); +} diff --git a/pallets/route-executor/src/tests/sell_all.rs b/pallets/route-executor/src/tests/sell_all.rs new file mode 100644 index 00000000000..33d0c5f03e0 --- /dev/null +++ b/pallets/route-executor/src/tests/sell_all.rs @@ -0,0 +1,465 @@ +// This file is part of HydraDX. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::tests::mock::*; +use crate::{Error, Event, Trade}; +use basilisk_traits::router::AssetPair; +use basilisk_traits::router::PoolType; +use frame_support::{assert_noop, assert_ok}; +use orml_traits::MultiCurrency; +use pretty_assertions::assert_eq; +use sp_runtime::DispatchError::BadOrigin; + +#[test] +fn sell_should_work_when_route_has_single_trade() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let limit = 5; + + let trades = vec![HDX_AUSD_TRADE_IN_XYK]; + + let alice_balance = Currencies::free_balance(HDX, &ALICE); + + //Act + assert_ok!(Router::sell_all(RuntimeOrigin::signed(ALICE), HDX, AUSD, limit, trades)); + + //Assert + assert_executed_sell_trades(vec![(PoolType::XYK, alice_balance, HDX, AUSD)]); + expect_events(vec![Event::Executed { + asset_in: HDX, + asset_out: AUSD, + amount_in: alice_balance, + amount_out: XYK_SELL_CALCULATION_RESULT, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn sell_should_work_with_omnipool_when_no_specified_or_onchain_route_exist() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let limit = 1; + + let alice_balance = Currencies::free_balance(HDX, &ALICE); + + //Act + assert_ok!(Router::sell_all(RuntimeOrigin::signed(ALICE), HDX, AUSD, limit, vec![])); + + //Assert + assert_executed_sell_trades(vec![(PoolType::Omnipool, alice_balance, HDX, AUSD)]); + expect_events(vec![Event::Executed { + asset_in: HDX, + asset_out: AUSD, + amount_in: alice_balance, + amount_out: OMNIPOOL_SELL_CALCULATION_RESULT, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn sell_should_work_when_route_has_single_trade_without_native_balance() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, KSM, 1000)]) + .build() + .execute_with(|| { + //Arrange + let limit = 5; + + let alice_nonnative_balance = Currencies::free_balance(KSM, &ALICE); + + let trades = vec![Trade { + pool: PoolType::XYK, + asset_in: KSM, + asset_out: AUSD, + }]; + + //Act + assert_ok!(Router::sell_all(RuntimeOrigin::signed(ALICE), KSM, AUSD, limit, trades)); + + //Assert + assert_executed_sell_trades(vec![(PoolType::XYK, alice_nonnative_balance, KSM, AUSD)]); + }); +} + +#[test] +fn sell_should_work_when_route_has_multiple_trades_with_same_pooltype() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let alice_native_balance = Currencies::free_balance(HDX, &ALICE); + + let limit = 5; + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }; + let trade2 = Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: MOVR, + }; + let trade3 = Trade { + pool: PoolType::XYK, + asset_in: MOVR, + asset_out: KSM, + }; + let trades = vec![trade1, trade2, trade3]; + + //Act + assert_ok!(Router::sell_all(RuntimeOrigin::signed(ALICE), HDX, KSM, limit, trades)); + + //Assert + assert_executed_sell_trades(vec![ + (PoolType::XYK, alice_native_balance, HDX, AUSD), + (PoolType::XYK, XYK_SELL_CALCULATION_RESULT, AUSD, MOVR), + (PoolType::XYK, XYK_SELL_CALCULATION_RESULT, MOVR, KSM), + ]); + expect_events(vec![Event::Executed { + asset_in: HDX, + asset_out: KSM, + amount_in: alice_native_balance, + amount_out: XYK_SELL_CALCULATION_RESULT, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn sell_should_work_when_route_has_multiple_trades_with_different_pool_type() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let alice_native_balance = Currencies::free_balance(HDX, &ALICE); + + let limit = 1; + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: MOVR, + }; + let trade2 = Trade { + pool: PoolType::Stableswap(AUSD), + asset_in: MOVR, + asset_out: AUSD, + }; + let trade3 = Trade { + pool: PoolType::Omnipool, + asset_in: AUSD, + asset_out: KSM, + }; + let trades = vec![trade1, trade2, trade3]; + + //Act + assert_ok!(Router::sell_all(RuntimeOrigin::signed(ALICE), HDX, KSM, limit, trades)); + + //Assert + assert_executed_sell_trades(vec![ + (PoolType::XYK, alice_native_balance, HDX, MOVR), + (PoolType::Stableswap(AUSD), XYK_SELL_CALCULATION_RESULT, MOVR, AUSD), + (PoolType::Omnipool, STABLESWAP_SELL_CALCULATION_RESULT, AUSD, KSM), + ]); + + expect_events(vec![Event::Executed { + asset_in: HDX, + asset_out: KSM, + amount_in: alice_native_balance, + amount_out: OMNIPOOL_SELL_CALCULATION_RESULT, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn sell_should_work_with_onchain_route_when_no_routes_specified() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let alice_native_balance = Currencies::free_balance(HDX, &ALICE); + let limit = 1; + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: MOVR, + }; + let trade2 = Trade { + pool: PoolType::Stableswap(AUSD), + asset_in: MOVR, + asset_out: AUSD, + }; + let trade3 = Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: KSM, + }; + let trades = vec![trade1, trade2, trade3]; + assert_ok!(Router::set_route( + RuntimeOrigin::signed(ALICE), + AssetPair::new(HDX, KSM), + trades, + )); + + //Act + assert_ok!(Router::sell_all(RuntimeOrigin::signed(ALICE), HDX, KSM, limit, vec![])); + + //Assert + assert_last_executed_sell_trades( + 3, + vec![ + (PoolType::XYK, alice_native_balance, HDX, MOVR), + (PoolType::Stableswap(AUSD), XYK_SELL_CALCULATION_RESULT, MOVR, AUSD), + (PoolType::XYK, STABLESWAP_SELL_CALCULATION_RESULT, AUSD, KSM), + ], + ); + + expect_events(vec![Event::Executed { + asset_in: HDX, + asset_out: KSM, + amount_in: alice_native_balance, + amount_out: XYK_SELL_CALCULATION_RESULT, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn sell_should_work_with_onchain_route_when_onchain_route_present_in_reverse_order() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, KSM, 2000)]) + .build() + .execute_with(|| { + //Arrange + let alice_nonnative_balance = Currencies::free_balance(KSM, &ALICE); + + let limit = 1; + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: MOVR, + }; + let trade2 = Trade { + pool: PoolType::Stableswap(AUSD), + asset_in: MOVR, + asset_out: AUSD, + }; + let trade3 = Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: KSM, + }; + let trades = vec![trade1, trade2, trade3]; + assert_ok!(Router::set_route( + RuntimeOrigin::signed(ALICE), + AssetPair::new(HDX, KSM), + trades, + )); + + //Act + //it fails, the amount out is not there after all three trades. + assert_ok!(Router::sell_all(RuntimeOrigin::signed(ALICE), KSM, HDX, limit, vec![])); + + //Assert + assert_last_executed_sell_trades( + 3, + vec![ + (PoolType::XYK, alice_nonnative_balance, KSM, AUSD), + (PoolType::Stableswap(AUSD), XYK_SELL_CALCULATION_RESULT, AUSD, MOVR), + (PoolType::XYK, STABLESWAP_SELL_CALCULATION_RESULT, MOVR, HDX), + ], + ); + + expect_events(vec![Event::Executed { + asset_in: KSM, + asset_out: HDX, + amount_in: alice_nonnative_balance, + amount_out: XYK_SELL_CALCULATION_RESULT, + event_id: 0, + } + .into()]); + }); +} + +#[test] +fn sell_should_work_when_first_trade_is_not_supported_in_the_first_pool() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let alice_native_balance = Currencies::free_balance(HDX, &ALICE); + let limit = 5; + let trade1 = Trade { + pool: PoolType::Stableswap(AUSD), + asset_in: HDX, + asset_out: AUSD, + }; + let trade2 = Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: KSM, + }; + let trades = vec![trade1, trade2]; + + //Act + assert_ok!(Router::sell_all(RuntimeOrigin::signed(ALICE), HDX, KSM, limit, trades)); + + //Assert + assert_executed_sell_trades(vec![ + (PoolType::Stableswap(AUSD), alice_native_balance, HDX, AUSD), + (PoolType::XYK, STABLESWAP_SELL_CALCULATION_RESULT, AUSD, KSM), + ]); + }); +} + +#[test] +fn sell_should_fail_when_max_limit_for_trade_reached() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, HDX, 1000)]) + .build() + .execute_with(|| { + //Arrange + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }; + let trade2 = Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: MOVR, + }; + let trade3 = Trade { + pool: PoolType::XYK, + asset_in: MOVR, + asset_out: KSM, + }; + let trade4 = Trade { + pool: PoolType::XYK, + asset_in: KSM, + asset_out: RMRK, + }; + let trade5 = Trade { + pool: PoolType::XYK, + asset_in: RMRK, + asset_out: SDN, + }; + let trade6 = Trade { + pool: PoolType::XYK, + asset_in: SDN, + asset_out: STABLE_SHARE_ASSET, + }; + let trades = vec![trade1, trade2, trade3, trade4, trade5, trade6]; + + //Act and Assert + assert_noop!( + Router::sell_all(RuntimeOrigin::signed(ALICE), HDX, SDN, 5, trades), + Error::::MaxTradesExceeded + ); + }); +} + +#[test] +fn sell_should_fail_when_called_with_non_signed_origin() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let limit = 5; + let trades = vec![HDX_AUSD_TRADE_IN_XYK]; + + //Act and Assert + assert_noop!( + Router::sell_all(RuntimeOrigin::none(), HDX, AUSD, limit, trades), + BadOrigin + ); + }); +} + +#[test] +fn sell_should_fail_when_min_limit_to_receive_is_not_reached() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let limit = XYK_SELL_CALCULATION_RESULT + 1; + + let trades = vec![HDX_AUSD_TRADE_IN_XYK]; + + //Act and Assert + assert_noop!( + Router::sell_all(RuntimeOrigin::signed(ALICE), HDX, AUSD, limit, trades), + Error::::TradingLimitReached + ); + }); +} + +#[test] +fn sell_should_fail_when_assets_dont_correspond_to_route() { + ExtBuilder::default() + .with_endowed_accounts(vec![(ALICE, AUSD, 1000)]) + .build() + .execute_with(|| { + //Arrange + let limit = 5; + + let trades = vec![ + Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: HDX, + }, + Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: MOVR, + }, + ]; + + //Act and assert + assert_noop!( + Router::sell_all(RuntimeOrigin::signed(ALICE), MOVR, AUSD, limit, trades), + Error::::InvalidRoute + ); + }); +} + +#[test] +fn sell_should_fail_when_intermediare_assets_are_inconsistent() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let limit = 5; + let trade1 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }; + let trade2 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: MOVR, + }; + let trade3 = Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: KSM, + }; + let trades = vec![trade1, trade2, trade3]; + + //Act + assert_noop!( + Router::sell_all(RuntimeOrigin::signed(ALICE), HDX, KSM, limit, trades), + Error::::InvalidRoute + ); + }); +} diff --git a/pallets/route-executor/src/tests/set_route.rs b/pallets/route-executor/src/tests/set_route.rs new file mode 100644 index 00000000000..9a36a663cfb --- /dev/null +++ b/pallets/route-executor/src/tests/set_route.rs @@ -0,0 +1,487 @@ +// This file is part of HydraDX. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::tests::mock::*; +use crate::{Error, Event, Trade}; +use basilisk_traits::router::RouteProvider; +use basilisk_traits::router::{AssetPair, PoolType}; +use frame_support::pallet_prelude::*; +use frame_support::{assert_noop, assert_ok}; +use pretty_assertions::assert_eq; +use sp_runtime::DispatchError::BadOrigin; + +#[test] +fn set_route_should_work_when_overriting_default_omnipool() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, AUSD); + let route = vec![Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }]; + + //Act + assert_ok!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, route.clone()), + Pays::No.into() + ); + + //Assert + let stored_route = Router::get_route(asset_pair); + assert_eq!(stored_route, route); + + expect_events(vec![Event::RouteUpdated { + asset_ids: vec![HDX, AUSD], + } + .into()]); + + expect_no_route_executed_event() + }); +} + +#[test] +fn set_route_should_store_route_in_ordered_fashion() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(DOT, HDX); + let route = vec![ + Trade { + pool: PoolType::XYK, + asset_in: DOT, + asset_out: STABLE_SHARE_ASSET, + }, + Trade { + pool: PoolType::Stableswap(STABLE_SHARE_ASSET), + asset_in: STABLE_SHARE_ASSET, + asset_out: AUSD, + }, + Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: HDX, + }, + ]; + + //Act + assert_ok!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, route), + Pays::No.into() + ); + + //Assert + let route_ordered = vec![ + Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }, + Trade { + pool: PoolType::Stableswap(STABLE_SHARE_ASSET), + asset_in: AUSD, + asset_out: STABLE_SHARE_ASSET, + }, + Trade { + pool: PoolType::XYK, + asset_in: STABLE_SHARE_ASSET, + asset_out: DOT, + }, + ]; + let stored_route = Router::get_route(asset_pair.ordered_pair()); + assert_eq!(stored_route, route_ordered); + }); +} + +#[test] +fn set_route_should_work_when_new_price_is_better() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, AUSD); + let route = vec![ + Trade { + pool: PoolType::LBP, + asset_in: HDX, + asset_out: DOT, + }, + Trade { + pool: PoolType::LBP, + asset_in: DOT, + asset_out: AUSD, + }, + ]; + + assert_ok!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, route), + Pays::No.into() + ); + + expect_events(vec![Event::RouteUpdated { + asset_ids: vec![HDX, AUSD], + } + .into()]); + + //Act + let cheaper_route = vec![Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }]; + + assert_ok!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, cheaper_route.clone()), + Pays::No.into() + ); + + //Assert + let stored_route = Router::get_route(asset_pair); + assert_eq!(stored_route, cheaper_route); + + expect_events(vec![ + Event::RouteUpdated { + asset_ids: vec![HDX, AUSD], + } + .into(), + Event::RouteUpdated { + asset_ids: vec![HDX, AUSD], + } + .into(), + ]); + expect_no_route_executed_event() + }); +} + +#[test] +fn set_route_should_not_override_when_only_normal_sell_price_is_better() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, AUSD); + + let route = vec![ + Trade { + pool: PoolType::Stableswap(STABLE_SHARE_ASSET), + asset_in: HDX, + asset_out: STABLE_SHARE_ASSET, + }, + Trade { + pool: PoolType::XYK, + asset_in: STABLE_SHARE_ASSET, + asset_out: AUSD, + }, + ]; + + assert_noop!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, route), + Error::::RouteUpdateIsNotSuccessful, + ); + + //Act and Assert + let stored_route = Router::get_route(asset_pair); + assert_eq!(stored_route, default_omnipool_route()); + }); +} + +#[test] +fn set_route_should_not_override_when_only_inverse_sell_price_is_better() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, AUSD); + + let route = vec![ + Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: STABLE_SHARE_ASSET, + }, + Trade { + pool: PoolType::Stableswap(STABLE_SHARE_ASSET), + asset_in: STABLE_SHARE_ASSET, + asset_out: AUSD, + }, + ]; + + //Act + assert_noop!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, route), + Error::::RouteUpdateIsNotSuccessful + ); + + //Assert + let stored_route = Router::get_route(asset_pair); + assert_eq!(stored_route, default_omnipool_route()); + }); +} + +#[test] +fn set_route_should_not_override_when_both_sell_and_buy_price_is_worse() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, AUSD); + let cheaper_route = vec![Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }]; + + assert_ok!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, cheaper_route.clone()), + Pays::No.into() + ); + + let route = vec![ + Trade { + pool: PoolType::Omnipool, + asset_in: HDX, + asset_out: STABLE_SHARE_ASSET, + }, + Trade { + pool: PoolType::Stableswap(STABLE_SHARE_ASSET), + asset_in: STABLE_SHARE_ASSET, + asset_out: AUSD, + }, + ]; + + //Act + assert_noop!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, route), + Error::::RouteUpdateIsNotSuccessful + ); + + //Assert + let stored_route = Router::get_route(asset_pair); + assert_eq!(stored_route, cheaper_route); + }); +} + +#[test] +fn set_route_should_fail_when_called_by_unsigned() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, AUSD); + let route = vec![ + Trade { + pool: PoolType::Omnipool, + asset_in: HDX, + asset_out: STABLE_SHARE_ASSET, + }, + Trade { + pool: PoolType::Stableswap(STABLE_SHARE_ASSET), + asset_in: STABLE_SHARE_ASSET, + asset_out: AUSD, + }, + ]; + + //Act and assert + assert_noop!(Router::set_route(RuntimeOrigin::none(), asset_pair, route), BadOrigin); + }); +} + +#[test] +fn set_route_should_fail_when_asset_pair_is_invalid_for_route() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, DOT); + let route = vec![ + Trade { + pool: PoolType::Omnipool, + asset_in: HDX, + asset_out: STABLE_SHARE_ASSET, + }, + Trade { + pool: PoolType::Stableswap(STABLE_SHARE_ASSET), + asset_in: STABLE_SHARE_ASSET, + asset_out: AUSD, + }, + ]; + + //Act and assert + assert_noop!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, route), + Error::::InvalidRoute + ); + }); +} + +#[test] +fn set_route_should_fail_when_called_with_empty_route() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, AUSD); + let empty_route = vec![]; + + //Act and assert + assert_noop!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, empty_route), + Error::::InvalidRoute + ); + }); +} + +#[test] +fn set_route_should_fail_when_called_with_too_long_route() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, AUSD); + + let trades = [Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }; 6]; + + let empty_route = trades.to_vec(); + + //Act and assert + assert_noop!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, empty_route), + Error::::MaxTradesExceeded + ); + }); +} + +#[test] +fn set_route_should_fail_when_route_is_not_valid() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, AUSD); + + let route = vec![ + Trade { + pool: PoolType::Omnipool, + asset_in: HDX, + asset_out: AUSD, + }, + Trade { + pool: PoolType::Stableswap(STABLE_SHARE_ASSET), + asset_in: STABLE_SHARE_ASSET, + asset_out: AUSD, + }, + ]; + + //Act and assert + assert_noop!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, route), + Error::::InvalidRoute + ); + + assert!(Router::route(asset_pair).is_none()); + }); +} + +#[test] +fn set_route_should_fail_when_trying_to_override_with_invalid_route() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, AUSD); + + let invalid_route = vec![ + Trade { + pool: PoolType::Omnipool, + asset_in: HDX, + asset_out: AUSD, + }, + Trade { + pool: PoolType::Stableswap(STABLE_SHARE_ASSET), + asset_in: STABLE_SHARE_ASSET, + asset_out: AUSD, + }, + ]; + + //Act and assert + assert_noop!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, invalid_route), + Error::::InvalidRoute + ); + + let stored_route = Router::get_route(asset_pair); + assert_eq!(stored_route, default_omnipool_route()); + }); +} + +#[test] +fn set_route_should_not_work_when_readded_the_same() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, AUSD); + let route = vec![Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }]; + + //Act + assert_ok!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, route.clone()), + Pays::No.into() + ); + + //Assert + assert_noop!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, route), + Error::::RouteUpdateIsNotSuccessful + ); + }); +} + +#[test] +fn set_route_should_fail_with_insufficient_asset() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, INSUFFICIENT_ASSET); + let route = vec![Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: INSUFFICIENT_ASSET, + }]; + + //Act + assert_noop!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, route), + Error::::RouteHasNoOracle + ); + }); +} + +#[test] +fn set_route_should_fail_with_insufficient_asset_as_intermediare() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let asset_pair = AssetPair::new(HDX, DOT); + let route = vec![ + Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: AUSD, + }, + Trade { + pool: PoolType::XYK, + asset_in: AUSD, + asset_out: INSUFFICIENT_ASSET, + }, + Trade { + pool: PoolType::XYK, + asset_in: INSUFFICIENT_ASSET, + asset_out: DOT, + }, + ]; + + //Act + assert_noop!( + Router::set_route(RuntimeOrigin::signed(ALICE), asset_pair, route), + Error::::RouteHasNoOracle + ); + }); +} diff --git a/pallets/route-executor/src/tests/spot_price.rs b/pallets/route-executor/src/tests/spot_price.rs new file mode 100644 index 00000000000..18216bee938 --- /dev/null +++ b/pallets/route-executor/src/tests/spot_price.rs @@ -0,0 +1,11 @@ +use crate::tests::mock::*; +use basilisk_traits::router::RouteSpotPriceProvider; + +#[test] +fn price_should_be_none_for_empty_route() { + ExtBuilder::default().build().execute_with(|| { + let price = Router::spot_price_with_fee(&[]); + + assert!(price.is_none()); + }); +} diff --git a/pallets/route-executor/src/types.rs b/pallets/route-executor/src/types.rs new file mode 100644 index 00000000000..f77809c1250 --- /dev/null +++ b/pallets/route-executor/src/types.rs @@ -0,0 +1,9 @@ +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::pallet_prelude::TypeInfo; + +#[derive(Debug, Encode, Decode, Copy, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +pub enum SkipEd { + Lock, + LockAndUnlock, + Unlock, +} diff --git a/pallets/route-executor/src/weights.rs b/pallets/route-executor/src/weights.rs new file mode 100644 index 00000000000..cd05ab51b03 --- /dev/null +++ b/pallets/route-executor/src/weights.rs @@ -0,0 +1,190 @@ +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for `pallet_route_executor`. +pub trait WeightInfo { + fn skip_ed_handling_for_trade_with_insufficient_assets() -> Weight; + fn calculate_and_execute_sell_in_lbp(c: u32, ) -> Weight; + fn calculate_and_execute_buy_in_lbp(c: u32, b: u32, ) -> Weight; + fn set_route_for_xyk() -> Weight; + fn force_insert_route() -> Weight; + fn get_oracle_price_for_xyk() -> Weight; + fn get_oracle_price_for_omnipool() -> Weight; + fn get_route() -> Weight; + fn calculate_spot_price_with_fee_in_lbp() -> Weight; +} + +/// Weights for `pallet_route_executor` using the HydraDX node and recommended hardware. +pub struct HydraWeight(PhantomData); +impl WeightInfo for HydraWeight { + /// Storage: `AssetRegistry::Assets` (r:1 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:0 w:1) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + fn skip_ed_handling_for_trade_with_insufficient_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `944` + // Estimated: `3590` + // Minimum execution time: 18_351_000 picoseconds. + Weight::from_parts(18_623_000, 3590) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `LBP::PoolData` (r:1 w:0) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:5 w:5) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Locks` (r:1 w:1) + /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:1) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:2 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// The range of component `c` is `[0, 1]`. + fn calculate_and_execute_sell_in_lbp(c: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `3809` + // Estimated: `13905` + // Minimum execution time: 403_889_000 picoseconds. + Weight::from_parts(408_439_763, 13905) + // Standard Error: 288_679 + .saturating_add(Weight::from_parts(78_440_436, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(17_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) + } + /// Storage: `LBP::PoolData` (r:1 w:0) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:5 w:5) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Locks` (r:1 w:1) + /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:1) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:2 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// The range of component `c` is `[1, 2]`. + /// The range of component `b` is `[0, 1]`. + fn calculate_and_execute_buy_in_lbp(c: u32, b: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1992 + b * (1842 ±0)` + // Estimated: `8799 + b * (7749 ±0)` + // Minimum execution time: 116_165_000 picoseconds. + Weight::from_parts(117_686_000, 8799) + // Standard Error: 232_510 + .saturating_add(Weight::from_parts(962_142, 0).saturating_mul(c.into())) + // Standard Error: 517_865 + .saturating_add(Weight::from_parts(293_725_885, 0).saturating_mul(b.into())) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().reads((12_u64).saturating_mul(b.into()))) + .saturating_add(RocksDbWeight::get().writes((8_u64).saturating_mul(b.into()))) + .saturating_add(Weight::from_parts(0, 7749).saturating_mul(b.into())) + } + /// Storage: `EmaOracle::Oracles` (r:2 w:0) + /// Proof: `EmaOracle::Oracles` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `Router::Routes` (r:1 w:1) + /// Proof: `Router::Routes` (`max_values`: None, `max_size`: Some(90), added: 2565, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:7 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:6 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:15 w:0) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `XYK::ShareToken` (r:6 w:0) + /// Proof: `XYK::ShareToken` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:7 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:5 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AcceptedCurrencies` (r:5 w:0) + /// Proof: `MultiTransactionPayment::AcceptedCurrencies` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::Accumulator` (r:1 w:0) + /// Proof: `EmaOracle::Accumulator` (`max_values`: Some(1), `max_size`: Some(5921), added: 6416, mode: `MaxEncodedLen`) + /// Storage: `Tokens::TotalIssuance` (r:1 w:0) + /// Proof: `Tokens::TotalIssuance` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn set_route_for_xyk() -> Weight { + // Proof Size summary in bytes: + // Measured: `7071` + // Estimated: `39735` + // Minimum execution time: 2_238_560_000 picoseconds. + Weight::from_parts(2_251_837_000, 39735) + .saturating_add(RocksDbWeight::get().reads(58_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Router::Routes` (r:0 w:1) + /// Proof: `Router::Routes` (`max_values`: None, `max_size`: Some(90), added: 2565, mode: `MaxEncodedLen`) + fn force_insert_route() -> Weight { + // Proof Size summary in bytes: + // Measured: `1012` + // Estimated: `0` + // Minimum execution time: 30_739_000 picoseconds. + Weight::from_parts(31_254_000, 0) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Router::Routes` (r:1 w:0) + /// Proof: `Router::Routes` (`max_values`: None, `max_size`: Some(90), added: 2565, mode: `MaxEncodedLen`) + fn get_route() -> Weight { + // Proof Size summary in bytes: + // Measured: `800` + // Estimated: `3555` + // Minimum execution time: 9_385_000 picoseconds. + Weight::from_parts(9_633_000, 3555) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `EmaOracle::Oracles` (r:2 w:0) + /// Proof: `EmaOracle::Oracles` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + fn get_oracle_price_for_xyk() -> Weight { + // Proof Size summary in bytes: + // Measured: `1452` + // Estimated: `6294` + // Minimum execution time: 32_684_000 picoseconds. + Weight::from_parts(33_157_000, 6294) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + } + /// Storage: `EmaOracle::Oracles` (r:4 w:0) + /// Proof: `EmaOracle::Oracles` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + fn get_oracle_price_for_omnipool() -> Weight { + // Proof Size summary in bytes: + // Measured: `1814` + // Estimated: `11598` + // Minimum execution time: 48_768_000 picoseconds. + Weight::from_parts(49_167_000, 11598) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + } + /// Storage: `LBP::PoolData` (r:1 w:0) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Locks` (r:1 w:0) + /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:2 w:0) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + fn calculate_spot_price_with_fee_in_lbp() -> Weight { + // Proof Size summary in bytes: + // Measured: `2029` + // Estimated: `6190` + // Minimum execution time: 57_184_000 picoseconds. + Weight::from_parts(57_713_000, 6190) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + } +} diff --git a/pallets/transaction-multi-payment/Cargo.toml b/pallets/transaction-multi-payment/Cargo.toml new file mode 100644 index 00000000000..639742b71a9 --- /dev/null +++ b/pallets/transaction-multi-payment/Cargo.toml @@ -0,0 +1,65 @@ +[package] +name = "pallet-transaction-multi-payment" +version = "11.1.0" +description = "Transaction multi currency payment support module" +authors = ["GalacticCoucil"] +edition = "2021" +license = "Apache 2.0" +repository = "https://github.com/galacticcouncil/warehouse" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { workspace = true } +scale-info = { workspace = true } + +# ORML dependencies +orml-traits = { workspace = true } + +basilisk-math = { workspace = true } +basilisk-traits = { workspace = true } + +# HydraDX traits +hydradx-traits = { workspace = true } +primitives = { workspace = true } +hydra-dx-math = { workspace = true } +pallet-xyk = { workspace = true } + +# Substrate dependencies +frame-support = { workspace = true } +frame-system = { workspace = true } +sp-api = { workspace = true } +sp-core = { workspace = true } +sp-std = { workspace = true } +sp-runtime = { workspace = true } +pallet-transaction-payment = { workspace = true } +pallet-utility = { workspace = true } + +[dev-dependencies] +pallet-currencies = { workspace = true } +orml-tokens = { workspace = true, features = ["std"] } +pallet-balances = { workspace = true, features = ["std"] } +sp-io = { workspace = true } +test-utils = { workspace = true } + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-core/std", + "sp-api/std", + "frame-support/std", + "frame-system/std", + "pallet-transaction-payment/std", + "sp-runtime/std", + "orml-traits/std", + "hydradx-traits/std", + "scale-info/std", + "primitives/std", +] +try-runtime = ["frame-support/try-runtime"] +runtime-benchmarks = [ + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", +] diff --git a/pallets/transaction-multi-payment/README.md b/pallets/transaction-multi-payment/README.md new file mode 100644 index 00000000000..1886f1de23a --- /dev/null +++ b/pallets/transaction-multi-payment/README.md @@ -0,0 +1,27 @@ + +## Transaction multi payment + +### Overview + +This pallet provides functionality to accepted transaction fees in other currencies. + +Extends substrate's `transaction-payment` pallet. + +### Interface +Extends `transaction-payment` interface to add functionality to set desired currency and to add members who can add or remove accepted currencies. + +- `set_currency` - set selected currency in whci all transactions fees will be paid. Balance of selected currency must be non-zero. +- `add_member` - only root can perform this action +- `remove_member` - only root can perform this action + +### Implementation details + +Transaction fees are paid in native currency by default. This pallet allows to set a different currency to pay fees with for an account. + +When the transaction fees is being paid and chosen currency is not native currency - swap is executed to obtain fee amount in native currency first. + +The swap (or buy) is done via selected AMM pool. + +Subsequently, the fee is paid in native currency. + + diff --git a/pallets/transaction-multi-payment/src/lib.rs b/pallets/transaction-multi-payment/src/lib.rs new file mode 100644 index 00000000000..2cd28a14ade --- /dev/null +++ b/pallets/transaction-multi-payment/src/lib.rs @@ -0,0 +1,912 @@ +// This file is part of Basilisk-node. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::unused_unit)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::large_enum_variant)] +#![allow(clippy::manual_inspect)] + +pub mod weights; + +pub use weights::WeightInfo; + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; +mod traits; + +pub use crate::traits::*; +use basilisk_math::ema::EmaPrice; +use basilisk_traits::{ + oracle::{NativePriceOracle, OraclePeriod, PriceOracle}, + router::{AssetPair, RouteProvider}, +}; +use frame_support::storage::with_transaction; +use frame_support::traits::{Contains, ExistenceRequirement, IsSubType}; +use frame_support::{ + dispatch::DispatchResult, + ensure, + sp_runtime::{ + traits::{DispatchInfoOf, One, PostDispatchInfoOf, Saturating, Zero}, + transaction_validity::{InvalidTransaction, TransactionValidityError}, + FixedPointNumber, FixedPointOperand, FixedU128, + }, + traits::Get, + weights::Weight, +}; +use frame_system::{ensure_signed, pallet_prelude::BlockNumberFor}; +use hydradx_traits::fee::InspectTransactionFeeCurrency; +use hydradx_traits::fee::SwappablePaymentAssetTrader; +use hydradx_traits::{evm::InspectEvmAccounts, AccountFeeCurrency}; +use orml_traits::{GetByKey, Happened, MultiCurrency}; +use pallet_transaction_payment::OnChargeTransaction; +use sp_runtime::traits::TryConvert; +use sp_std::{marker::PhantomData, prelude::*}; + +pub type AssetIdOf = + <::Currencies as MultiCurrency<::AccountId>>::CurrencyId; +type BalanceOf = <::Currencies as MultiCurrency<::AccountId>>::Balance; + +/// Spot price type +pub type Price = FixedU128; + +// Re-export pallet items so that they can be accessed from the crate namespace. +pub use pallet::*; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use codec::DecodeLimit; + use frame_support::dispatch::PostDispatchInfo; + use frame_support::pallet_prelude::*; + use frame_support::weights::WeightToFee; + use frame_system::ensure_none; + use frame_system::pallet_prelude::OriginFor; + use hydradx_traits::fee::SwappablePaymentAssetTrader; + use sp_core::{H160, H256, U256}; + use sp_runtime::{ModuleError, TransactionOutcome}; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(_n: BlockNumberFor) -> Weight { + let native_asset = T::NativeAssetId::get(); + + let mut weight: u64 = 0; + + for (asset_id, fallback_price) in >::iter() { + let maybe_price = Self::get_oracle_price(asset_id, native_asset); + + let price = maybe_price.unwrap_or(fallback_price); + + AcceptedCurrencyPrice::::insert(asset_id, price); + + weight += ::WeightInfo::get_oracle_price().ref_time(); + } + + Weight::from_parts(weight, 0) + } + + fn on_finalize(_n: BlockNumberFor) { + let _ = >::clear(u32::MAX, None); + } + } + + #[pallet::config] + pub trait Config: frame_system::Config + pallet_transaction_payment::Config { + /// Because this pallet emits events, it depends on the runtime's definition of an event. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// The origin which can add/remove accepted currencies + type AcceptedCurrencyOrigin: EnsureOrigin; + + /// Multi Currency + type Currencies: MultiCurrency; + + /// On chain route provider + type RouteProvider: RouteProvider>; + + /// Oracle price provider for routes + type OraclePriceProvider: PriceOracle, Price = EmaPrice>; + + /// Supporting swappable assets as fee currencies + type SwappablePaymentAssetSupport: SwappablePaymentAssetTrader< + Self::AccountId, + AssetIdOf, + BalanceOf, + >; + + /// Weight information for the extrinsics. + type WeightInfo: WeightInfo; + + /// Convert a weight value into a deductible fee based on the currency type. + type WeightToFee: WeightToFee>; + + /// Native Asset + #[pallet::constant] + type NativeAssetId: Get>; + + /// Polkadot Native Asset (DOT) + #[pallet::constant] + type PolkadotNativeAssetId: Get>; + + /// EVM Asset + #[pallet::constant] + type EvmAssetId: Get>; + + /// EVM Accounts info + type InspectEvmAccounts: InspectEvmAccounts; + + type EvmPermit: EVMPermit; + + /// Try to retrieve fee currency from runtime call. + /// It is generic implementation to avoid tight coupling with other pallets such as utility. + type TryCallCurrency<'a>: TryConvert<&'a ::RuntimeCall, AssetIdOf>; + } + + #[pallet::event] + #[pallet::generate_deposit(pub(crate) fn deposit_event)] + pub enum Event { + /// CurrencySet + /// [who, currency] + CurrencySet { + account_id: T::AccountId, + asset_id: AssetIdOf, + }, + + /// New accepted currency added + /// [currency] + CurrencyAdded { asset_id: AssetIdOf }, + + /// Accepted currency removed + /// [currency] + CurrencyRemoved { asset_id: AssetIdOf }, + + /// Transaction fee paid in non-native currency + /// [Account, Currency, Native fee amount, Non-native fee amount, Destination account] + FeeWithdrawn { + account_id: T::AccountId, + asset_id: AssetIdOf, + native_fee_amount: BalanceOf, + non_native_fee_amount: BalanceOf, + destination_account_id: T::AccountId, + }, + } + + #[pallet::error] + pub enum Error { + /// Selected currency is not supported. + UnsupportedCurrency, + + /// Account balance should be non-zero. + ZeroBalance, + + /// Currency is already in the list of accepted currencies. + AlreadyAccepted, + + /// It is not allowed to add Core Asset as accepted currency. Core asset is accepted by design. + CoreAssetNotAllowed, + + /// Fallback price cannot be zero. + ZeroPrice, + + /// Fallback price was not found. + FallbackPriceNotFound, + + /// Math overflow + Overflow, + + /// It is not allowed to change payment currency of an EVM account. + EvmAccountNotAllowed, + + /// EVM permit expired. + EvmPermitExpired, + + /// EVM permit is invalid. + EvmPermitInvalid, + + /// EVM permit call failed. + EvmPermitCallExecutionError, + + /// EVM permit call failed. + EvmPermitRunnerError, + } + + /// Account currency map + #[pallet::storage] + #[pallet::getter(fn get_currency)] + pub type AccountCurrencyMap = StorageMap<_, Blake2_128Concat, T::AccountId, AssetIdOf, OptionQuery>; + + /// Curated list of currencies which fees can be paid mapped to corresponding fallback price + #[pallet::storage] + #[pallet::getter(fn currencies)] + pub type AcceptedCurrencies = StorageMap<_, Twox64Concat, AssetIdOf, Price, OptionQuery>; + + /// Asset prices from the spot price provider or the fallback price if the price is not available. Updated at the beginning of every block. + #[pallet::storage] + #[pallet::getter(fn currency_price)] + pub type AcceptedCurrencyPrice = StorageMap<_, Twox64Concat, AssetIdOf, Price, OptionQuery>; + + #[pallet::storage] + #[pallet::getter(fn tx_fee_currency_override)] + pub type TransactionCurrencyOverride = + StorageMap<_, Twox64Concat, T::AccountId, AssetIdOf, OptionQuery>; + + #[pallet::genesis_config] + #[derive(frame_support::DefaultNoBound)] + pub struct GenesisConfig { + pub currencies: Vec<(AssetIdOf, Price)>, + pub account_currencies: Vec<(T::AccountId, AssetIdOf)>, + } + + #[pallet::genesis_build] + impl BuildGenesisConfig for GenesisConfig { + fn build(&self) { + for (asset, price) in &self.currencies { + AcceptedCurrencies::::insert(asset, price); + } + + for (account, asset) in &self.account_currencies { + >::insert(account, asset); + } + } + } + #[pallet::call] + impl Pallet + where + BalanceOf: FixedPointOperand, + { + /// Set selected currency for given account. + /// + /// This allows to set a currency for an account in which all transaction fees will be paid. + /// Account balance cannot be zero. + /// + /// In case of sufficient asset, the chosen currency must be in the list of accepted currencies + /// In case of insufficient asset, the chosen currency must have a XYK pool with DOT + /// + /// When currency is set, fixed fee is withdrawn from the account to pay for the currency change + /// + /// EVM accounts are now allowed to change thier payment currency. + /// + /// Emits `CurrencySet` event when successful. + #[pallet::call_index(0)] + #[pallet::weight(::WeightInfo::set_currency())] + pub fn set_currency(origin: OriginFor, currency: AssetIdOf) -> DispatchResult { + let who = ensure_signed(origin)?; + + if T::SwappablePaymentAssetSupport::is_transaction_fee_currency(currency) { + ensure!( + currency == T::NativeAssetId::get() || AcceptedCurrencies::::contains_key(currency), + Error::::UnsupportedCurrency + ); + } else { + ensure!( + T::SwappablePaymentAssetSupport::is_trade_supported(currency, T::PolkadotNativeAssetId::get()), + Error::::UnsupportedCurrency + ); + } + + >::insert(who.clone(), currency); + + Self::deposit_event(Event::CurrencySet { + account_id: who, + asset_id: currency, + }); + + Ok(()) + } + + /// Add a currency to the list of accepted currencies. + /// + /// Only member can perform this action. + /// + /// Currency must not be already accepted. Core asset id cannot be explicitly added. + /// + /// Emits `CurrencyAdded` event when successful. + #[pallet::call_index(1)] + #[pallet::weight(::WeightInfo::add_currency())] + pub fn add_currency(origin: OriginFor, currency: AssetIdOf, price: Price) -> DispatchResult { + T::AcceptedCurrencyOrigin::ensure_origin(origin)?; + + ensure!(currency != T::NativeAssetId::get(), Error::::CoreAssetNotAllowed); + + AcceptedCurrencies::::try_mutate_exists(currency, |maybe_price| -> DispatchResult { + if maybe_price.is_some() { + return Err(Error::::AlreadyAccepted.into()); + } + + *maybe_price = Some(price); + Self::deposit_event(Event::CurrencyAdded { asset_id: currency }); + Ok(()) + }) + } + + /// Remove currency from the list of supported currencies + /// Only selected members can perform this action + /// + /// Core asset cannot be removed. + /// + /// Emits `CurrencyRemoved` when successful. + #[pallet::call_index(2)] + #[pallet::weight(::WeightInfo::remove_currency())] + pub fn remove_currency(origin: OriginFor, currency: AssetIdOf) -> DispatchResult { + T::AcceptedCurrencyOrigin::ensure_origin(origin)?; + + ensure!(currency != T::NativeAssetId::get(), Error::::CoreAssetNotAllowed); + + AcceptedCurrencies::::try_mutate(currency, |x| -> DispatchResult { + if x.is_none() { + return Err(Error::::UnsupportedCurrency.into()); + } + + *x = None; + + Self::deposit_event(Event::CurrencyRemoved { asset_id: currency }); + + Ok(()) + }) + } + + /// Reset currency of the specified account to HDX. + /// If the account is EVM account, the payment currency is reset to WETH. + /// Only selected members can perform this action. + /// + /// Emits `CurrencySet` when successful. + #[pallet::call_index(3)] + #[pallet::weight(::WeightInfo::reset_payment_currency())] + pub fn reset_payment_currency(origin: OriginFor, account_id: T::AccountId) -> DispatchResult { + T::AcceptedCurrencyOrigin::ensure_origin(origin)?; + + let currency = if T::InspectEvmAccounts::is_evm_account(account_id.clone()) { + let currency = T::EvmAssetId::get(); + AccountCurrencyMap::::insert(account_id.clone(), currency); + currency + } else { + AccountCurrencyMap::::remove(account_id.clone()); + T::NativeAssetId::get() + }; + + Self::deposit_event(Event::CurrencySet { + account_id, + asset_id: currency, + }); + + Ok(()) + } + + /// Dispatch EVM permit. + /// The main purpose of this function is to allow EVM accounts to pay for the transaction fee in non-native currency + /// by allowing them to self-dispatch pre-signed permit. + /// The EVM fee is paid in the currency set for the account. + #[pallet::call_index(4)] + #[pallet::weight( + ::EvmPermit::dispatch_weight(*gas_limit) + )] + pub fn dispatch_permit( + origin: OriginFor, + from: H160, + to: H160, + value: U256, + data: Vec, + gas_limit: u64, + deadline: U256, + v: u8, + r: H256, + s: H256, + ) -> DispatchResultWithPostInfo { + ensure_none(origin)?; + + // dispatch permit should never return error. + // validate_unsigned should prevent the transaction getting to this point in case of invalid permit. + // In case of any error, we call error handler ( which should pause this transaction) and return ok. + + if T::EvmPermit::validate_permit(from, to, data.clone(), value, gas_limit, deadline, v, r, s).is_err() { + T::EvmPermit::on_dispatch_permit_error(); + return Ok(PostDispatchInfo::default()); + }; + + let (gas_price, _) = T::EvmPermit::gas_price(); + + // Set fee currency for the evm dispatch + let account_id = T::InspectEvmAccounts::account_id(from); + + let encoded = data.clone(); + let mut encoded_extrinsic = encoded.as_slice(); + let maybe_call: Result<::RuntimeCall, _> = + DecodeLimit::decode_all_with_depth_limit(32, &mut encoded_extrinsic); + + let currency = if let Ok(call) = maybe_call { + T::TryCallCurrency::try_convert(&call).unwrap_or_else(|_| Pallet::::account_currency(&account_id)) + } else { + Pallet::::account_currency(&account_id) + }; + + TransactionCurrencyOverride::::insert(account_id.clone(), currency); + + let result = T::EvmPermit::dispatch_permit(from, to, data, value, gas_limit, gas_price, None, None, vec![]) + .unwrap_or_else(|e| { + // In case of runner error, account has not been charged, so we need to call error handler to pause dispatch error + if e.error == Error::::EvmPermitRunnerError.into() { + T::EvmPermit::on_dispatch_permit_error(); + } + e.post_info + }); + + TransactionCurrencyOverride::::remove(account_id.clone()); + + Ok(result) + } + } + + #[pallet::validate_unsigned] + impl ValidateUnsigned for Pallet + where + AssetIdOf: Into, + { + type Call = Call; + + fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { + match call { + Call::dispatch_permit { + from, + to, + value, + data, + gas_limit, + deadline, + v, + r, + s, + } => { + // We need to wrap this as separate tx, and since we also "dry-run" the dispatch, + // we need to rollback the changes if any + let result = with_transaction::<(), DispatchError, _>(|| { + // First verify signature + let result = T::EvmPermit::validate_permit( + *from, + *to, + data.clone(), + *value, + *gas_limit, + *deadline, + *v, + *r, + *s, + ); + if let Some(error_res) = result.err() { + return TransactionOutcome::Rollback(Err(error_res)); + } + + // Set fee currency for the evm dispatch + let account_id = T::InspectEvmAccounts::account_id(*from); + + let encoded = data.clone(); + let mut encoded_extrinsic = encoded.as_slice(); + let maybe_call: Result<::RuntimeCall, _> = + DecodeLimit::decode_all_with_depth_limit(32, &mut encoded_extrinsic); + + let currency = if let Ok(call) = maybe_call { + T::TryCallCurrency::try_convert(&call) + .unwrap_or_else(|_| crate::pallet::Pallet::::account_currency(&account_id)) + } else { + Pallet::::account_currency(&account_id) + }; + + TransactionCurrencyOverride::::insert(account_id.clone(), currency); + + let (gas_price, _) = T::EvmPermit::gas_price(); + + let result = T::EvmPermit::dispatch_permit( + *from, + *to, + data.clone(), + *value, + *gas_limit, + gas_price, + None, + None, + vec![], + ); + TransactionCurrencyOverride::::remove(&account_id); + match result { + Ok(_post_info) => TransactionOutcome::Rollback(Ok(())), + Err(e) => TransactionOutcome::Rollback(Err(e.error)), + } + }); + let nonce = T::EvmPermit::permit_nonce(*from); + match result { + Ok(()) => ValidTransaction::with_tag_prefix("EVMPermit") + .and_provides((nonce, from)) + .priority(0) + .longevity(64) + .propagate(true) + .build(), + Err(e) => { + let error_number = match e { + DispatchError::Module(ModuleError { error, .. }) => error[0], + _ => 0, // this case should never happen because an Error is always converted to DispatchError::Module(ModuleError) + }; + InvalidTransaction::Custom(error_number).into() + } + } + } + _ => InvalidTransaction::Call.into(), + } + } + } +} + +impl Pallet { + pub fn account_currency(who: &T::AccountId) -> AssetIdOf + where + BalanceOf: FixedPointOperand, + { + Pallet::::get_currency(who).unwrap_or_else(T::NativeAssetId::get) + } + + fn get_currency_price(currency: AssetIdOf) -> Option + where + BalanceOf: FixedPointOperand, + { + if let Some(price) = Self::price(currency) { + Some(price) + } else { + // If not loaded in on_init, let's try first the spot price provider again + // This is unlikely scenario as the price would be retrieved in on_init for each block + let maybe_price = Self::get_oracle_price(currency, T::NativeAssetId::get()); + + if let Some(price) = maybe_price { + Some(price) + } else { + Self::currencies(currency) + } + } + } + + fn get_oracle_price( + asset_id: >::CurrencyId, + native_asset: >::CurrencyId, + ) -> Option { + let on_chain_route = T::RouteProvider::get_route(AssetPair::new(asset_id, native_asset)); + + T::OraclePriceProvider::price(&on_chain_route, OraclePeriod::Short) + .map(|ratio| FixedU128::from_rational(ratio.n, ratio.d)) + } +} + +fn convert_fee_with_price(fee: B, price: FixedU128) -> Option +where + B: FixedPointOperand + Ord + One, +{ + // Make sure that the fee is never less than 1 + price.checked_mul_int(fee).map(|f| f.max(One::one())) +} + +/// Deposits all fees to some account +pub struct DepositAll(PhantomData); + +impl DepositFee, BalanceOf> for DepositAll { + fn deposit_fee(who: &T::AccountId, currency: AssetIdOf, amount: BalanceOf) -> DispatchResult { + ::Currencies::deposit(currency, who, amount)?; + Ok(()) + } +} + +/// Implements the transaction payment for native as well as non-native currencies +pub struct TransferFees(PhantomData<(T, MC, DF, FR)>); + +impl OnChargeTransaction for TransferFees +where + T: Config + pallet_utility::Config, + MC: MultiCurrency<::AccountId>, + AssetIdOf: Into, + MC::Balance: FixedPointOperand, + FR: Get, + DF: DepositFee, + ::RuntimeCall: IsSubType> + IsSubType>, + ::RuntimeCall: IsSubType>, + BalanceOf: FixedPointOperand, + BalanceOf: From, +{ + type LiquidityInfo = Option, Price>>; + type Balance = ::AccountId>>::Balance; + + /// Withdraw the predicted fee from the transaction origin. + /// + /// Note: The `fee` already includes the `tip`. + fn withdraw_fee( + who: &T::AccountId, + call: &::RuntimeCall, + _info: &DispatchInfoOf<::RuntimeCall>, + fee: Self::Balance, + _tip: Self::Balance, + ) -> Result { + if fee.is_zero() { + return Ok(None); + } + + let currency = Self::resolve_currency_from_call(who, call); + + let (converted_fee, currency, price) = if T::SwappablePaymentAssetSupport::is_transaction_fee_currency(currency) + { + let price = Pallet::::get_currency_price(currency) + .ok_or(TransactionValidityError::Invalid(InvalidTransaction::Payment))?; + + let converted_fee = convert_fee_with_price(fee, price) + .ok_or(TransactionValidityError::Invalid(InvalidTransaction::Payment))?; + (converted_fee, currency, price) + } else { + //In case of insufficient asset we buy DOT with insufficient asset, and using that DOT and amount as fee currency + let dot_hdx_price = Pallet::::get_currency_price(T::PolkadotNativeAssetId::get()) + .ok_or(TransactionValidityError::Invalid(InvalidTransaction::Payment))?; + + let fee_in_dot = convert_fee_with_price(fee, dot_hdx_price) + .ok_or(TransactionValidityError::Invalid(InvalidTransaction::Payment))?; + + let amount_in = T::SwappablePaymentAssetSupport::calculate_in_given_out( + currency, + T::PolkadotNativeAssetId::get(), + fee_in_dot.into(), + ) + .map_err(|_| TransactionValidityError::Invalid(InvalidTransaction::Payment))?; + let pool_fee = T::SwappablePaymentAssetSupport::calculate_fee_amount(amount_in) + .map_err(|_| TransactionValidityError::Invalid(InvalidTransaction::Payment))?; + let max_limit = amount_in.saturating_add(pool_fee); + + T::SwappablePaymentAssetSupport::buy( + who, + currency, + T::PolkadotNativeAssetId::get(), + fee_in_dot.into(), + max_limit, + who, + ) + .map_err(|_| TransactionValidityError::Invalid(InvalidTransaction::Payment))?; + + (fee_in_dot, T::PolkadotNativeAssetId::get(), dot_hdx_price) + }; + + match MC::withdraw(currency.into(), who, converted_fee, ExistenceRequirement::AllowDeath) { + Ok(()) => { + if currency == T::NativeAssetId::get() { + Ok(Some(PaymentInfo::Native(fee))) + } else { + Ok(Some(PaymentInfo::NonNative(converted_fee, currency, price))) + } + } + Err(_) => Err(InvalidTransaction::Payment.into()), + } + } + + /// Since the predicted fee might have been too high, parts of the fee may + /// be refunded. + /// + /// Note: The `fee` already includes the `tip`. + fn correct_and_deposit_fee( + who: &T::AccountId, + _dispatch_info: &DispatchInfoOf<::RuntimeCall>, + _post_info: &PostDispatchInfoOf<::RuntimeCall>, + corrected_fee: Self::Balance, + tip: Self::Balance, + already_withdrawn: Self::LiquidityInfo, + ) -> Result<(), TransactionValidityError> { + let fee_receiver = FR::get(); + + if let Some(paid) = already_withdrawn { + // Calculate how much refund we should return + let (currency, refund, fee, tip) = match paid { + PaymentInfo::Native(paid_fee) => ( + T::NativeAssetId::get().into(), + paid_fee.saturating_sub(corrected_fee), + corrected_fee.saturating_sub(tip), + tip, + ), + PaymentInfo::NonNative(paid_fee, currency, price) => { + // calculate corrected_fee in the non-native currency + let converted_corrected_fee = convert_fee_with_price(corrected_fee, price) + .ok_or(TransactionValidityError::Invalid(InvalidTransaction::Payment))?; + let refund = paid_fee.saturating_sub(converted_corrected_fee); + let converted_tip = price + .checked_mul_int(tip) + .ok_or(TransactionValidityError::Invalid(InvalidTransaction::Payment))?; + ( + currency.into(), + refund, + converted_corrected_fee.saturating_sub(converted_tip), + converted_tip, + ) + } + }; + + // refund to the account that paid the fees + MC::deposit(currency, who, refund) + .map_err(|_| TransactionValidityError::Invalid(InvalidTransaction::Payment))?; + + // deposit the fee + DF::deposit_fee(&fee_receiver, currency, fee + tip) + .map_err(|_| TransactionValidityError::Invalid(InvalidTransaction::Payment))?; + } + + Ok(()) + } + + fn can_withdraw_fee( + who: &T::AccountId, + call: &::RuntimeCall, + _info: &DispatchInfoOf<::RuntimeCall>, + fee: Self::Balance, + _tip: Self::Balance, + ) -> Result<(), TransactionValidityError> { + if fee.is_zero() { + return Ok(()); + } + + let currency = Self::resolve_currency_from_call(who, call); + + MC::ensure_can_withdraw(currency.into(), who, fee).map_err(|_| InvalidTransaction::Payment.into()) + } + + #[cfg(feature = "runtime-benchmarks")] + fn endow_account(who: &T::AccountId, amount: Self::Balance) { + let currency = Pallet::::account_currency(who); + let _ = MC::deposit(currency.into(), who, amount); + } + + #[cfg(feature = "runtime-benchmarks")] + fn minimum_balance() -> Self::Balance { + // Without any context, return native asset's minimum balance + MC::minimum_balance(T::NativeAssetId::get().into()) + } +} + +// use frame_support::dispatch::IsSubType; + +impl TransferFees +where + T: Config + pallet_utility::Config, + MC: MultiCurrency<::AccountId>, + AssetIdOf: Into, + ::RuntimeCall: IsSubType> + IsSubType>, + ::RuntimeCall: IsSubType>, +{ + fn resolve_currency_from_call(who: &T::AccountId, call: &::RuntimeCall) -> AssetIdOf { + if let Some(Call::set_currency { currency }) = call.is_sub_type() { + *currency + } else if let Some(pallet_utility::pallet::Call::batch { calls }) + | Some(pallet_utility::pallet::Call::batch_all { calls }) + | Some(pallet_utility::pallet::Call::force_batch { calls }) = call.is_sub_type() + { + match calls.first() { + Some(first_call) => match first_call.is_sub_type() { + Some(Call::set_currency { currency }) => *currency, + _ => Pallet::::account_currency(who), + }, + None => Pallet::::account_currency(who), + } + } else { + Pallet::::account_currency(who) + } + } +} + +/// We provide an oracle for the price of all currencies accepted as fee payment. +/// In the else statement, first we try to get the price from cache, otherwise we calculate it +/// The price calculation based on onchain-route is mainly used by EVM dry run as in the dry run we dont have storage filled with prices, so calculation is needed +impl NativePriceOracle, Price> for Pallet { + fn price(currency: AssetIdOf) -> Option { + if currency == T::NativeAssetId::get() { + Some(Price::one()) + } else { + Pallet::::currency_price(currency).or_else(|| Self::get_oracle_price(currency, T::NativeAssetId::get())) + } + } +} + +/// Type to automatically add a fee currency for an account on account creation. +pub struct AddTxAssetOnAccount(PhantomData); +impl Happened<(T::AccountId, AssetIdOf)> for AddTxAssetOnAccount { + fn happened((who, currency): &(T::AccountId, AssetIdOf)) { + if !AccountCurrencyMap::::contains_key(who) + && AcceptedCurrencies::::contains_key(currency) + && T::Currencies::total_balance(T::NativeAssetId::get(), who).is_zero() + { + AccountCurrencyMap::::insert(who, currency); + } + } +} + +/// Type to automatically remove the fee currency for an account on account deletion. +/// +/// Note: The fee currency is only removed if the system account is gone or the account +/// corresponding to the fee currency is empty. +pub struct RemoveTxAssetOnKilled(PhantomData); +impl Happened<(T::AccountId, AssetIdOf)> for RemoveTxAssetOnKilled { + fn happened((who, _currency): &(T::AccountId, AssetIdOf)) { + if !frame_system::Pallet::::account_exists(who) { + AccountCurrencyMap::::remove(who); + } else if let Some(currency) = AccountCurrencyMap::::get(who) { + if T::Currencies::total_balance(currency, who).is_zero() { + AccountCurrencyMap::::remove(who); + } + } + } +} + +impl Contains> for Pallet { + fn contains(currency: &AssetIdOf) -> bool { + AcceptedCurrencies::::contains_key(currency) + } +} + +impl GetByKey, Option> for Pallet { + fn get(k: &AssetIdOf) -> Option { + AcceptedCurrencyPrice::::get(k) + } +} + +/// Provides account's fee payment asset or default fee asset ( Native asset ) +impl AccountFeeCurrency for Pallet { + type AssetId = AssetIdOf; + + fn get(who: &T::AccountId) -> Self::AssetId { + Pallet::::account_currency(who) + } +} + +pub struct TryCallCurrency(PhantomData); +impl TryConvert<&::RuntimeCall, AssetIdOf> for TryCallCurrency +where + T: Config + pallet_utility::Config, + ::RuntimeCall: IsSubType> + IsSubType>, + ::RuntimeCall: IsSubType>, +{ + fn try_convert( + call: &::RuntimeCall, + ) -> Result, &::RuntimeCall> { + if let Some(crate::pallet::Call::set_currency { currency }) = call.is_sub_type() { + Ok(*currency) + } else if let Some(pallet_utility::pallet::Call::batch { calls }) + | Some(pallet_utility::pallet::Call::batch_all { calls }) + | Some(pallet_utility::pallet::Call::force_batch { calls }) = call.is_sub_type() + { + // `calls` can be empty Vec + match calls.first() { + Some(first_call) => match first_call.is_sub_type() { + Some(crate::pallet::Call::set_currency { currency }) => Ok(*currency), + _ => Err(call), + }, + _ => Err(call), + } + } else { + Err(call) + } + } +} + +pub struct NoCallCurrency(PhantomData); +impl TryConvert<&::RuntimeCall, AssetIdOf> for NoCallCurrency { + fn try_convert( + call: &::RuntimeCall, + ) -> Result, &::RuntimeCall> { + Err(call) + } +} diff --git a/pallets/transaction-multi-payment/src/mock.rs b/pallets/transaction-multi-payment/src/mock.rs new file mode 100644 index 00000000000..69214e5728a --- /dev/null +++ b/pallets/transaction-multi-payment/src/mock.rs @@ -0,0 +1,613 @@ +// This file is part of Basilisk-node. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::*; +pub use crate as multi_payment; +use crate::{Config, TransferFees}; +use basilisk_math::ratio::Ratio; + +use basilisk_traits::{ + oracle::{OraclePeriod, PriceOracle}, + router::{RouteProvider, Trade}, +}; +use frame_support::dispatch::{DispatchResultWithPostInfo, PostDispatchInfo}; +use frame_support::{ + dispatch::DispatchClass, + parameter_types, + sp_runtime::{ + traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Verify}, + BuildStorage, MultiSignature, Perbill, + }, + traits::{Everything, Get, Nothing}, + weights::{IdentityFee, Weight}, +}; +use frame_system as system; +use hydradx_traits::AssetKind; +use orml_traits::{currency::MutationHooks, parameter_type_with_key}; +use pallet_currencies::{BasicCurrencyAdapter, MockBoundErc20, MockErc20Currency}; +use sp_core::{H160, H256, U256}; +use sp_runtime::DispatchError; +use sp_std::cell::RefCell; + +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; +pub type Balance = u128; +pub type AssetId = u32; +pub type Amount = i128; + +pub const INITIAL_BALANCE: Balance = 1_000_000_000_000_000u128; + +pub const ALICE: AccountId = AccountId::new([1; 32]); +pub const BOB: AccountId = AccountId::new([2; 32]); +pub const CHARLIE: AccountId = AccountId::new([3; 32]); +pub const DAVE: AccountId = AccountId::new([4; 32]); +pub const FEE_RECEIVER: AccountId = AccountId::new([5; 32]); + +pub const HDX: AssetId = 0; +pub const WETH: AssetId = 20; +pub const DOT: AssetId = 5; +pub const SUPPORTED_CURRENCY: AssetId = 2000; +pub const SUPPORTED_CURRENCY_WITH_PRICE: AssetId = 3000; +pub const UNSUPPORTED_CURRENCY: AssetId = 4000; +pub const INSUFFICIENT_CURRENCY: AssetId = 10000; +pub const SUPPORTED_CURRENCY_NO_BALANCE: AssetId = 5000; // Used for insufficient balance testing +pub const HIGH_ED_CURRENCY: AssetId = 6000; +pub const HIGH_VALUE_CURRENCY: AssetId = 7000; + +pub const HIGH_ED: Balance = 5; + +const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); +const MAX_BLOCK_WEIGHT: Weight = Weight::from_parts(1024, 0); + +thread_local! { + static EXTRINSIC_BASE_WEIGHT: RefCell = const { RefCell::new(Weight::zero()) }; +} + +pub struct ExtrinsicBaseWeight; +impl Get for ExtrinsicBaseWeight { + fn get() -> Weight { + EXTRINSIC_BASE_WEIGHT.with(|v| *v.borrow()) + } +} + +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Test + { + System: frame_system, + PaymentPallet: multi_payment, + TransactionPayment: pallet_transaction_payment, + Balances: pallet_balances, + Currencies: pallet_currencies, + Tokens: orml_tokens, + Utility: pallet_utility, + } + +); + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 63; + + pub const HdxAssetId: u32 = HDX; + pub const EvmAssetId: u32 = WETH; + pub const DotAssetId: u32 = DOT; + pub const ExistentialDeposit: u128 = 2; + pub const MaxLocks: u32 = 50; + pub const RegistryStringLimit: u32 = 100; + pub const FeeReceiver: AccountId = FEE_RECEIVER; + + pub RuntimeBlockWeights: system::limits::BlockWeights = system::limits::BlockWeights::builder() + .base_block(Weight::zero()) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = ExtrinsicBaseWeight::get(); + }) + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = (NORMAL_DISPATCH_RATIO * MAX_BLOCK_WEIGHT).set_proof_size(u64::MAX).into(); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = (NORMAL_DISPATCH_RATIO * MAX_BLOCK_WEIGHT).set_proof_size(u64::MAX).into(); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = MAX_BLOCK_WEIGHT.set_proof_size(u64::MAX).into(); + }) + .avg_block_initialization(Perbill::from_percent(0)) + .build_or_panic(); + + pub ExchangeFeeRate: (u32, u32) = (2, 1_000); +} + +impl system::Config for Test { + type BaseCallFilter = Everything; + type BlockWeights = RuntimeBlockWeights; + type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; + type Nonce = u64; + type Block = Block; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; + type SingleBlockMigrations = (); + type MultiBlockMigrator = (); + type PreInherents = (); + type PostInherents = (); + type PostTransactions = (); + type ExtensionsWeightInfo = (); +} + +impl Config for Test { + type RuntimeEvent = RuntimeEvent; + type AcceptedCurrencyOrigin = frame_system::EnsureRoot; + type Currencies = Currencies; + type RouteProvider = DefaultRouteProvider; + type OraclePriceProvider = PriceProviderMock; + type WeightInfo = (); + type WeightToFee = IdentityFee; + type NativeAssetId = HdxAssetId; + type PolkadotNativeAssetId = DotAssetId; + type EvmAssetId = EvmAssetId; + type InspectEvmAccounts = EvmAccountsMock; + type EvmPermit = PermitDispatchHandler; + type TryCallCurrency<'a> = NoCallCurrency; + type SwappablePaymentAssetSupport = MockedInsufficientAssetSupport; +} + +pub struct MockedInsufficientAssetSupport; + +impl InspectTransactionFeeCurrency for MockedInsufficientAssetSupport { + fn is_transaction_fee_currency(_asset: AssetId) -> bool { + true + } +} + +impl SwappablePaymentAssetTrader for MockedInsufficientAssetSupport { + fn is_trade_supported(_from: AssetId, _into: AssetId) -> bool { + unimplemented!() + } + + fn buy( + _origin: &AccountId, + _asset_in: AssetId, + _asset_out: AssetId, + _amount: Balance, + _max_limit: Balance, + _dest: &AccountId, + ) -> DispatchResult { + unimplemented!() + } + + fn calculate_fee_amount(_swap_amount: Balance) -> Result { + unimplemented!() + } + + fn calculate_in_given_out( + _insuff_asset_id: AssetId, + _asset_out: AssetId, + _asset_out_amount: Balance, + ) -> Result { + unimplemented!() + } + + fn calculate_out_given_in( + _asset_in: AssetId, + _asset_out: AssetId, + _asset_in_amount: Balance, + ) -> Result { + unimplemented!() + } +} + +pub struct DummyRegistry(sp_std::marker::PhantomData); + +impl hydradx_traits::registry::Inspect for DummyRegistry { + type AssetId = AssetId; + type Location = u8; + + fn asset_type(_id: Self::AssetId) -> Option { + unimplemented!() + } + + fn is_sufficient(id: Self::AssetId) -> bool { + id < INSUFFICIENT_CURRENCY + } + + fn decimals(_id: Self::AssetId) -> Option { + unimplemented!() + } + + fn exists(_asset_id: AssetId) -> bool { + true + } + + fn is_banned(_id: Self::AssetId) -> bool { + unimplemented!() + } + + fn asset_name(_id: Self::AssetId) -> Option> { + unimplemented!() + } + + fn asset_symbol(_id: Self::AssetId) -> Option> { + unimplemented!() + } + + fn existential_deposit(_id: Self::AssetId) -> Option { + unimplemented!() + } +} +pub struct DefaultRouteProvider; + +impl RouteProvider for DefaultRouteProvider {} + +pub struct EvmAccountsMock; +impl hydradx_traits::evm::InspectEvmAccounts for EvmAccountsMock { + fn is_evm_account(_account_id: AccountId) -> bool { + false + } + + fn evm_address(_account_id: &impl AsRef<[u8; 32]>) -> sp_core::H160 { + sp_core::H160::default() + } + + fn truncated_account_id(_evm_address: sp_core::H160) -> AccountId { + AccountId::from([0u8; 32]) + } + + fn bound_account_id(_evm_address: sp_core::H160) -> Option { + None + } + + fn account_id(_evm_address: sp_core::H160) -> AccountId { + AccountId::from([0u8; 32]) + } + + fn can_deploy_contracts(_evm_address: sp_core::H160) -> bool { + false + } + + fn is_approved_contract(_address: sp_core::H160) -> bool { + false + } +} + +pub struct PriceProviderMock {} + +impl PriceOracle for PriceProviderMock { + type Price = Ratio; + + fn price(route: &[Trade], _period: OraclePeriod) -> Option { + let asset_a = route.first().unwrap().asset_in; + let asset_b = route.first().unwrap().asset_out; + match (asset_a, asset_b) { + (SUPPORTED_CURRENCY_WITH_PRICE, HDX) => Some(Ratio::new(1, 10)), + _ => None, + } + } +} +impl pallet_balances::Config for Test { + type MaxLocks = MaxLocks; + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type MaxReserves = (); + type ReserveIdentifier = (); + type FreezeIdentifier = (); + type MaxFreezes = (); + type RuntimeHoldReason = (); + type RuntimeFreezeReason = (); + type DoneSlashHandler = (); +} + +impl pallet_transaction_payment::Config for Test { + type RuntimeEvent = RuntimeEvent; + type OnChargeTransaction = TransferFees, FeeReceiver>; + type LengthToFee = IdentityFee; + type OperationalFeeMultiplier = (); + type WeightToFee = IdentityFee; + type FeeMultiplierUpdate = (); + type WeightInfo = (); +} + +parameter_type_with_key! { + pub ExistentialDeposits: |currency_id: AssetId| -> Balance { + match *currency_id { + HIGH_ED_CURRENCY => HIGH_ED, + HIGH_VALUE_CURRENCY => 1u128, + _ => 2u128 + } + }; +} + +parameter_types! { + pub const MaxReserves: u32 = 50; +} + +pub struct CurrencyHooks; +impl MutationHooks for CurrencyHooks { + type OnDust = (); + type OnSlash = (); + type PreDeposit = (); + type PostDeposit = (); + type PreTransfer = (); + type PostTransfer = (); + type OnNewTokenAccount = AddTxAssetOnAccount; + type OnKilledTokenAccount = RemoveTxAssetOnKilled; +} + +impl orml_tokens::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type Amount = Amount; + type CurrencyId = AssetId; + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; + type MaxLocks = (); + type DustRemovalWhitelist = Nothing; + type ReserveIdentifier = (); + type MaxReserves = MaxReserves; + type CurrencyHooks = CurrencyHooks; +} + +parameter_types! { + pub CurrenciesReserveAccount: AccountId = AccountId::from([1u8; 32]); +} + +impl pallet_currencies::Config for Test { + type RuntimeEvent = RuntimeEvent; + type MultiCurrency = Tokens; + type NativeCurrency = BasicCurrencyAdapter; + type Erc20Currency = MockErc20Currency; + type BoundErc20 = MockBoundErc20; + type GetNativeCurrencyId = HdxAssetId; + type WeightInfo = (); + type ReserveAccount = CurrenciesReserveAccount; +} + +impl pallet_utility::Config for Test { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PalletsOrigin = OriginCaller; + type BatchHook = (); + type WeightInfo = (); +} + +pub struct ExtBuilder { + base_weight: Weight, + native_balances: Vec<(AccountId, Balance)>, + endowed_accounts: Vec<(AccountId, AssetId, Balance)>, + account_currencies: Vec<(AccountId, AssetId)>, +} + +impl Default for ExtBuilder { + fn default() -> Self { + Self { + base_weight: Weight::zero(), + native_balances: vec![(ALICE, INITIAL_BALANCE)], + endowed_accounts: vec![ + (ALICE, HDX, INITIAL_BALANCE), + (ALICE, SUPPORTED_CURRENCY, INITIAL_BALANCE), // used for fallback price test + (ALICE, SUPPORTED_CURRENCY_WITH_PRICE, INITIAL_BALANCE), + ], + + account_currencies: vec![], + } + } +} + +impl ExtBuilder { + pub fn base_weight(mut self, base_weight: u64) -> Self { + self.base_weight = Weight::from_parts(base_weight, 0); + self + } + pub fn account_native_balance(mut self, account: AccountId, balance: Balance) -> Self { + self.native_balances.push((account, balance)); + self + } + pub fn account_tokens(mut self, account: AccountId, asset: AssetId, balance: Balance) -> Self { + self.endowed_accounts.push((account, asset, balance)); + self + } + pub fn with_currencies(mut self, account_currencies: Vec<(AccountId, AssetId)>) -> Self { + self.account_currencies = account_currencies; + self + } + fn set_constants(&self) { + EXTRINSIC_BASE_WEIGHT.with(|v| *v.borrow_mut() = self.base_weight); + } + pub fn build(self) -> sp_io::TestExternalities { + use frame_support::traits::OnInitialize; + + self.set_constants(); + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + + pallet_balances::GenesisConfig:: { + balances: self.native_balances, + dev_accounts: Default::default(), + } + .assimilate_storage(&mut t) + .unwrap(); + + orml_tokens::GenesisConfig:: { + balances: self.endowed_accounts, + } + .assimilate_storage(&mut t) + .unwrap(); + + let core_asset: u32 = 0; + let mut buf: Vec = Vec::new(); + + buf.extend_from_slice(&core_asset.to_le_bytes()); + buf.extend_from_slice(b"HDT"); + buf.extend_from_slice(&core_asset.to_le_bytes()); + + crate::GenesisConfig:: { + currencies: vec![ + (SUPPORTED_CURRENCY_NO_BALANCE, Price::from(1)), + (SUPPORTED_CURRENCY, Price::from_float(1.5)), + (SUPPORTED_CURRENCY_WITH_PRICE, Price::from_float(0.5)), + (HIGH_ED_CURRENCY, Price::from(3)), + (HIGH_VALUE_CURRENCY, Price::from_inner(100)), + ], + account_currencies: self.account_currencies, + } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext: sp_io::TestExternalities = t.into(); + ext.execute_with(|| { + System::set_block_number(1); + // Make sure the prices are up-to-date. + PaymentPallet::on_initialize(1); + }); + ext + } +} + +pub fn expect_events(e: Vec) { + test_utils::expect_events::(e); +} + +#[derive(Clone, Debug, PartialEq)] +pub struct PermitDispatchData { + pub source: H160, + pub target: H160, + pub input: Vec, + pub value: U256, + pub gas_limit: u64, + pub max_fee_per_gas: U256, + pub max_priority_fee_per_gas: Option, + pub nonce: Option, + pub access_list: Vec<(H160, Vec)>, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct ValidationData { + pub source: H160, + pub target: H160, + pub input: Vec, + pub value: U256, + pub gas_limit: u64, + pub deadline: U256, + pub v: u8, + pub r: H256, + pub s: H256, +} + +thread_local! { + static PERMIT_VALIDATION: RefCell> = const { RefCell::new(vec![]) }; + static PERMIT_DISPATCH: RefCell> = const { RefCell::new(vec![]) }; +} + +pub struct PermitDispatchHandler; + +impl PermitDispatchHandler { + pub fn last_validation_call_data() -> ValidationData { + PERMIT_VALIDATION.with(|v| v.borrow().last().unwrap().clone()) + } + + pub fn last_dispatch_call_data() -> PermitDispatchData { + PERMIT_DISPATCH.with(|v| v.borrow().last().unwrap().clone()) + } +} + +impl EVMPermit for PermitDispatchHandler { + fn validate_permit( + source: H160, + target: H160, + input: Vec, + value: U256, + gas_limit: u64, + deadline: U256, + v: u8, + r: H256, + s: H256, + ) -> sp_runtime::DispatchResult { + let data = ValidationData { + source, + target, + input, + value, + gas_limit, + deadline, + v, + r, + s, + }; + PERMIT_VALIDATION.with(|v| v.borrow_mut().push(data)); + Ok(()) + } + + fn dispatch_permit( + source: H160, + target: H160, + input: Vec, + value: U256, + gas_limit: u64, + max_fee_per_gas: U256, + max_priority_fee_per_gas: Option, + nonce: Option, + access_list: Vec<(H160, Vec)>, + ) -> DispatchResultWithPostInfo { + let data = PermitDispatchData { + source, + target, + input, + value, + gas_limit, + max_fee_per_gas, + max_priority_fee_per_gas, + nonce, + access_list, + }; + PERMIT_DISPATCH.with(|v| v.borrow_mut().push(data)); + Ok(PostDispatchInfo::default()) + } + + fn gas_price() -> (U256, Weight) { + (U256::from(222u128), Weight::zero()) + } + + fn dispatch_weight(_gas_limit: u64) -> Weight { + todo!() + } + + fn permit_nonce(_account: H160) -> U256 { + U256::default() + } + + fn on_dispatch_permit_error() {} +} diff --git a/pallets/transaction-multi-payment/src/tests.rs b/pallets/transaction-multi-payment/src/tests.rs new file mode 100644 index 00000000000..c4d1ea76efb --- /dev/null +++ b/pallets/transaction-multi-payment/src/tests.rs @@ -0,0 +1,1310 @@ +// This file is part of Basilisk-node. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub use crate::{mock::*, Error}; +use crate::{AcceptedCurrencies, AcceptedCurrencyPrice, Event, Price}; + +use basilisk_traits::oracle::NativePriceOracle; +use frame_support::{ + assert_noop, assert_ok, + dispatch::{DispatchInfo, PostDispatchInfo}, + sp_runtime::traits::{BadOrigin, TransactionExtension}, + traits::{tokens::Precision, ExistenceRequirement, Hooks}, + weights::Weight, +}; +use orml_traits::MultiCurrency; +use pallet_balances::Call as BalancesCall; +use pallet_transaction_payment::ChargeTransactionPayment; +use sp_runtime::traits::DispatchTransaction; + +const CALL: &::RuntimeCall = + &RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: BOB, value: 69 }); + +#[test] +fn on_initialize_should_fill_storage_with_prices() { + // Arrange + ExtBuilder::default().build().execute_with(|| { + // Act + let current = System::block_number(); + PaymentPallet::on_finalize(current); + // the block number is not important here and can stay the same + PaymentPallet::on_initialize(current); + + // Assert + // verify that all accepted currencies have the price set + let iter = >::iter(); + for (asset_id, _) in iter { + assert!(>::contains_key(asset_id)); + } + + // fallback price + assert_eq!( + PaymentPallet::currency_price(SUPPORTED_CURRENCY), + Some(Price::from_float(1.5)) + ); + // price from the spot price provider + assert_eq!( + PaymentPallet::currency_price(SUPPORTED_CURRENCY_WITH_PRICE), + Some(Price::from_float(0.1)) + ); + // not supported + assert_eq!(PaymentPallet::currency_price(UNSUPPORTED_CURRENCY), None); + }); +} + +#[test] +fn on_finalize_should_remove_prices_from_storage() { + // Arrange + ExtBuilder::default().build().execute_with(|| { + let current = System::block_number(); + + // verify that the storage is not empty + assert_eq!( + PaymentPallet::currency_price(SUPPORTED_CURRENCY), + Some(Price::from_float(1.5)) + ); + + // Act + PaymentPallet::on_finalize(current); + + // Assert + let mut iter = >::iter_values(); + assert_eq!(iter.next(), None); + }); +} + +#[test] +fn set_unsupported_currency() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + PaymentPallet::set_currency(RuntimeOrigin::signed(BOB), UNSUPPORTED_CURRENCY), + Error::::UnsupportedCurrency + ); + + assert_eq!(PaymentPallet::get_currency(BOB), None); + }); +} + +#[test] +fn set_supported_currency_without_spot_price_should_charge_fee_in_correct_currency() { + ExtBuilder::default().base_weight(5).build().execute_with(|| { + let call = &RuntimeCall::PaymentPallet(crate::Call::set_currency { + currency: SUPPORTED_CURRENCY, + }); + + let len = 10; + let info = info_from_weight(Weight::from_parts(5, 0)); + + let pre = + ChargeTransactionPayment::::from(0).validate_and_prepare(Some(ALICE).into(), call, &info, len, 0); + assert!(pre.is_ok()); + + assert_eq!( + Currencies::free_balance(SUPPORTED_CURRENCY, &ALICE), + 999_999_999_999_970 + ); + + let (pre_data, _origin) = pre.unwrap(); + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &info, + &mut default_post_info(), + len, + &Ok(()) + )); + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &FEE_RECEIVER), 30); + }); +} + +#[test] +fn set_supported_currency_in_batch_should_charge_fee_in_correct_currency() { + // batch + ExtBuilder::default().base_weight(5).build().execute_with(|| { + let first_inner_call = RuntimeCall::PaymentPallet(crate::Call::set_currency { + currency: SUPPORTED_CURRENCY, + }); + let second_inner_call = RuntimeCall::System(frame_system::Call::remark { remark: vec![] }); + let call = RuntimeCall::Utility(pallet_utility::Call::batch { + calls: vec![first_inner_call, second_inner_call], + }); + + let len = 10; + let info = info_from_weight(Weight::from_parts(5, 0)); + + let pre = + ChargeTransactionPayment::::from(0).validate_and_prepare(Some(ALICE).into(), &call, &info, len, 0); + assert!(pre.is_ok()); + + assert_eq!( + Currencies::free_balance(SUPPORTED_CURRENCY, &ALICE), + 999_999_999_999_970 + ); + + let (pre_data, _origin) = pre.unwrap(); + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &info, + &mut default_post_info(), + len, + &Ok(()) + )); + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &FEE_RECEIVER), 30); + }); + + // batch_all + ExtBuilder::default().base_weight(5).build().execute_with(|| { + let first_inner_call = RuntimeCall::PaymentPallet(crate::Call::set_currency { + currency: SUPPORTED_CURRENCY, + }); + let second_inner_call = RuntimeCall::System(frame_system::Call::remark { remark: vec![] }); + let call = RuntimeCall::Utility(pallet_utility::Call::batch_all { + calls: vec![first_inner_call, second_inner_call], + }); + + let len = 10; + let info = info_from_weight(Weight::from_parts(5, 0)); + + let pre = + ChargeTransactionPayment::::from(0).validate_and_prepare(Some(ALICE).into(), &call, &info, len, 0); + assert!(pre.is_ok()); + + assert_eq!( + Currencies::free_balance(SUPPORTED_CURRENCY, &ALICE), + 999_999_999_999_970 + ); + + let (pre_data, _origin) = pre.unwrap(); + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &info, + &mut default_post_info(), + len, + &Ok(()) + )); + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &FEE_RECEIVER), 30); + }); + + // batch_all + ExtBuilder::default().base_weight(5).build().execute_with(|| { + let first_inner_call = RuntimeCall::PaymentPallet(crate::Call::set_currency { + currency: SUPPORTED_CURRENCY, + }); + let second_inner_call = RuntimeCall::System(frame_system::Call::remark { remark: vec![] }); + let call = RuntimeCall::Utility(pallet_utility::Call::force_batch { + calls: vec![first_inner_call, second_inner_call], + }); + + let len = 10; + let info = info_from_weight(Weight::from_parts(5, 0)); + + let pre = + ChargeTransactionPayment::::from(0).validate_and_prepare(Some(ALICE).into(), &call, &info, len, 0); + assert!(pre.is_ok()); + + assert_eq!( + Currencies::free_balance(SUPPORTED_CURRENCY, &ALICE), + 999_999_999_999_970 + ); + + let (pre_data, _origin) = pre.unwrap(); + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &info, + &mut default_post_info(), + len, + &Ok(()) + )); + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &FEE_RECEIVER), 30); + }); +} + +#[test] +fn set_supported_currency_in_batch_should_not_work_if_not_first_transaction() { + // batch + ExtBuilder::default().base_weight(5).build().execute_with(|| { + let first_inner_call = RuntimeCall::System(frame_system::Call::remark { remark: vec![] }); + let second_inner_call = RuntimeCall::PaymentPallet(crate::Call::set_currency { + currency: SUPPORTED_CURRENCY, + }); + let call = RuntimeCall::Utility(pallet_utility::Call::batch { + calls: vec![first_inner_call, second_inner_call], + }); + + let len = 10; + let info = info_from_weight(Weight::from_parts(5, 0)); + + let alice_initial_non_native_balance = Currencies::free_balance(SUPPORTED_CURRENCY, &ALICE); + + let pre = + ChargeTransactionPayment::::from(0).validate_and_prepare(Some(ALICE).into(), &call, &info, len, 0); + assert!(pre.is_ok()); + + assert_eq!(Currencies::free_balance(HDX, &ALICE), 999_999_999_999_980); + + let (pre_data, _origin) = pre.unwrap(); + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &info, + &mut default_post_info(), + len, + &Ok(()) + )); + assert_eq!(Currencies::free_balance(HDX, &FEE_RECEIVER), 20); + assert_eq!( + Currencies::free_balance(SUPPORTED_CURRENCY, &ALICE), + alice_initial_non_native_balance + ); + }); + + // batch_all + ExtBuilder::default().base_weight(5).build().execute_with(|| { + let first_inner_call = RuntimeCall::System(frame_system::Call::remark { remark: vec![] }); + let second_inner_call = RuntimeCall::PaymentPallet(crate::Call::set_currency { + currency: SUPPORTED_CURRENCY, + }); + let call = RuntimeCall::Utility(pallet_utility::Call::batch_all { + calls: vec![first_inner_call, second_inner_call], + }); + + let len = 10; + let info = info_from_weight(Weight::from_parts(5, 0)); + + let alice_initial_non_native_balance = Currencies::free_balance(SUPPORTED_CURRENCY, &ALICE); + + let pre = + ChargeTransactionPayment::::from(0).validate_and_prepare(Some(ALICE).into(), &call, &info, len, 0); + assert!(pre.is_ok()); + + assert_eq!(Currencies::free_balance(HDX, &ALICE), 999_999_999_999_980); + + let (pre_data, _origin) = pre.unwrap(); + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &info, + &mut default_post_info(), + len, + &Ok(()) + )); + assert_eq!(Currencies::free_balance(HDX, &FEE_RECEIVER), 20); + assert_eq!( + Currencies::free_balance(SUPPORTED_CURRENCY, &ALICE), + alice_initial_non_native_balance + ); + }); + + // batch_all + ExtBuilder::default().base_weight(5).build().execute_with(|| { + let first_inner_call = RuntimeCall::System(frame_system::Call::remark { remark: vec![] }); + let second_inner_call = RuntimeCall::PaymentPallet(crate::Call::set_currency { + currency: SUPPORTED_CURRENCY, + }); + let call = RuntimeCall::Utility(pallet_utility::Call::force_batch { + calls: vec![first_inner_call, second_inner_call], + }); + + let len = 10; + let info = info_from_weight(Weight::from_parts(5, 0)); + + let alice_initial_non_native_balance = Currencies::free_balance(SUPPORTED_CURRENCY, &ALICE); + + let pre = + ChargeTransactionPayment::::from(0).validate_and_prepare(Some(ALICE).into(), &call, &info, len, 0); + assert!(pre.is_ok()); + + assert_eq!(Currencies::free_balance(HDX, &ALICE), 999_999_999_999_980); + + let (pre_data, _origin) = pre.unwrap(); + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &info, + &mut default_post_info(), + len, + &Ok(()) + )); + assert_eq!(Currencies::free_balance(HDX, &FEE_RECEIVER), 20); + assert_eq!( + Currencies::free_balance(SUPPORTED_CURRENCY, &ALICE), + alice_initial_non_native_balance + ); + }); +} + +#[test] +fn set_supported_currency_with_spot_price_should_charge_fee_in_correct_currency() { + ExtBuilder::default().base_weight(5).build().execute_with(|| { + let call = &RuntimeCall::PaymentPallet(crate::Call::set_currency { + currency: SUPPORTED_CURRENCY_WITH_PRICE, + }); + + let len = 10; + let info = info_from_weight(Weight::from_parts(5, 0)); + + let pre = + ChargeTransactionPayment::::from(0).validate_and_prepare(Some(ALICE).into(), call, &info, len, 0); + assert!(pre.is_ok()); + + assert_eq!( + Currencies::free_balance(SUPPORTED_CURRENCY_WITH_PRICE, &ALICE), + 999_999_999_999_998 + ); + + let (pre_data, _origin) = pre.unwrap(); + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &info, + &mut default_post_info(), + len, + &Ok(()) + )); + assert_eq!( + Currencies::free_balance(SUPPORTED_CURRENCY_WITH_PRICE, &FEE_RECEIVER), + 2 + ); + }); +} + +#[test] +fn set_native_currency() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(PaymentPallet::set_currency(RuntimeOrigin::signed(ALICE), HDX),); + + assert_eq!(PaymentPallet::get_currency(ALICE), Some(HDX)); + }); +} + +#[test] +fn fee_payment_in_native_currency() { + ExtBuilder::default() + .base_weight(5) + .account_native_balance(CHARLIE, 100) + .build() + .execute_with(|| { + let len = 10; + let info = info_from_weight(Weight::from_parts(5, 0)); + + assert!(ChargeTransactionPayment::::from(0) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &info, len, 0) + .is_ok()); + + assert_eq!(Balances::free_balance(CHARLIE), 100 - 5 - 5 - 10); + }); +} + +#[test] +fn fee_payment_in_non_native_currency() { + ExtBuilder::default() + .base_weight(5) + .account_tokens(CHARLIE, SUPPORTED_CURRENCY_WITH_PRICE, 10_000) + .with_currencies(vec![(CHARLIE, SUPPORTED_CURRENCY_WITH_PRICE)]) + .build() + .execute_with(|| { + // Make sure Charlie ain't got a penny! + assert_eq!(Balances::free_balance(CHARLIE), 0); + + let len = 1000; + let info = info_from_weight(Weight::from_parts(5, 0)); + + assert_eq!(Tokens::free_balance(SUPPORTED_CURRENCY_WITH_PRICE, &CHARLIE), 10_000); + + assert!(ChargeTransactionPayment::::from(0) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &info, len, 0) + .is_ok()); + + //Native balance check - Charlie should be still broke! + assert_eq!(Balances::free_balance(CHARLIE), 0); + + assert_eq!(Tokens::free_balance(SUPPORTED_CURRENCY_WITH_PRICE, &CHARLIE), 9899); + }); +} + +#[test] +fn fee_payment_in_expensive_non_native_currency_should_be_non_zero() { + ExtBuilder::default() + .base_weight(5) + .account_tokens(BOB, HIGH_VALUE_CURRENCY, 10_000) + .with_currencies(vec![(BOB, HIGH_VALUE_CURRENCY)]) + .build() + .execute_with(|| { + let len = 100; + let info = info_from_weight(Weight::from_parts(5, 0)); + + assert_eq!(Tokens::free_balance(HIGH_VALUE_CURRENCY, &BOB), 10_000); + + let pre = ChargeTransactionPayment::::from(0) + .validate_and_prepare(Some(BOB).into(), CALL, &info, len, 0) + .unwrap(); + + // Bob should be charged at least 1 token + assert_eq!(Tokens::free_balance(HIGH_VALUE_CURRENCY, &BOB), 9999); + + let mut post_info = post_info_from_weight(Weight::from_parts(3, 0)); + let (pre_data, _origin) = pre; + assert!( + ChargeTransactionPayment::::post_dispatch(pre_data, &info, &mut post_info, len, &Ok(())).is_ok() + ); + // BOB should not be refunded in case he payed only 1 token + assert_eq!(Tokens::free_balance(HIGH_VALUE_CURRENCY, &BOB), 9999); + }); +} + +#[test] +fn fee_payment_non_native_insufficient_balance() { + ExtBuilder::default() + .base_weight(5) + .account_tokens(CHARLIE, SUPPORTED_CURRENCY, 100) + .with_currencies(vec![(CHARLIE, SUPPORTED_CURRENCY)]) + .build() + .execute_with(|| { + let len = 1000; + let info = info_from_weight(Weight::from_parts(5, 0)); + + assert!(ChargeTransactionPayment::::from(0) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &info, len, 0) + .is_err()); + + assert_eq!(Tokens::free_balance(SUPPORTED_CURRENCY, &CHARLIE), 100); + }); +} + +#[test] +fn add_new_accepted_currency() { + ExtBuilder::default().base_weight(5).build().execute_with(|| { + assert_ok!(PaymentPallet::add_currency( + RuntimeOrigin::root(), + 100, + Price::from_float(1.1) + )); + expect_events(vec![Event::CurrencyAdded { asset_id: 100 }.into()]); + + assert_eq!(PaymentPallet::currencies(100), Some(Price::from_float(1.1))); + assert_noop!( + PaymentPallet::add_currency(RuntimeOrigin::signed(ALICE), 1000, Price::from_float(1.2)), + BadOrigin + ); + assert_noop!( + PaymentPallet::add_currency(RuntimeOrigin::root(), 100, Price::from(10)), + Error::::AlreadyAccepted + ); + assert_eq!(PaymentPallet::currencies(100), Some(Price::from_float(1.1))); + }); +} + +#[test] +fn removed_accepted_currency() { + ExtBuilder::default().base_weight(5).build().execute_with(|| { + assert_ok!(PaymentPallet::add_currency(RuntimeOrigin::root(), 100, Price::from(3))); + assert_eq!(PaymentPallet::currencies(100), Some(Price::from(3))); + + assert_noop!( + PaymentPallet::remove_currency(RuntimeOrigin::signed(ALICE), 100), + BadOrigin + ); + + assert_noop!( + PaymentPallet::remove_currency(RuntimeOrigin::root(), 1000), + Error::::UnsupportedCurrency + ); + + assert_ok!(PaymentPallet::remove_currency(RuntimeOrigin::root(), 100)); + expect_events(vec![Event::CurrencyRemoved { asset_id: 100 }.into()]); + + assert_eq!(PaymentPallet::currencies(100), None); + + assert_noop!( + PaymentPallet::remove_currency(RuntimeOrigin::root(), 100), + Error::::UnsupportedCurrency + ); + }); +} + +#[test] +fn account_currency_works() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(PaymentPallet::account_currency(&ALICE), HDX); + + assert_ok!(PaymentPallet::set_currency( + RuntimeOrigin::signed(ALICE), + SUPPORTED_CURRENCY + )); + expect_events(vec![Event::CurrencySet { + account_id: ALICE, + asset_id: SUPPORTED_CURRENCY, + } + .into()]); + + assert_eq!(PaymentPallet::account_currency(&ALICE), SUPPORTED_CURRENCY); + + assert_ok!(PaymentPallet::set_currency(RuntimeOrigin::signed(ALICE), HDX)); + assert_eq!(PaymentPallet::account_currency(&ALICE), HDX); + }); +} + +/// create a transaction info struct from weight. Handy to avoid building the whole struct. +pub fn info_from_weight(w: Weight) -> DispatchInfo { + // pays_fee: Pays::Yes -- class: DispatchClass::Normal + DispatchInfo { + call_weight: w, + ..Default::default() + } +} + +fn post_info_from_weight(w: Weight) -> PostDispatchInfo { + PostDispatchInfo { + actual_weight: Some(w), + pays_fee: Default::default(), + } +} + +fn default_post_info() -> PostDispatchInfo { + PostDispatchInfo { + actual_weight: None, + pays_fee: Default::default(), + } +} + +#[test] +fn fee_should_be_transferred_when_paid_in_native_currency() { + // Arrange + ExtBuilder::default() + .account_native_balance(CHARLIE, 100) + .base_weight(5) + .build() + .execute_with(|| { + let len = 10; + let tip = 0; + let dispatch_info = info_from_weight(Weight::from_parts(15, 0)); + + // Act + let pre = ChargeTransactionPayment::::from(tip) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &dispatch_info, len, 0) + .unwrap(); + // Assert + + assert_eq!(Balances::free_balance(CHARLIE), 100 - 30); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 0); + + // Act + let (pre_data, _origin) = pre; + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &dispatch_info, + &mut default_post_info(), + len, + &Ok(()) + )); + // Assert + assert_eq!(Balances::free_balance(CHARLIE), 100 - 30); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 30); + }); +} + +#[test] +fn fee_should_be_withdrawn_when_paid_in_native_currency() { + // Arrange + ExtBuilder::default() + .account_native_balance(CHARLIE, 100) + .base_weight(5) + .build() + .execute_with(|| { + let len = 10; + let tip = 0; + let dispatch_info = info_from_weight(Weight::from_parts(15, 0)); + let previous_total_issuance = Balances::total_issuance(); + + // Act + let pre = ChargeTransactionPayment::::from(tip) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &dispatch_info, len, 0) + .unwrap(); + + // Assert + assert_eq!(Balances::free_balance(CHARLIE), 100 - 30); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 0); + + // Act + let (pre_data, _origin) = pre; + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &dispatch_info, + &mut default_post_info(), + len, + &Ok(()) + )); + // Assert + assert_eq!(Balances::free_balance(CHARLIE), 100 - 30); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 30); + assert_eq!(Balances::total_issuance(), previous_total_issuance); + }); +} + +#[test] +fn fee_should_be_transferred_when_paid_in_native_currency_work_with_tip() { + // Arrange + ExtBuilder::default() + .account_native_balance(CHARLIE, 100) + .base_weight(5) + .build() + .execute_with(|| { + let len = 10; + let tip = 5; + let dispatch_info = info_from_weight(Weight::from_parts(15, 0)); + let post_dispatch_info = post_info_from_weight(Weight::from_parts(10, 0)); + + // Act + let pre = ChargeTransactionPayment::::from(tip) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &dispatch_info, len, 0) + .unwrap(); + // Assert + + assert_eq!(Balances::free_balance(CHARLIE), 100 - 5 - 10 - 15 - tip); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 0); + + // Act + let (pre_data, _origin) = pre; + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &dispatch_info, + &mut post_dispatch_info.clone(), + len, + &Ok(()) + )); + + // Assert + assert_eq!(Balances::free_balance(CHARLIE), 100 - 5 - 10 - 10 - tip); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 30); + }); +} + +#[test] +fn fee_should_be_withdrawn_when_paid_in_native_currency_work_with_tip() { + // Arrange + ExtBuilder::default() + .account_native_balance(CHARLIE, 100) + .base_weight(5) + .build() + .execute_with(|| { + let len = 10; + let tip = 5; + let dispatch_info = info_from_weight(Weight::from_parts(15, 0)); + let post_dispatch_info = post_info_from_weight(Weight::from_parts(10, 0)); + let previous_total_issuance = Balances::total_issuance(); + + // Act + let pre = ChargeTransactionPayment::::from(tip) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &dispatch_info, len, 0) + .unwrap(); + + // Assert + assert_eq!(Balances::free_balance(CHARLIE), 100 - 5 - 10 - 15 - tip); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 0); + + // Act + let (pre_data, _origin) = pre; + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &dispatch_info, + &mut post_dispatch_info.clone(), + len, + &Ok(()) + )); + + // Assert + assert_eq!(Balances::free_balance(CHARLIE), 100 - 5 - 10 - 10 - tip); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 30); + assert_eq!(Balances::total_issuance(), previous_total_issuance); + }); +} + +#[test] +fn fee_should_be_transferred_when_paid_in_non_native_currency() { + // Arrange + ExtBuilder::default() + .with_currencies(vec![(CHARLIE, SUPPORTED_CURRENCY)]) + .account_tokens(CHARLIE, SUPPORTED_CURRENCY, 10_000) + .base_weight(5) + .build() + .execute_with(|| { + let len = 10; + let tip = 0; + let dispatch_info = info_from_weight(Weight::from_parts(15, 0)); + + // Act + let pre = ChargeTransactionPayment::::from(tip) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &dispatch_info, len, 0) + .unwrap(); + + // Assert + + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &CHARLIE), 10_000 - 45); + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &FeeReceiver::get()), 0); + assert_eq!(Balances::free_balance(CHARLIE), 0); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 0); + + // Act + let (pre_data, _origin) = pre; + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &dispatch_info, + &mut default_post_info(), + len, + &Ok(()) + )); + + // Assert + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &CHARLIE), 10_000 - 45); + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &FeeReceiver::get()), 45); + assert_eq!(Balances::free_balance(CHARLIE), 0); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 0); + }); +} + +#[test] +fn fee_should_be_withdrawn_when_paid_in_non_native_currency() { + // Arrange + ExtBuilder::default() + .with_currencies(vec![(CHARLIE, SUPPORTED_CURRENCY)]) + .account_tokens(CHARLIE, SUPPORTED_CURRENCY, 10_000) + .base_weight(5) + .build() + .execute_with(|| { + let len = 10; + let tip = 0; + let dispatch_info = info_from_weight(Weight::from_parts(15, 0)); + let previous_total_issuance = Tokens::total_issuance(SUPPORTED_CURRENCY); + + // Act + let pre = ChargeTransactionPayment::::from(tip) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &dispatch_info, len, 0) + .unwrap(); + + // Assert + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &CHARLIE), 10_000 - 45); + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &FeeReceiver::get()), 0); + assert_eq!(Balances::free_balance(CHARLIE), 0); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 0); + + // Act + let (pre_data, _origin) = pre; + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &dispatch_info, + &mut default_post_info(), + len, + &Ok(()) + )); + + // Assert + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &CHARLIE), 10_000 - 45); + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &FeeReceiver::get()), 45); + assert_eq!(Balances::free_balance(CHARLIE), 0); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 0); + assert_eq!(Tokens::total_issuance(SUPPORTED_CURRENCY), previous_total_issuance); + }); +} + +#[test] +fn fee_should_be_transferred_when_paid_in_non_native_currency_with_tip() { + // Arrange + ExtBuilder::default() + .with_currencies(vec![(CHARLIE, SUPPORTED_CURRENCY)]) + .account_tokens(CHARLIE, SUPPORTED_CURRENCY, 10_000) + .base_weight(5) + .build() + .execute_with(|| { + let len = 10; + let tip = 5; + let dispatch_info = info_from_weight(Weight::from_parts(15, 0)); + let post_dispatch_info = post_info_from_weight(Weight::from_parts(10, 0)); + + // Act + let pre = ChargeTransactionPayment::::from(tip) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &dispatch_info, len, 0) + .unwrap(); + + // Assert + + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &CHARLIE), 10_000 - 52); + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &FeeReceiver::get()), 0); + assert_eq!(Balances::free_balance(CHARLIE), 0); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 0); + + // Act + let (pre_data, _origin) = pre; + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &dispatch_info, + &mut post_dispatch_info.clone(), + len, + &Ok(()) + )); + + // Assert + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &CHARLIE), 10_000 - 45); + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &FeeReceiver::get()), 45); + assert_eq!(Balances::free_balance(CHARLIE), 0); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 0); + }); +} + +#[test] +fn fee_should_be_withdrawn_and_not_refunded_when_paid_in_non_native_currency_with_tip() { + // Arrange + ExtBuilder::default() + .with_currencies(vec![(CHARLIE, SUPPORTED_CURRENCY)]) + .account_tokens(CHARLIE, SUPPORTED_CURRENCY, 10_000) + .base_weight(5) + .build() + .execute_with(|| { + let len = 10; + let tip = 5; + let dispatch_info = info_from_weight(Weight::from_parts(15, 0)); + let post_dispatch_info = post_info_from_weight(Weight::from_parts(10, 0)); + let previous_total_issuance = Tokens::total_issuance(SUPPORTED_CURRENCY); + + // Act + let pre = ChargeTransactionPayment::::from(tip) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &dispatch_info, len, 0) + .unwrap(); + + // Assert + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &CHARLIE), 10_000 - 52); + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &FeeReceiver::get()), 0); + assert_eq!(Balances::free_balance(CHARLIE), 0); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 0); + + // Act + let (pre_data, _origin) = pre; + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &dispatch_info, + &mut post_dispatch_info.clone(), + len, + &Ok(()) + )); + + // Assert + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &CHARLIE), 10_000 - 45); + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &FeeReceiver::get()), 45); + assert_eq!(Balances::free_balance(CHARLIE), 0); + assert_eq!(Balances::free_balance(FEE_RECEIVER), 0); + assert_eq!(Tokens::total_issuance(SUPPORTED_CURRENCY), previous_total_issuance); + }); +} + +#[test] +fn fee_payment_in_native_currency_with_no_balance() { + ExtBuilder::default() + .base_weight(5) + .account_native_balance(CHARLIE, 10) + .build() + .execute_with(|| { + let len = 10; + let info = info_from_weight(Weight::from_parts(5, 0)); + + assert!(ChargeTransactionPayment::::from(0) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &info, len, 0) + .is_err()); + + assert_eq!(Balances::free_balance(CHARLIE), 10); + assert_eq!(Balances::free_balance(FeeReceiver::get()), 0); + }); +} + +#[test] +fn fee_payment_in_non_native_currency_with_no_balance() { + ExtBuilder::default() + .base_weight(5) + .account_tokens(CHARLIE, SUPPORTED_CURRENCY, 100) + .with_currencies(vec![(CHARLIE, SUPPORTED_CURRENCY)]) + .build() + .execute_with(|| { + let len = 1000; + let info = info_from_weight(Weight::from_parts(5, 0)); + + assert!(ChargeTransactionPayment::::from(0) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &info, len, 0) + .is_err()); + + assert_eq!(Tokens::free_balance(SUPPORTED_CURRENCY, &CHARLIE), 100); + assert_eq!(Tokens::free_balance(SUPPORTED_CURRENCY, &FeeReceiver::get()), 0); + }); +} + +#[test] +fn fee_payment_in_non_native_currency_with_no_price() { + ExtBuilder::default() + .base_weight(5) + .account_tokens(CHARLIE, SUPPORTED_CURRENCY, 10_000) + .with_currencies(vec![(CHARLIE, SUPPORTED_CURRENCY)]) + .build() + .execute_with(|| { + // Make sure Charlie ain't got a penny! + assert_eq!(Balances::free_balance(CHARLIE), 0); + + let len = 10; + let info = info_from_weight(Weight::from_parts(5, 0)); + + assert_eq!(Tokens::free_balance(SUPPORTED_CURRENCY, &FEE_RECEIVER), 0); + + assert!(ChargeTransactionPayment::::from(0) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &info, len, 0) + .is_ok()); + + //Native balance check - Charlie should be still broke! + assert_eq!(Balances::free_balance(CHARLIE), 0); + + assert_eq!(Tokens::free_balance(SUPPORTED_CURRENCY, &CHARLIE), 9970); + assert_eq!(Tokens::free_balance(SUPPORTED_CURRENCY, &FEE_RECEIVER), 0); + }); +} + +#[test] +fn fee_payment_in_unregistered_currency() { + ExtBuilder::default() + .base_weight(5) + .account_tokens(CHARLIE, SUPPORTED_CURRENCY, 100) + .with_currencies(vec![(CHARLIE, SUPPORTED_CURRENCY)]) + .build() + .execute_with(|| { + let len = 1000; + let info = info_from_weight(Weight::from_parts(5, 0)); + + assert_ok!(PaymentPallet::remove_currency( + RuntimeOrigin::root(), + SUPPORTED_CURRENCY + )); + + assert!(ChargeTransactionPayment::::from(0) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &info, len, 0) + .is_err()); + + assert_eq!(Tokens::free_balance(SUPPORTED_CURRENCY, &CHARLIE), 100); + }); +} + +#[test] +fn fee_payment_non_native_insufficient_balance_with_no_pool() { + ExtBuilder::default() + .base_weight(5) + .account_tokens(CHARLIE, SUPPORTED_CURRENCY, 100) + .with_currencies(vec![(CHARLIE, SUPPORTED_CURRENCY)]) + .build() + .execute_with(|| { + let len = 1000; + let info = info_from_weight(Weight::from_parts(5, 0)); + + assert!(ChargeTransactionPayment::::from(0) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &info, len, 0) + .is_err()); + + assert_eq!(Tokens::free_balance(SUPPORTED_CURRENCY, &CHARLIE), 100); + }); +} + +#[test] +fn fee_transfer_can_kill_account_when_paid_in_native() { + // Arrange + ExtBuilder::default() + .account_native_balance(CHARLIE, 30) + .base_weight(5) + .build() + .execute_with(|| { + let len = 10; + let tip = 0; + let dispatch_info = info_from_weight(Weight::from_parts(15, 0)); + + // Act + let pre = ChargeTransactionPayment::::from(tip) + .validate_and_prepare(Some(CHARLIE).into(), CALL, &dispatch_info, len, 0) + .unwrap(); + + // Assert + assert_eq!(Balances::free_balance(FEE_RECEIVER), 0); + + // Act + let (pre_data, _origin) = pre; + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &dispatch_info, + &mut default_post_info(), + len, + &Ok(()) + )); + + // Assert + assert_eq!(Balances::free_balance(CHARLIE), 0); // zero balance indicates that the account can be killed + assert_eq!(Balances::free_balance(FEE_RECEIVER), 30); + }); +} + +#[test] +fn fee_transfer_can_kill_account_when_paid_in_non_native() { + // Arrange + ExtBuilder::default() + .with_currencies(vec![(ALICE, SUPPORTED_CURRENCY)]) + .base_weight(5) + .build() + .execute_with(|| { + let len = 10; + let tip = 0; + let dispatch_info = info_from_weight(Weight::from_parts(15, 0)); + + assert_ok!(Currencies::withdraw( + SUPPORTED_CURRENCY, + &ALICE, + INITIAL_BALANCE - 45, + ExistenceRequirement::AllowDeath + )); + + // Act + let pre = ChargeTransactionPayment::::from(tip) + .validate_and_prepare(Some(ALICE).into(), CALL, &dispatch_info, len, 0) + .unwrap(); + + // Assert + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &FEE_RECEIVER), 0); + + // Act + let (pre_data, _origin) = pre; + assert_ok!(ChargeTransactionPayment::::post_dispatch( + pre_data, + &dispatch_info, + &mut default_post_info(), + len, + &Ok(()) + )); + + // Assert + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &ALICE), 0); // zero balance indicates that the account can be killed + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &FEE_RECEIVER), 45); + }); +} + +#[test] +fn set_and_remove_currency_on_lifecycle_callbacks() { + ExtBuilder::default() + .base_weight(5) + .account_native_balance(CHARLIE, 10) + .account_tokens(CHARLIE, SUPPORTED_CURRENCY, 10) + .build() + .execute_with(|| { + assert_ok!(Tokens::transfer(Some(CHARLIE).into(), BOB, SUPPORTED_CURRENCY, 5)); + + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &CHARLIE), 5); + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY, &BOB), 5); + // Bob's fee currency was set on transfer (due to account creation) + assert_eq!(PaymentPallet::get_currency(BOB), Some(SUPPORTED_CURRENCY)); + + // currency should be removed if account is killed + assert_ok!(Tokens::transfer_all( + Some(BOB).into(), + CHARLIE, + SUPPORTED_CURRENCY, + false + )); + assert_eq!(PaymentPallet::get_currency(BOB), None); + }); +} + +#[test] +fn currency_stays_around_until_reaping() { + use frame_support::traits::fungibles::Balanced; + + ExtBuilder::default() + .base_weight(5) + .account_native_balance(CHARLIE, 10) + .account_tokens(CHARLIE, SUPPORTED_CURRENCY, 10) + .build() + .execute_with(|| { + // setup + assert_ok!(>::deposit( + HIGH_ED_CURRENCY, + &DAVE, + HIGH_ED * 2, + Precision::Exact + ) + .map(|_| ())); + assert_eq!(Currencies::free_balance(HIGH_ED_CURRENCY, &DAVE), HIGH_ED * 2); + assert_eq!(PaymentPallet::get_currency(DAVE), Some(HIGH_ED_CURRENCY)); + + // currency is not removed when account goes below existential deposit but stays around + // until the account is reaped + assert_ok!(Tokens::transfer(Some(DAVE).into(), BOB, HIGH_ED_CURRENCY, HIGH_ED + 1,)); + assert_eq!(PaymentPallet::get_currency(DAVE), Some(HIGH_ED_CURRENCY)); + assert_eq!(PaymentPallet::get_currency(BOB), Some(HIGH_ED_CURRENCY)); + + // ... and account is reaped when all funds are transferred + assert_ok!(Tokens::transfer_all(Some(DAVE).into(), BOB, HIGH_ED_CURRENCY, false)); + assert_eq!(PaymentPallet::get_currency(DAVE), None); + }); +} + +#[test] +fn currency_is_removed_when_balance_hits_zero() { + use frame_support::traits::fungibles::Balanced; + + ExtBuilder::default() + .base_weight(5) + .account_native_balance(CHARLIE, 10) + .account_tokens(CHARLIE, SUPPORTED_CURRENCY, 10) + .build() + .execute_with(|| { + // setup + assert_ok!(>::deposit( + SUPPORTED_CURRENCY_WITH_PRICE, + &DAVE, + 10, + Precision::Exact + ) + .map(|_| ())); + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY_WITH_PRICE, &DAVE), 10); + assert_eq!(PaymentPallet::get_currency(DAVE), Some(SUPPORTED_CURRENCY_WITH_PRICE)); + + // currency is removed when all funds of tx fee currency are transferred (even if + // account still has other funds) + assert_ok!(Tokens::transfer(Some(CHARLIE).into(), DAVE, SUPPORTED_CURRENCY, 2)); + assert_ok!(Tokens::transfer_all( + Some(DAVE).into(), + BOB, + SUPPORTED_CURRENCY_WITH_PRICE, + false + )); + assert_eq!(PaymentPallet::get_currency(DAVE), None); + }); +} + +#[test] +fn currency_is_not_changed_on_unrelated_account_activity() { + use frame_support::traits::fungibles::Balanced; + + ExtBuilder::default() + .base_weight(5) + .account_native_balance(CHARLIE, 10) + .account_tokens(CHARLIE, SUPPORTED_CURRENCY, 10) + .build() + .execute_with(|| { + // setup + assert_ok!(>::deposit( + SUPPORTED_CURRENCY_WITH_PRICE, + &DAVE, + 10, + Precision::Exact + ) + .map(|_| ())); + assert_eq!(Currencies::free_balance(SUPPORTED_CURRENCY_WITH_PRICE, &DAVE), 10); + assert_eq!(PaymentPallet::get_currency(DAVE), Some(SUPPORTED_CURRENCY_WITH_PRICE)); + + // tx fee currency is not changed when a new currency is added to the account + assert_ok!(Tokens::transfer(Some(CHARLIE).into(), DAVE, SUPPORTED_CURRENCY, 2)); + assert_eq!(PaymentPallet::get_currency(DAVE), Some(SUPPORTED_CURRENCY_WITH_PRICE)); + + // tx fee currency is not removed when an unrelated account is removed + assert_ok!(Tokens::transfer_all( + Some(DAVE).into(), + CHARLIE, + SUPPORTED_CURRENCY, + false + )); + assert_eq!(PaymentPallet::get_currency(DAVE), Some(SUPPORTED_CURRENCY_WITH_PRICE)); + }); +} + +#[test] +fn only_set_fee_currency_for_supported_currency() { + ExtBuilder::default() + .base_weight(5) + .account_native_balance(CHARLIE, 10) + .account_tokens(CHARLIE, UNSUPPORTED_CURRENCY, 10) + .build() + .execute_with(|| { + assert_ok!(Tokens::transfer(Some(CHARLIE).into(), BOB, UNSUPPORTED_CURRENCY, 5)); + + assert_eq!(Currencies::free_balance(UNSUPPORTED_CURRENCY, &CHARLIE), 5); + assert_eq!(Currencies::free_balance(UNSUPPORTED_CURRENCY, &BOB), 5); + // Bob's fee currency was not set on transfer (due to the currency being unsupported) + assert_eq!(PaymentPallet::get_currency(BOB), None); + }); +} + +#[test] +fn only_set_fee_currency_when_without_native_currency() { + ExtBuilder::default() + .account_native_balance(CHARLIE, 10) + .build() + .execute_with(|| { + assert_eq!(PaymentPallet::get_currency(CHARLIE), None); + + assert_ok!(Currencies::transfer( + Some(ALICE).into(), + CHARLIE, + SUPPORTED_CURRENCY, + 10, + )); + + assert_eq!(PaymentPallet::get_currency(CHARLIE), None); + }); +} + +#[test] +fn do_not_set_fee_currency_for_new_native_account() { + ExtBuilder::default() + .account_native_balance(CHARLIE, 10) + .build() + .execute_with(|| { + assert_eq!(PaymentPallet::get_currency(DAVE), None); + + assert_ok!(Currencies::transfer(Some(CHARLIE).into(), DAVE, 0, 10,)); + + assert_eq!(PaymentPallet::get_currency(DAVE), None); + }); +} + +#[test] +fn returns_prices_for_supported_currencies() { + ExtBuilder::default().build().execute_with(|| { + // returns constant price of 1 for native asset + assert_eq!(PaymentPallet::price(HdxAssetId::get()), Some(1.into())); + // returns default price configured at genesis + assert_eq!(PaymentPallet::price(SUPPORTED_CURRENCY_NO_BALANCE), Some(1.into())); + assert_eq!(PaymentPallet::price(SUPPORTED_CURRENCY), Some(Price::from_float(1.5))); + assert_eq!(PaymentPallet::price(HIGH_ED_CURRENCY), Some(3.into())); + // returns spot price + assert_eq!( + PaymentPallet::price(SUPPORTED_CURRENCY_WITH_PRICE), + Some(Price::from_float(0.1)) + ); + }); +} + +#[test] +fn reset_payment_currency_should_set_currency_to_hdx_for_non_evm_accounts() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(PaymentPallet::set_currency( + RuntimeOrigin::signed(ALICE), + SUPPORTED_CURRENCY, + )); + + assert_ok!(PaymentPallet::reset_payment_currency(RuntimeOrigin::root(), ALICE,)); + + assert_eq!(PaymentPallet::get_currency(ALICE), None); + + expect_events(vec![Event::CurrencySet { + account_id: ALICE, + asset_id: HDX, + } + .into()]); + }); +} diff --git a/pallets/transaction-multi-payment/src/traits.rs b/pallets/transaction-multi-payment/src/traits.rs new file mode 100644 index 00000000000..a181b9d798f --- /dev/null +++ b/pallets/transaction-multi-payment/src/traits.rs @@ -0,0 +1,142 @@ +use crate::{Config, Error, PhantomData}; +use frame_support::dispatch::PostDispatchInfo; +use frame_support::pallet_prelude::DispatchResultWithPostInfo; +use frame_support::sp_runtime::DispatchResult; +use frame_support::weights::Weight; +use sp_core::{H160, H256, U256}; +use sp_std::vec::Vec; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum PaymentInfo { + Native(Balance), + NonNative(Balance, AssetId, Price), +} + +/// Handler for dealing with fees +pub trait DepositFee { + fn deposit_fee(who: &AccountId, currency: AssetId, amount: Balance) -> DispatchResult; +} + +pub trait EVMPermit { + #![allow(clippy::too_many_arguments)] + fn validate_permit( + source: H160, + target: H160, + data: Vec, + value: U256, + gas_limit: u64, + deadline: U256, + v: u8, + r: H256, + s: H256, + ) -> DispatchResult; + + fn dispatch_permit( + source: H160, + target: H160, + data: Vec, + value: U256, + gas_limit: u64, + max_fee_per_gas: U256, + max_priority_fee_per_gas: Option, + nonce: Option, + access_list: Vec<(H160, Vec)>, + ) -> DispatchResultWithPostInfo; + + fn gas_price() -> (U256, Weight); + + fn dispatch_weight(gas_limit: u64) -> Weight; + + fn permit_nonce(account: H160) -> U256; + + fn on_dispatch_permit_error(); +} + +impl EVMPermit for () { + fn validate_permit( + _source: H160, + _target: H160, + _data: Vec, + _value: U256, + _gas_limit: u64, + _deadline: U256, + _v: u8, + _r: H256, + _s: H256, + ) -> DispatchResult { + Ok(()) + } + + fn dispatch_permit( + _source: H160, + _target: H160, + _data: Vec, + _value: U256, + _gas_limit: u64, + _max_fee_per_gas: U256, + _max_priority_fee_per_gas: Option, + _nonce: Option, + _access_list: Vec<(H160, Vec)>, + ) -> DispatchResultWithPostInfo { + Ok(PostDispatchInfo::default()) + } + + fn gas_price() -> (U256, Weight) { + Default::default() + } + + fn dispatch_weight(_gas_limit: u64) -> Weight { + Weight::zero() + } + + fn permit_nonce(_account: H160) -> U256 { + U256::default() + } + + fn on_dispatch_permit_error() {} +} + +pub struct DisabledEvmPermitHandler(PhantomData); +impl EVMPermit for DisabledEvmPermitHandler { + fn validate_permit( + _source: H160, + _target: H160, + _data: Vec, + _value: U256, + _gas_limit: u64, + _deadline: U256, + _v: u8, + _r: H256, + _s: H256, + ) -> DispatchResult { + Err(Error::::EvmPermitCallExecutionError.into()) + } + + fn dispatch_permit( + _source: H160, + _target: H160, + _data: Vec, + _value: U256, + _gas_limit: u64, + _max_fee_per_gas: U256, + _max_priority_fee_per_gas: Option, + _nonce: Option, + _access_list: Vec<(H160, Vec)>, + ) -> DispatchResultWithPostInfo { + Err(Error::::EvmPermitCallExecutionError.into()) + } + + fn gas_price() -> (U256, Weight) { + Default::default() + } + + fn dispatch_weight(_gas_limit: u64) -> Weight { + Weight::MAX + } + + fn permit_nonce(_account: H160) -> U256 { + U256::default() + } + + fn on_dispatch_permit_error() {} +} diff --git a/pallets/transaction-multi-payment/src/weights.rs b/pallets/transaction-multi-payment/src/weights.rs new file mode 100644 index 00000000000..e65ba0ea4b8 --- /dev/null +++ b/pallets/transaction-multi-payment/src/weights.rs @@ -0,0 +1,127 @@ +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_transaction_multi_payment. +pub trait WeightInfo { + fn add_currency() -> Weight; + fn remove_currency() -> Weight; + fn set_currency() -> Weight; + fn get_oracle_price() -> Weight; + fn reset_payment_currency() -> Weight; + fn withdraw_fee() -> Weight; +} + +/// Weights for pallet_transaction_multi_payment using the hydraDX node and recommended hardware. +impl WeightInfo for () { + /// Storage: `MultiTransactionPayment::AcceptedCurrencies` (r:1 w:1) + /// Proof: `MultiTransactionPayment::AcceptedCurrencies` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn add_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `1209` + // Estimated: `3493` + // Minimum execution time: 27_104_000 picoseconds. + Weight::from_parts(27_570_000, 3493) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `MultiTransactionPayment::AcceptedCurrencies` (r:1 w:1) + /// Proof: `MultiTransactionPayment::AcceptedCurrencies` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn remove_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `1240` + // Estimated: `3493` + // Minimum execution time: 27_177_000 picoseconds. + Weight::from_parts(27_728_000, 3493) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `MultiTransactionPayment::AcceptedCurrencies` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AcceptedCurrencies` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:0 w:1) + /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + fn set_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `1305` + // Estimated: `3493` + // Minimum execution time: 38_736_000 picoseconds. + Weight::from_parts(39_416_000, 3493) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Router::Routes` (r:1 w:0) + /// Proof: `Router::Routes` (`max_values`: None, `max_size`: Some(90), added: 2565, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::Oracles` (r:10 w:0) + /// Proof: `EmaOracle::Oracles` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + fn get_oracle_price() -> Weight { + // Proof Size summary in bytes: + // Measured: `3221` + // Estimated: `27510` + // Minimum execution time: 104_922_000 picoseconds. + Weight::from_parts(106_301_000, 27510) + .saturating_add(RocksDbWeight::get().reads(11_u64)) + } + /// Storage: `AssetRegistry::NextAssetId` (r:1 w:0) + /// Proof: `AssetRegistry::NextAssetId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::LocationAssets` (r:1 w:0) + /// Proof: `AssetRegistry::LocationAssets` (`max_values`: None, `max_size`: Some(622), added: 3097, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:0 w:1) + /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + fn reset_payment_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `1313` + // Estimated: `4087` + // Minimum execution time: 30_422_000 picoseconds. + Weight::from_parts(30_834_000, 4087) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AcceptedCurrencies` (r:2 w:0) + /// Proof: `MultiTransactionPayment::AcceptedCurrencies` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::NextAssetId` (r:1 w:0) + /// Proof: `AssetRegistry::NextAssetId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::LocationAssets` (r:1 w:0) + /// Proof: `AssetRegistry::LocationAssets` (`max_values`: None, `max_size`: Some(622), added: 3097, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AcceptedCurrencyPrice` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AcceptedCurrencyPrice` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `Router::Routes` (r:1 w:0) + /// Proof: `Router::Routes` (`max_values`: None, `max_size`: Some(90), added: 2565, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::Oracles` (r:1 w:0) + /// Proof: `EmaOracle::Oracles` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:4 w:4) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `XYK::ShareToken` (r:1 w:0) + /// Proof: `XYK::ShareToken` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:2 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::WhitelistedAssets` (r:1 w:0) + /// Proof: `EmaOracle::WhitelistedAssets` (`max_values`: Some(1), `max_size`: Some(641), added: 1136, mode: `MaxEncodedLen`) + /// Storage: `Tokens::TotalIssuance` (r:1 w:1) + /// Proof: `Tokens::TotalIssuance` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn withdraw_fee() -> Weight { + // Proof Size summary in bytes: + // Measured: `4158` + // Estimated: `11322` + // Minimum execution time: 283_584_000 picoseconds. + Weight::from_parts(285_058_000, 11322) + .saturating_add(RocksDbWeight::get().reads(24_u64)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) + } +} diff --git a/pallets/xyk-liquidity-mining/Cargo.toml b/pallets/xyk-liquidity-mining/Cargo.toml index 93f27acb821..e5e8924faf0 100644 --- a/pallets/xyk-liquidity-mining/Cargo.toml +++ b/pallets/xyk-liquidity-mining/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-xyk-liquidity-mining" -version = "1.1.13" +version = "1.2.0" description = "Liquidity mining" authors = ["GalacticCouncil"] edition = "2021" diff --git a/pallets/xyk-liquidity-mining/benchmarking/Cargo.toml b/pallets/xyk-liquidity-mining/benchmarking/Cargo.toml index 0a40c187918..5f7d3c2bd06 100644 --- a/pallets/xyk-liquidity-mining/benchmarking/Cargo.toml +++ b/pallets/xyk-liquidity-mining/benchmarking/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-xyk-liquidity-mining-benchmarking" -version = "1.0.19" +version = "1.1.0" description = "Liquidity Mining Benchmarking Module" authors = ["GalacticCouncil"] edition = "2021" diff --git a/pallets/xyk-liquidity-mining/benchmarking/src/mock.rs b/pallets/xyk-liquidity-mining/benchmarking/src/mock.rs index fc8eabd9e76..5061794ec57 100644 --- a/pallets/xyk-liquidity-mining/benchmarking/src/mock.rs +++ b/pallets/xyk-liquidity-mining/benchmarking/src/mock.rs @@ -126,6 +126,7 @@ impl system::Config for Test { type PreInherents = (); type PostInherents = (); type PostTransactions = (); + type ExtensionsWeightInfo = (); } impl crate::Config for Test {} @@ -173,16 +174,35 @@ impl pallet_xyk_liquidity_mining::Config for Test { type NonDustableWhitelistHandler = Duster; } +pub struct NoErc20Support; + +impl hydradx_traits::evm::Erc20Inspect for NoErc20Support { + fn contract_address(_id: AssetId) -> Option { + None + } + + fn is_atoken(_asset_id: AssetId) -> bool { + false + } +} + +impl hydradx_traits::evm::Erc20OnDust for NoErc20Support { + fn on_dust( + _account: &AccountId, + _dust_dest_account: &AccountId, + _currency_id: AssetId, + ) -> sp_runtime::DispatchResult { + Err(sp_runtime::DispatchError::Other("EVM not supported")) + } +} + impl pallet_duster::Config for Test { type RuntimeEvent = RuntimeEvent; - type Balance = Balance; - type Amount = Amount; - type CurrencyId = AssetId; + type AssetId = AssetId; type MultiCurrency = Currency; - type MinCurrencyDeposits = AssetRegistry; - type Reward = (); - type NativeCurrencyId = BSXAssetId; - type BlacklistUpdateOrigin = EnsureRoot; + type ExistentialDeposit = AssetRegistry; + type WhitelistUpdateOrigin = EnsureRoot; + type Erc20Support = NoErc20Support; type TreasuryAccountId = TreasuryAccount; type WeightInfo = (); } @@ -221,6 +241,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type RuntimeFreezeReason = (); + type DoneSlashHandler = (); } parameter_types! { diff --git a/pallets/xyk-liquidity-mining/src/lib.rs b/pallets/xyk-liquidity-mining/src/lib.rs index 3b6456db17c..d87ad364187 100644 --- a/pallets/xyk-liquidity-mining/src/lib.rs +++ b/pallets/xyk-liquidity-mining/src/lib.rs @@ -45,7 +45,10 @@ pub mod weights; pub use pallet::*; -use frame_support::traits::tokens::nonfungibles::{Inspect, Mutate}; +use frame_support::traits::{ + tokens::nonfungibles::{Inspect, Mutate}, + ExistenceRequirement, +}; use frame_support::{ensure, sp_runtime::traits::Zero, PalletId}; use frame_system::pallet_prelude::BlockNumberFor; use hydradx_traits::liquidity_mining::{GlobalFarmId, Mutate as LiquidityMiningMutate, YieldFarmId}; @@ -914,13 +917,25 @@ impl Pallet { fn lock_lp_tokens(lp_token: AssetId, who: &T::AccountId, amount: Balance) -> Result<(), DispatchError> { let service_account_for_lp_shares = Self::account_id(); - T::MultiCurrency::transfer(lp_token, who, &service_account_for_lp_shares, amount) + T::MultiCurrency::transfer( + lp_token, + who, + &service_account_for_lp_shares, + amount, + ExistenceRequirement::AllowDeath, + ) } fn unlock_lp_tokens(lp_token: AssetId, who: &T::AccountId, amount: Balance) -> Result<(), DispatchError> { let service_account_for_lp_shares = Self::account_id(); - T::MultiCurrency::transfer(lp_token, &service_account_for_lp_shares, who, amount) + T::MultiCurrency::transfer( + lp_token, + &service_account_for_lp_shares, + who, + amount, + ExistenceRequirement::AllowDeath, + ) } /// This function retuns value of lp tokens in the `asset` currency. diff --git a/pallets/xyk-liquidity-mining/src/tests/mock.rs b/pallets/xyk-liquidity-mining/src/tests/mock.rs index e73396bfab6..65da5c66429 100644 --- a/pallets/xyk-liquidity-mining/src/tests/mock.rs +++ b/pallets/xyk-liquidity-mining/src/tests/mock.rs @@ -144,6 +144,7 @@ impl system::Config for Test { type PreInherents = (); type PostInherents = (); type PostTransactions = (); + type ExtensionsWeightInfo = (); } thread_local! { @@ -820,6 +821,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type RuntimeFreezeReason = (); + type DoneSlashHandler = (); } parameter_type_with_key! { diff --git a/pallets/xyk/Cargo.toml b/pallets/xyk/Cargo.toml new file mode 100644 index 00000000000..37e0af56e18 --- /dev/null +++ b/pallets/xyk/Cargo.toml @@ -0,0 +1,75 @@ +[package] +name = "pallet-xyk" +version = "6.8.0" +description = "XYK automated market maker" +authors = ["GalacticCouncil"] +edition = "2021" +homepage = "https://github.com/galacticcouncil/hydradx-node" +license = "Apache 2.0" +repository = "https://github.com/galacticcouncil/hydradx-node" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[build-dependencies] +substrate-wasm-builder = { workspace = true } + +[dependencies] +codec = { workspace = true } +scale-info = { workspace = true } +primitive-types = { workspace = true } +serde = { workspace = true, optional = true } +log = { workspace = true } + +basilisk-traits = { workspace = true } + +basilisk-math = { workspace = true } +hydra-dx-math = { workspace = true } + +# ORML dependencies +orml-tokens = { workspace = true } +orml-traits = { workspace = true } + +# HydraDX dependencies +hydradx-traits = { workspace = true } +pallet-broadcast = { workspace = true } + +# Substrate dependencies +frame-benchmarking = { workspace = true, optional = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +sp-core = { workspace = true } +sp-runtime = { workspace = true } +sp-std = { workspace = true } + +[dev-dependencies] +pallet-asset-registry = { workspace = true } +sp-io = { workspace = true } +sp-api = { workspace = true } +proptest = { workspace = true } + +[features] +default = ["std"] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-system/runtime-benchmarks", + "frame-support/runtime-benchmarks", +] +std = [ + "serde", + "codec/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-core/std", + "sp-std/std", + "orml-traits/std", + "hydradx-traits/std", + "orml-tokens/std", + "frame-benchmarking/std", + "scale-info/std", + "pallet-asset-registry/std", + "pallet-broadcast/std", + "basilisk-traits/std", +] +try-runtime = ["frame-support/try-runtime"] diff --git a/pallets/xyk/README.md b/pallets/xyk/README.md new file mode 100644 index 00000000000..c29db36c790 --- /dev/null +++ b/pallets/xyk/README.md @@ -0,0 +1,25 @@ +### AMM XYK pallet + +## Overview +AMM pallet provides functionality for managing liquidity pool and executing trades. + +This pallet implements AMM Api trait therefore it is possible to plug this pool implementation +into the exchange pallet. + +### Terminology + +- **Currency** - implementation of fungible multi-currency system +- **AssetPairAccount** / **AssetPairAccountId** - support for creating share accounts for asset pairs. +- **NativeAssetId** - asset id native currency +- **ShareToken** - asset id from asset registry for an asset pair +- **TotalLiquidity** - total liquidity in a pool identified by asset pair account id +- **PoolAssets** - asset pair in a pool identified by asset pair account id + +### Interface + +#### Dispatchable functions +- `create_pool` +- `add_liquidity` +- `remove_liquidity` +- `sell` +- `buy` diff --git a/pallets/xyk/src/impls.rs b/pallets/xyk/src/impls.rs new file mode 100644 index 00000000000..41f8a3ca017 --- /dev/null +++ b/pallets/xyk/src/impls.rs @@ -0,0 +1,31 @@ +use crate::types::{AssetId, AssetPair, Price}; +use hydradx_traits::pools::SpotPriceProvider; +use hydradx_traits::AMM; +use orml_traits::MultiCurrency; +use sp_runtime::FixedPointNumber; +use sp_std::marker::PhantomData; + +pub struct XYKSpotPrice(PhantomData); + +impl SpotPriceProvider for XYKSpotPrice { + type Price = Price; + + fn pair_exists(asset_a: AssetId, asset_b: AssetId) -> bool { + >::exists(AssetPair::new(asset_b, asset_a)) + } + + fn spot_price(asset_a: AssetId, asset_b: AssetId) -> Option { + if Self::pair_exists(asset_a, asset_b) { + let pair_account = >::get_pair_id(AssetPair { + asset_out: asset_a, + asset_in: asset_b, + }); + let asset_a_reserve = T::Currency::free_balance(asset_a, &pair_account); + let asset_b_reserve = T::Currency::free_balance(asset_b, &pair_account); + + Price::checked_from_rational(asset_a_reserve, asset_b_reserve) + } else { + None + } + } +} diff --git a/pallets/xyk/src/lib.rs b/pallets/xyk/src/lib.rs new file mode 100644 index 00000000000..e3d6af04487 --- /dev/null +++ b/pallets/xyk/src/lib.rs @@ -0,0 +1,1212 @@ +// This file is part of HydraDX-node. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # XYK Pallet +//! +//! ## Overview +//! +//! XYK pallet provides functionality for managing liquidity pool and executing trades. +//! +//! This pallet implements AMM Api trait therefore it is possible to plug this pool implementation +//! into the exchange pallet. + +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::unused_unit)] +#![allow(clippy::upper_case_acronyms)] +#![allow(clippy::manual_inspect)] + +use basilisk_traits::{OnCreatePoolHandler, OnLiquidityChangedHandler, OnTradeHandler}; +use frame_support::sp_runtime::{traits::Zero, DispatchError}; +use frame_support::{ + dispatch::DispatchResult, + ensure, + traits::{ExistenceRequirement, Get}, + transactional, +}; +use frame_system::ensure_signed; +use frame_system::pallet_prelude::BlockNumberFor; +use hydradx_traits::{AMMPosition, AMMTransfer, AssetPairAccountIdFor, CanCreatePool, AMM}; +use pallet_broadcast::types::{Asset, Destination, Fee}; + +use sp_std::{vec, vec::Vec}; + +use crate::types::{Amount, AssetId, AssetPair, Balance}; +use basilisk_math::ratio::Ratio; +use hydradx_traits::AMMAddLiquidity; +use orml_traits::{MultiCurrency, MultiCurrencyExtended}; + +#[cfg(test)] +mod tests; + +mod impls; +mod trade_execution; +pub mod types; +pub mod weights; + +pub use impls::XYKSpotPrice; + +pub use weights::WeightInfo; + +// Re-export pallet items so that they can be accessed from the crate namespace. +pub use pallet::*; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::OriginFor; + use hydradx_traits::{ + pools::DustRemovalAccountWhitelist, + registry::{AssetKind, Create}, + Source, + }; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::hooks] + impl Hooks> for Pallet {} + + #[pallet::config] + pub trait Config: frame_system::Config + pallet_broadcast::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// Registry support + type AssetRegistry: Create; + + /// Share token support + type AssetPairAccountId: AssetPairAccountIdFor; + + /// Multi currency for transfer of currencies + type Currency: MultiCurrencyExtended; + + /// Native Asset Id + #[pallet::constant] + type NativeAssetId: Get; + + /// Weight information for the extrinsics. + type WeightInfo: WeightInfo; + + /// Trading fee rate + #[pallet::constant] + type GetExchangeFee: Get<(u32, u32)>; + + /// Minimum trading limit + #[pallet::constant] + type MinTradingLimit: Get; + + /// Minimum pool liquidity + #[pallet::constant] + type MinPoolLiquidity: Get; + + /// Max fraction of pool to sell in single transaction + #[pallet::constant] + type MaxInRatio: Get; + + /// Max fraction of pool to buy in single transaction + #[pallet::constant] + type MaxOutRatio: Get; + + /// Oracle source identifier for this pallet. + #[pallet::constant] + type OracleSource: Get; + + /// Called to ensure that pool can be created + type CanCreatePool: CanCreatePool; + + /// AMM handlers + type AMMHandler: OnCreatePoolHandler + + OnTradeHandler + + OnLiquidityChangedHandler; + + /// Discounted fee + type DiscountedFee: Get<(u32, u32)>; + + /// Account whitelist manager to exclude pool accounts from dusting mechanism. + type NonDustableWhitelistHandler: DustRemovalAccountWhitelist; + } + + #[pallet::error] + pub enum Error { + /// It is not allowed to create a pool between same assets. + CannotCreatePoolWithSameAssets, + + /// Liquidity has not reached the required minimum. + InsufficientLiquidity, + + /// Amount is less than min trading limit. + InsufficientTradingAmount, + + /// Liquidity is zero. + ZeroLiquidity, + + /// It is not allowed to create a pool with zero initial price. + /// Not used, kept for backward compatibility + ZeroInitialPrice, + + /// Overflow + /// Not used, kept for backward compatibility + CreatePoolAssetAmountInvalid, + + /// Overflow + InvalidMintedLiquidity, // No tests - but it is currently not possible this error to occur due to previous checks in the code. + + /// Overflow + InvalidLiquidityAmount, // no tests - it is currently not possible this error to occur due to previous checks in the code. + + /// Asset amount has exceeded given limit. + AssetAmountExceededLimit, + + /// Asset amount has not reached given limit. + AssetAmountNotReachedLimit, + + /// Asset balance is not sufficient. + InsufficientAssetBalance, + + /// Not enough asset liquidity in the pool. + InsufficientPoolAssetBalance, + + /// Not enough core asset liquidity in the pool. + InsufficientNativeCurrencyBalance, + + /// Liquidity pool for given assets does not exist. + TokenPoolNotFound, + + /// Liquidity pool for given assets already exists. + TokenPoolAlreadyExists, + + /// Overflow + AddAssetAmountInvalid, // no tests + /// Overflow + RemoveAssetAmountInvalid, // no tests + /// Overflow + SellAssetAmountInvalid, // no tests + /// Overflow + BuyAssetAmountInvalid, // no tests + + /// Overflow + FeeAmountInvalid, + + /// Overflow + CannotApplyDiscount, + + /// Max fraction of pool to buy in single transaction has been exceeded. + MaxOutRatioExceeded, + /// Max fraction of pool to sell in single transaction has been exceeded. + MaxInRatioExceeded, + + /// Overflow + Overflow, + + /// Pool cannot be created due to outside factors. + CannotCreatePool, + } + + #[pallet::event] + #[pallet::generate_deposit(pub(crate) fn deposit_event)] + pub enum Event { + /// New liquidity was provided to the pool. + LiquidityAdded { + who: T::AccountId, + asset_a: AssetId, + asset_b: AssetId, + amount_a: Balance, + amount_b: Balance, + }, + + /// Liquidity was removed from the pool. + LiquidityRemoved { + who: T::AccountId, + asset_a: AssetId, + asset_b: AssetId, + shares: Balance, + }, + + /// Pool was created. + PoolCreated { + who: T::AccountId, + asset_a: AssetId, + asset_b: AssetId, + initial_shares_amount: Balance, + share_token: AssetId, + pool: T::AccountId, + }, + + /// Pool was destroyed. + PoolDestroyed { + who: T::AccountId, + asset_a: AssetId, + asset_b: AssetId, + share_token: AssetId, + pool: T::AccountId, + }, + + /// Asset sale executed. + /// Deprecated. Replaced by pallet_broadcast::Swapped + SellExecuted { + who: T::AccountId, + asset_in: AssetId, + asset_out: AssetId, + amount: Balance, + sale_price: Balance, + fee_asset: AssetId, + fee_amount: Balance, + pool: T::AccountId, + }, + + /// Asset purchase executed. + /// Deprecated. Replaced by pallet_broadcast::Swapped + BuyExecuted { + who: T::AccountId, + asset_out: AssetId, + asset_in: AssetId, + amount: Balance, + buy_price: Balance, + fee_asset: AssetId, + fee_amount: Balance, + pool: T::AccountId, + }, + } + + /// Asset id storage for shared pool tokens + #[pallet::storage] + #[pallet::getter(fn share_token)] + pub(crate) type ShareToken = StorageMap<_, Blake2_128Concat, T::AccountId, AssetId, ValueQuery>; + + /// Total liquidity in a pool. + #[pallet::storage] + #[pallet::getter(fn total_liquidity)] + pub(crate) type TotalLiquidity = StorageMap<_, Blake2_128Concat, T::AccountId, Balance, ValueQuery>; + + /// Asset pair in a pool. + #[pallet::storage] + #[pallet::getter(fn pool_assets)] + pub(crate) type PoolAssets = + StorageMap<_, Blake2_128Concat, T::AccountId, (AssetId, AssetId), OptionQuery>; + + #[pallet::call] + impl Pallet { + /// Create new pool for given asset pair. + /// + /// Registers new pool for given asset pair (`asset a` and `asset b`) in asset registry. + /// Asset registry creates new id or returns previously created one if such pool existed before. + /// + /// Pool is created with initial liquidity provided by `origin`. + /// Shares are issued with specified initial price and represents proportion of asset in the pool. + /// + /// Emits `PoolCreated` event when successful. + #[pallet::call_index(0)] + #[pallet::weight(::WeightInfo::create_pool())] + pub fn create_pool( + origin: OriginFor, + asset_a: AssetId, + amount_a: Balance, + asset_b: AssetId, + amount_b: Balance, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + ensure!( + T::CanCreatePool::can_create(asset_a, asset_b), + Error::::CannotCreatePool + ); + + ensure!( + amount_a >= T::MinPoolLiquidity::get() && amount_b >= T::MinPoolLiquidity::get(), + Error::::InsufficientLiquidity + ); + + ensure!(asset_a != asset_b, Error::::CannotCreatePoolWithSameAssets); + + let asset_pair = AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }; + + ensure!(!Self::exists(asset_pair), Error::::TokenPoolAlreadyExists); + + let shares_added = if asset_a < asset_b { amount_a } else { amount_b }; + + ensure!( + T::Currency::free_balance(asset_a, &who) >= amount_a, + Error::::InsufficientAssetBalance + ); + + ensure!( + T::Currency::free_balance(asset_b, &who) >= amount_b, + Error::::InsufficientAssetBalance + ); + + let pair_account = Self::get_pair_id(asset_pair); + + let token_name = asset_pair.name(); + + let share_token = T::AssetRegistry::get_or_register_insufficient_asset( + token_name.try_into().map_err(|_| Error::::CannotCreatePool)?, + AssetKind::XYK, + None, + None, + None, + None, + None, + )?; + + let _ = T::AMMHandler::on_create_pool(asset_pair.asset_in, asset_pair.asset_out); + + T::NonDustableWhitelistHandler::add_account(&pair_account)?; + + >::insert(&pair_account, share_token); + >::insert(&pair_account, (asset_a, asset_b)); + + Self::deposit_event(Event::PoolCreated { + who: who.clone(), + asset_a, + asset_b, + initial_shares_amount: shares_added, + share_token, + pool: pair_account.clone(), + }); + + T::Currency::transfer(asset_a, &who, &pair_account, amount_a, ExistenceRequirement::AllowDeath)?; + T::Currency::transfer(asset_b, &who, &pair_account, amount_b, ExistenceRequirement::AllowDeath)?; + + T::Currency::deposit(share_token, &who, shares_added)?; + + >::insert(&pair_account, shares_added); + + Ok(()) + } + + /// Add liquidity to previously created asset pair pool. + /// + /// Shares are issued with current price. + /// + /// Emits `LiquidityAdded` event when successful. + #[pallet::call_index(1)] + #[pallet::weight( + ::WeightInfo::add_liquidity() + .saturating_add(T::AMMHandler::on_liquidity_changed_weight()) + )] + #[transactional] + pub fn add_liquidity( + origin: OriginFor, + asset_a: AssetId, + asset_b: AssetId, + amount_a: Balance, + amount_b_max_limit: Balance, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::do_add_liquidity(who, asset_a, asset_b, amount_a, amount_b_max_limit)?; + + Ok(()) + } + + /// Remove liquidity from specific liquidity pool in the form of burning shares. + /// + /// If liquidity in the pool reaches 0, it is destroyed. + /// + /// Emits 'LiquidityRemoved' when successful. + /// Emits 'PoolDestroyed' when pool is destroyed. + #[pallet::call_index(2)] + #[pallet::weight( + ::WeightInfo::remove_liquidity() + .saturating_add(T::AMMHandler::on_liquidity_changed_weight()) + )] + #[transactional] + pub fn remove_liquidity( + origin: OriginFor, + asset_a: AssetId, + asset_b: AssetId, + liquidity_amount: Balance, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + let asset_pair = AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }; + + ensure!(!liquidity_amount.is_zero(), Error::::ZeroLiquidity); + + ensure!(Self::exists(asset_pair), Error::::TokenPoolNotFound); + + let pair_account = Self::get_pair_id(asset_pair); + + let share_token = Self::share_token(&pair_account); + + let total_shares = Self::total_liquidity(&pair_account); + + let account_shares = T::Currency::free_balance(share_token, &who); + + ensure!(total_shares >= liquidity_amount, Error::::InsufficientLiquidity); + + ensure!(account_shares >= liquidity_amount, Error::::InsufficientAssetBalance); + + // Account's liquidity left should be either 0 or at least MinPoolLiquidity + ensure!( + (account_shares.saturating_sub(liquidity_amount)) >= T::MinPoolLiquidity::get() + || (account_shares == liquidity_amount), + Error::::InsufficientLiquidity + ); + + let asset_a_reserve = T::Currency::free_balance(asset_a, &pair_account); + let asset_b_reserve = T::Currency::free_balance(asset_b, &pair_account); + + let liquidity_out = hydra_dx_math::xyk::calculate_liquidity_out( + asset_a_reserve, + asset_b_reserve, + liquidity_amount, + total_shares, + ) + .map_err(|_| Error::::RemoveAssetAmountInvalid)?; + + let (remove_amount_a, remove_amount_b) = liquidity_out; + + ensure!( + T::Currency::free_balance(asset_a, &pair_account) >= remove_amount_a, + Error::::InsufficientPoolAssetBalance + ); + ensure!( + T::Currency::free_balance(asset_b, &pair_account) >= remove_amount_b, + Error::::InsufficientPoolAssetBalance + ); + + let liquidity_left = total_shares + .checked_sub(liquidity_amount) + .ok_or(Error::::InvalidLiquidityAmount)?; + + T::Currency::transfer( + asset_a, + &pair_account, + &who, + remove_amount_a, + ExistenceRequirement::AllowDeath, + )?; + T::Currency::transfer( + asset_b, + &pair_account, + &who, + remove_amount_b, + ExistenceRequirement::AllowDeath, + )?; + + T::Currency::withdraw(share_token, &who, liquidity_amount, ExistenceRequirement::AllowDeath)?; + + >::insert(&pair_account, liquidity_left); + + let liquidity_a = T::Currency::total_balance(asset_a, &pair_account); + let liquidity_b = T::Currency::total_balance(asset_b, &pair_account); + T::AMMHandler::on_liquidity_changed( + T::OracleSource::get(), + asset_a, + asset_b, + remove_amount_a, + remove_amount_b, + liquidity_a, + liquidity_b, + Ratio::new(liquidity_a, liquidity_b), + ) + .map_err(|(_w, e)| e)?; + + Self::deposit_event(Event::LiquidityRemoved { + who: who.clone(), + asset_a, + asset_b, + shares: liquidity_amount, + }); + + if liquidity_left == 0 { + >::remove(&pair_account); + >::remove(&pair_account); + >::remove(&pair_account); + + // Ignore the failure, this cant stop liquidity removal + let r = T::NonDustableWhitelistHandler::remove_account(&pair_account); + + if r.is_err() { + log::trace!( + target: "xyk::remova_liquidity", "XYK: Failed to remove account {:?} from dust-removal whitelist. Reason {:?}", + pair_account, + r + ); + } + + Self::deposit_event(Event::PoolDestroyed { + who, + asset_a, + asset_b, + share_token, + pool: pair_account, + }); + } + + Ok(()) + } + + /// Trade asset in for asset out. + /// + /// Executes a swap of `asset_in` for `asset_out`. Price is determined by the liquidity pool. + /// + /// `max_limit` - minimum amount of `asset_out` / amount of asset_out to be obtained from the pool in exchange for `asset_in`. + /// + /// Emits `SellExecuted` when successful. Deprecated. + /// Emits `pallet_broadcast::Swapped` when successful. + #[pallet::call_index(3)] + #[pallet::weight(::WeightInfo::sell() + ::AMMHandler::on_trade_weight())] + pub fn sell( + origin: OriginFor, + asset_in: AssetId, + asset_out: AssetId, + amount: Balance, + max_limit: Balance, + discount: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + >::sell(&who, AssetPair { asset_in, asset_out }, amount, max_limit, discount)?; + + Ok(()) + } + + /// Trade asset in for asset out. + /// + /// Executes a swap of `asset_in` for `asset_out`. Price is determined by the liquidity pool. + /// + /// `max_limit` - maximum amount of `asset_in` to be sold in exchange for `asset_out`. + /// Emits `BuyExecuted` when successful. Deprecated. + /// Emits `pallet_broadcast::Swapped` when successful. + #[pallet::call_index(4)] + #[pallet::weight(::WeightInfo::buy() + ::AMMHandler::on_trade_weight())] + pub fn buy( + origin: OriginFor, + asset_out: AssetId, + asset_in: AssetId, + amount: Balance, + max_limit: Balance, + discount: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + >::buy(&who, AssetPair { asset_in, asset_out }, amount, max_limit, discount)?; + + Ok(()) + } + } +} + +impl Pallet { + fn do_add_liquidity( + who: T::AccountId, + asset_a: AssetId, + asset_b: AssetId, + amount_a: Balance, + amount_b_max_limit: Balance, + ) -> Result { + let asset_pair = AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }; + + ensure!(Self::exists(asset_pair), Error::::TokenPoolNotFound); + + ensure!( + amount_a >= T::MinTradingLimit::get(), + Error::::InsufficientTradingAmount + ); + + ensure!(!amount_b_max_limit.is_zero(), Error::::ZeroLiquidity); + + ensure!( + T::Currency::free_balance(asset_a, &who) >= amount_a, + Error::::InsufficientAssetBalance + ); + + let pair_account = Self::get_pair_id(asset_pair); + + let share_token = Self::share_token(&pair_account); + + let account_shares = T::Currency::free_balance(share_token, &who); + + let asset_a_reserve = T::Currency::free_balance(asset_a, &pair_account); + let asset_b_reserve = T::Currency::free_balance(asset_b, &pair_account); + let share_issuance = Self::total_liquidity(&pair_account); + + let amount_b = hydra_dx_math::xyk::calculate_liquidity_in(asset_a_reserve, asset_b_reserve, amount_a) + .map_err(|_| Error::::AddAssetAmountInvalid)?; + + ensure!( + T::Currency::free_balance(asset_b, &who) >= amount_b, + Error::::InsufficientAssetBalance + ); + + ensure!(amount_b <= amount_b_max_limit, Error::::AssetAmountExceededLimit); + + let shares_added = hydra_dx_math::xyk::calculate_shares(asset_a_reserve, amount_a, share_issuance) + .ok_or(Error::::Overflow)?; + + ensure!(!shares_added.is_zero(), Error::::InvalidMintedLiquidity); + + // Make sure that account share liquidity is at least MinPoolLiquidity + ensure!( + account_shares + .checked_add(shares_added) + .ok_or(Error::::InvalidMintedLiquidity)? + >= T::MinPoolLiquidity::get(), + Error::::InsufficientLiquidity + ); + + let liquidity_amount = share_issuance + .checked_add(shares_added) + .ok_or(Error::::InvalidLiquidityAmount)?; + + T::Currency::transfer(asset_a, &who, &pair_account, amount_a, ExistenceRequirement::AllowDeath)?; + T::Currency::transfer(asset_b, &who, &pair_account, amount_b, ExistenceRequirement::AllowDeath)?; + + T::Currency::deposit(share_token, &who, shares_added)?; + + >::insert(&pair_account, liquidity_amount); + + let liquidity_a = T::Currency::total_balance(asset_a, &pair_account); + let liquidity_b = T::Currency::total_balance(asset_b, &pair_account); + T::AMMHandler::on_liquidity_changed( + T::OracleSource::get(), + asset_a, + asset_b, + amount_a, + amount_b, + liquidity_a, + liquidity_b, + Ratio::new(liquidity_a, liquidity_b), + ) + .map_err(|(_w, e)| e)?; + + Self::deposit_event(Event::LiquidityAdded { + who, + asset_a, + asset_b, + amount_a, + amount_b, + }); + + Ok(shares_added) + } + + /// Return balance of each asset in selected liquidity pool. + pub fn get_pool_balances(pool_address: T::AccountId) -> Option> { + let mut balances = Vec::new(); + + if let Some(assets) = Self::get_pool_assets(&pool_address) { + for item in &assets { + let reserve = T::Currency::free_balance(*item, &pool_address); + balances.push((*item, reserve)); + } + } + Some(balances) + } + /// Calculate discounted trade fee + fn calculate_discounted_fee(amount: Balance) -> Result { + Ok( + hydra_dx_math::fee::calculate_pool_trade_fee(amount, T::DiscountedFee::get()) + .ok_or::>(Error::::FeeAmountInvalid)?, + ) + } + + /// Calculate trade fee + fn calculate_fee(amount: Balance) -> Result { + let fee = T::GetExchangeFee::get(); + Ok(hydra_dx_math::fee::calculate_pool_trade_fee(amount, (fee.0, fee.1)) + .ok_or::>(Error::::FeeAmountInvalid)?) + } + + pub fn pair_account_from_assets(asset_a: AssetId, asset_b: AssetId) -> T::AccountId { + T::AssetPairAccountId::from_assets(asset_a, asset_b, "xyk") + } +} + +// Implementation of AMM API which makes possible to plug the AMM pool into the exchange pallet. +impl AMM for Pallet { + fn exists(assets: AssetPair) -> bool { + >::contains_key(Self::get_pair_id(assets)) + } + + fn get_pair_id(assets: AssetPair) -> T::AccountId { + Self::pair_account_from_assets(assets.asset_in, assets.asset_out) + } + + fn get_share_token(assets: AssetPair) -> AssetId { + let pair_account = Self::get_pair_id(assets); + Self::share_token(&pair_account) + } + + fn get_pool_assets(pool_account_id: &T::AccountId) -> Option> { + let maybe_assets = >::get(pool_account_id); + maybe_assets.map(|assets| vec![assets.0, assets.1]) + } + + fn get_spot_price_unchecked(asset_a: AssetId, asset_b: AssetId, amount: Balance) -> Balance { + let pair_account = Self::get_pair_id(AssetPair { + asset_out: asset_a, + asset_in: asset_b, + }); + + let asset_a_reserve = T::Currency::free_balance(asset_a, &pair_account); + let asset_b_reserve = T::Currency::free_balance(asset_b, &pair_account); + + hydra_dx_math::xyk::calculate_spot_price(asset_a_reserve, asset_b_reserve, amount) + .unwrap_or_else(|_| Balance::zero()) + } + + /// Validate a sell. Perform all necessary checks and calculations. + /// No storage changes are performed yet. + /// + /// Return `AMMTransfer` with all info needed to execute the transaction. + fn validate_sell( + who: &T::AccountId, + assets: AssetPair, + amount: Balance, + min_bought: Balance, + discount: bool, + ) -> Result, sp_runtime::DispatchError> { + ensure!( + amount >= T::MinTradingLimit::get(), + Error::::InsufficientTradingAmount + ); + + ensure!(Self::exists(assets), Error::::TokenPoolNotFound); + + ensure!( + T::Currency::free_balance(assets.asset_in, who) >= amount, + Error::::InsufficientAssetBalance + ); + + // If discount, pool for Sell asset and native asset must exist + if discount { + ensure!( + Self::exists(AssetPair { + asset_in: assets.asset_in, + asset_out: T::NativeAssetId::get() + }), + Error::::CannotApplyDiscount + ); + } + + let pair_account = Self::get_pair_id(assets); + + let asset_in_reserve = T::Currency::free_balance(assets.asset_in, &pair_account); + let asset_out_reserve = T::Currency::free_balance(assets.asset_out, &pair_account); + + ensure!( + amount + <= asset_in_reserve + .checked_div(T::MaxInRatio::get()) + .ok_or(Error::::Overflow)?, + Error::::MaxInRatioExceeded + ); + + let amount_out = hydra_dx_math::xyk::calculate_out_given_in(asset_in_reserve, asset_out_reserve, amount) + .map_err(|_| Error::::SellAssetAmountInvalid)?; + + ensure!( + amount_out + <= asset_out_reserve + .checked_div(T::MaxOutRatio::get()) + .ok_or(Error::::Overflow)?, + Error::::MaxOutRatioExceeded + ); + + let transfer_fee = if discount { + Self::calculate_discounted_fee(amount_out)? + } else { + Self::calculate_fee(amount_out)? + }; + + let amount_out_without_fee = amount_out + .checked_sub(transfer_fee) + .ok_or(Error::::SellAssetAmountInvalid)?; + + ensure!(asset_out_reserve > amount_out, Error::::InsufficientAssetBalance); + + ensure!( + min_bought <= amount_out_without_fee, + Error::::AssetAmountNotReachedLimit + ); + + let discount_fee = if discount { + let native_asset = T::NativeAssetId::get(); + + let native_pair_account = Self::get_pair_id(AssetPair { + asset_in: assets.asset_in, + asset_out: native_asset, + }); + + let native_reserve = T::Currency::free_balance(native_asset, &native_pair_account); + let asset_reserve = T::Currency::free_balance(assets.asset_in, &native_pair_account); + + let native_fee_spot_price = + hydra_dx_math::xyk::calculate_spot_price(asset_reserve, native_reserve, transfer_fee) + .map_err(|_| Error::::CannotApplyDiscount)?; + + ensure!( + T::Currency::free_balance(native_asset, who) >= native_fee_spot_price, + Error::::InsufficientNativeCurrencyBalance + ); + + native_fee_spot_price + } else { + Balance::zero() + }; + + let transfer = AMMTransfer { + origin: who.clone(), + assets, + amount, + amount_b: amount_out_without_fee, + discount, + discount_amount: discount_fee, + fee: (assets.asset_out, transfer_fee), + }; + + Ok(transfer) + } + + /// Execute sell. validate_sell must be called first. + /// Perform necessary storage/state changes. + /// Note : the execution should not return error as everything was previously verified and validated. + #[transactional] + fn execute_sell(transfer: &AMMTransfer) -> DispatchResult { + let pair_account = Self::get_pair_id(transfer.assets); + + if transfer.discount && transfer.discount_amount > 0u128 { + let native_asset = T::NativeAssetId::get(); + T::Currency::withdraw( + native_asset, + &transfer.origin, + transfer.discount_amount, + ExistenceRequirement::AllowDeath, + )?; + } + + T::Currency::transfer( + transfer.assets.asset_in, + &transfer.origin, + &pair_account, + transfer.amount, + ExistenceRequirement::AllowDeath, + )?; + T::Currency::transfer( + transfer.assets.asset_out, + &pair_account, + &transfer.origin, + transfer.amount_b, + ExistenceRequirement::AllowDeath, + )?; + + let liquidity_in = T::Currency::total_balance(transfer.assets.asset_in, &pair_account); + let liquidity_out = T::Currency::total_balance(transfer.assets.asset_out, &pair_account); + T::AMMHandler::on_trade( + T::OracleSource::get(), + transfer.assets.asset_in, + transfer.assets.asset_out, + transfer.amount, + transfer.amount_b, + liquidity_in, + liquidity_out, + Ratio::new(liquidity_in, liquidity_out), + ) + .map_err(|(_w, e)| e)?; + + // TODO: Deprecated, remove when ready + Self::deposit_event(Event::::SellExecuted { + who: transfer.origin.clone(), + asset_in: transfer.assets.asset_in, + asset_out: transfer.assets.asset_out, + amount: transfer.amount, + sale_price: transfer.amount_b, + fee_asset: transfer.fee.0, + fee_amount: transfer.fee.1, + pool: pair_account.clone(), + }); + + pallet_broadcast::Pallet::::deposit_trade_event( + transfer.origin.clone(), + pair_account.clone(), + pallet_broadcast::types::Filler::XYK(Self::share_token(&pair_account)), + pallet_broadcast::types::TradeOperation::ExactIn, + vec![Asset::new(transfer.assets.asset_in, transfer.amount)], + vec![Asset::new(transfer.assets.asset_out, transfer.amount_b)], + vec![Fee { + asset: transfer.fee.0, + amount: transfer.fee.1, + destination: Destination::Account(pair_account), + }], + ); + + Ok(()) + } + + /// Validate a buy. Perform all necessary checks and calculations. + /// No storage changes are performed yet. + /// + /// Return `AMMTransfer` with all info needed to execute the transaction. + fn validate_buy( + who: &T::AccountId, + assets: AssetPair, + amount: Balance, + max_limit: Balance, + discount: bool, + ) -> Result, DispatchError> { + ensure!( + amount >= T::MinTradingLimit::get(), + Error::::InsufficientTradingAmount + ); + + ensure!(Self::exists(assets), Error::::TokenPoolNotFound); + + let pair_account = Self::get_pair_id(assets); + + let asset_out_reserve = T::Currency::free_balance(assets.asset_out, &pair_account); + let asset_in_reserve = T::Currency::free_balance(assets.asset_in, &pair_account); + + ensure!(asset_out_reserve > amount, Error::::InsufficientPoolAssetBalance); + + ensure!( + amount + <= asset_out_reserve + .checked_div(T::MaxOutRatio::get()) + .ok_or(Error::::Overflow)?, + Error::::MaxOutRatioExceeded + ); + + // If discount, pool for Sell asset and native asset must exist + if discount { + ensure!( + Self::exists(AssetPair { + asset_in: assets.asset_out, + asset_out: T::NativeAssetId::get() + }), + Error::::CannotApplyDiscount + ); + } + + let buy_price = hydra_dx_math::xyk::calculate_in_given_out(asset_out_reserve, asset_in_reserve, amount) + .map_err(|_| Error::::BuyAssetAmountInvalid)?; + + ensure!( + buy_price + <= asset_in_reserve + .checked_div(T::MaxInRatio::get()) + .ok_or(Error::::Overflow)?, + Error::::MaxInRatioExceeded + ); + + let transfer_fee = if discount { + Self::calculate_discounted_fee(buy_price)? + } else { + Self::calculate_fee(buy_price)? + }; + + let buy_price_with_fee = buy_price + .checked_add(transfer_fee) + .ok_or(Error::::BuyAssetAmountInvalid)?; + + ensure!(max_limit >= buy_price_with_fee, Error::::AssetAmountExceededLimit); + + ensure!( + T::Currency::free_balance(assets.asset_in, who) >= buy_price_with_fee, + Error::::InsufficientAssetBalance + ); + + let discount_fee = if discount { + let native_asset = T::NativeAssetId::get(); + + let native_pair_account = Self::get_pair_id(AssetPair { + asset_in: assets.asset_out, + asset_out: native_asset, + }); + + let native_reserve = T::Currency::free_balance(native_asset, &native_pair_account); + let asset_reserve = T::Currency::free_balance(assets.asset_out, &native_pair_account); + + let native_fee_spot_price = + hydra_dx_math::xyk::calculate_spot_price(asset_reserve, native_reserve, transfer_fee) + .map_err(|_| Error::::CannotApplyDiscount)?; + + ensure!( + T::Currency::free_balance(native_asset, who) >= native_fee_spot_price, + Error::::InsufficientNativeCurrencyBalance + ); + native_fee_spot_price + } else { + Balance::zero() + }; + + let transfer = AMMTransfer { + origin: who.clone(), + assets, + amount, + amount_b: buy_price, + discount, + discount_amount: discount_fee, + fee: (assets.asset_in, transfer_fee), + }; + + Ok(transfer) + } + + /// Execute buy. validate_buy must be called first. + /// Perform necessary storage/state changes. + /// Note : the execution should not return error as everything was previously verified and validated. + #[transactional] + fn execute_buy( + transfer: &AMMTransfer, + destination: Option<&T::AccountId>, + ) -> DispatchResult { + let pair_account = Self::get_pair_id(transfer.assets); + + if transfer.discount && transfer.discount_amount > 0 { + let native_asset = T::NativeAssetId::get(); + T::Currency::withdraw( + native_asset, + &transfer.origin, + transfer.discount_amount, + ExistenceRequirement::AllowDeath, + )?; + } + + T::Currency::transfer( + transfer.assets.asset_out, + &pair_account, + destination.unwrap_or(&transfer.origin), + transfer.amount, + ExistenceRequirement::AllowDeath, + )?; + T::Currency::transfer( + transfer.assets.asset_in, + &transfer.origin, + &pair_account, + transfer.amount_b + transfer.fee.1, + ExistenceRequirement::AllowDeath, + )?; + + let liquidity_in = T::Currency::total_balance(transfer.assets.asset_in, &pair_account); + let liquidity_out = T::Currency::total_balance(transfer.assets.asset_out, &pair_account); + T::AMMHandler::on_trade( + T::OracleSource::get(), + transfer.assets.asset_in, + transfer.assets.asset_out, + transfer.amount, + transfer.amount_b, + liquidity_in, + liquidity_out, + Ratio::new(liquidity_in, liquidity_out), + ) + .map_err(|(_w, e)| e)?; + + // TODO: Deprecated, remove when ready + Self::deposit_event(Event::::BuyExecuted { + who: transfer.origin.clone(), + asset_out: transfer.assets.asset_out, + asset_in: transfer.assets.asset_in, + amount: transfer.amount, + buy_price: transfer.amount_b, + fee_asset: transfer.fee.0, + fee_amount: transfer.fee.1, + pool: pair_account.clone(), + }); + + pallet_broadcast::Pallet::::deposit_trade_event( + transfer.origin.clone(), + pair_account.clone(), + pallet_broadcast::types::Filler::XYK(Self::share_token(&pair_account)), + pallet_broadcast::types::TradeOperation::ExactOut, + vec![Asset::new(transfer.assets.asset_in, transfer.amount)], + vec![Asset::new(transfer.assets.asset_out, transfer.amount_b)], + vec![Fee { + asset: transfer.fee.0, + amount: transfer.fee.1, + destination: Destination::Account(pair_account), + }], + ); + + Ok(()) + } + + fn get_min_trading_limit() -> Balance { + T::MinTradingLimit::get() + } + + fn get_min_pool_liquidity() -> Balance { + T::MinPoolLiquidity::get() + } + + fn get_max_in_ratio() -> u128 { + T::MaxInRatio::get() + } + + fn get_max_out_ratio() -> u128 { + T::MaxOutRatio::get() + } + + fn get_fee(_pool_account_id: &T::AccountId) -> (u32, u32) { + T::GetExchangeFee::get() + } +} + +pub struct AllowAllPools(); + +impl CanCreatePool for AllowAllPools { + fn can_create(_asset_a: AssetId, _asset_b: AssetId) -> bool { + true + } +} + +impl AMMPosition for Pallet { + type Error = DispatchError; + + fn get_liquidity_behind_shares( + asset_a: AssetId, + asset_b: AssetId, + shares_amount: Balance, + ) -> Result<(Balance, Balance), Self::Error> { + let asset_pair = AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }; + + let pair_account = Self::get_pair_id(asset_pair); + + let total_shares = Self::total_liquidity(&pair_account); + + let asset_a_reserve = T::Currency::free_balance(asset_a, &pair_account); + let asset_b_reserve = T::Currency::free_balance(asset_b, &pair_account); + + hydra_dx_math::xyk::calculate_liquidity_out(asset_a_reserve, asset_b_reserve, shares_amount, total_shares) + .map_err(|_| Error::::RemoveAssetAmountInvalid.into()) + } +} + +impl AMMAddLiquidity for Pallet { + fn add_liquidity( + who: T::AccountId, + asset_a: AssetId, + asset_b: AssetId, + amount_a: Balance, + amount_b_max_limit: Balance, + ) -> Result { + Self::do_add_liquidity(who, asset_a, asset_b, amount_a, amount_b_max_limit) + } +} diff --git a/pallets/xyk/src/tests/amm_position.rs b/pallets/xyk/src/tests/amm_position.rs new file mode 100644 index 00000000000..65196d4d306 --- /dev/null +++ b/pallets/xyk/src/tests/amm_position.rs @@ -0,0 +1,53 @@ +use super::mock::*; +use crate::types::AssetPair; +use crate::*; +use frame_support::assert_ok; + +#[test] +fn get_liquidity_behind_shares_should_return_both_assets_value_when_pool_exists() { + let asset_a = ACA; + let asset_b = DOT; + + ExtBuilder::default() + .with_accounts(vec![(ALICE, asset_a, 1_000 * ONE), (ALICE, asset_b, 1_000 * ONE)]) + .build() + .execute_with(|| { + //arange + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 100 * ONE, + asset_b, + 10 * ONE + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + + let share_token = XYK::share_token(pair_account); + + let shares_amount = Currency::free_balance(share_token, &ALICE); + + assert_eq!( + XYK::get_liquidity_behind_shares(asset_a, asset_b, shares_amount).unwrap(), + (100 * ONE, 10 * ONE) + ); + + assert_eq!( + XYK::get_liquidity_behind_shares(asset_b, asset_a, shares_amount).unwrap(), + (10 * ONE, 100 * ONE) + ); + + assert_eq!( + XYK::get_liquidity_behind_shares(asset_b, asset_a, shares_amount / 2).unwrap(), + (5 * ONE, 50 * ONE) + ); + + assert_eq!( + XYK::get_liquidity_behind_shares(asset_a, asset_b, shares_amount / 2).unwrap(), + (50 * ONE, 5 * ONE) + ); + }); +} diff --git a/pallets/xyk/src/tests/creation.rs b/pallets/xyk/src/tests/creation.rs new file mode 100644 index 00000000000..90c09ec3f9a --- /dev/null +++ b/pallets/xyk/src/tests/creation.rs @@ -0,0 +1,432 @@ +pub use super::mock::*; +use crate::{Error, Event}; +use frame_support::{assert_noop, assert_ok, BoundedVec}; +use hydradx_traits::AMM as AmmPool; +use orml_traits::MultiCurrency; +use pallet_asset_registry::AssetType; +use sp_std::convert::TryInto; + +use crate::types::AssetPair; + +#[test] +fn create_pool_should_work() { + new_test_ext().execute_with(|| { + let asset_a = HDX; + let asset_b = ACA; + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 100_000_000_000_000, + asset_b, + 10 * 100_000_000_000_000, + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + assert_eq!(XYK::get_pool_assets(&pair_account), Some(vec![asset_a, asset_b])); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 100000000000000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 1000000000000000); + assert_eq!(Currency::free_balance(asset_a, &ALICE), 900000000000000); + assert_eq!(Currency::free_balance(asset_b, &ALICE), 0); + assert_eq!(Currency::free_balance(share_token, &ALICE), 100000000000000); + assert_eq!(XYK::total_liquidity(pair_account), 100000000000000); + + let name: Vec = vec![232, 3, 0, 0, 72, 68, 84, 184, 11, 0, 0]; + let bounded_name: BoundedVec::StringLimit> = + name.try_into().unwrap(); + + expect_events(vec![ + pallet_asset_registry::Event::Registered { + asset_id: share_token, + asset_name: bounded_name, + asset_type: AssetType::XYK, + } + .into(), + Event::PoolCreated { + who: ALICE, + asset_a, + asset_b, + initial_shares_amount: 100000000000000, + share_token, + pool: pair_account, + } + .into(), + frame_system::Event::NewAccount { account: pair_account }.into(), + orml_tokens::Event::Endowed { + currency_id: asset_a, + who: pair_account, + amount: 100000000000000, + } + .into(), + orml_tokens::Event::Endowed { + currency_id: asset_b, + who: pair_account, + amount: 1000000000000000, + } + .into(), + orml_tokens::Event::Endowed { + currency_id: share_token, + who: ALICE, + amount: 100000000000000, + } + .into(), + ]); + }); +} + +#[test] +fn create_same_pool_should_not_work() { + new_test_ext().execute_with(|| { + let user = ALICE; + let asset_a = HDX; + let asset_b = ACA; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_b, + 1000, + asset_a, + 2000, + )); + assert_noop!( + XYK::create_pool(RuntimeOrigin::signed(user), asset_b, 999, asset_a, 2 * 999), + Error::::InsufficientLiquidity + ); + assert_noop!( + XYK::create_pool(RuntimeOrigin::signed(user), asset_b, 1000, asset_a, 0), + Error::::InsufficientLiquidity + ); + assert_noop!( + XYK::create_pool(RuntimeOrigin::signed(user), asset_a, 1000, asset_a, 2000), + Error::::CannotCreatePoolWithSameAssets + ); + assert_noop!( + XYK::create_pool(RuntimeOrigin::signed(user), asset_b, 1000, asset_a, 2000), + Error::::TokenPoolAlreadyExists + ); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + expect_events(vec![Event::PoolCreated { + who: ALICE, + asset_a: asset_b, + asset_b: asset_a, + initial_shares_amount: 2000, + share_token, + pool: pair_account, + } + .into()]); + }); +} + +#[test] +fn create_pool_with_insufficient_balance_should_not_work() { + new_test_ext().execute_with(|| { + let user = ALICE; + let asset_a = HDX; + + assert_noop!( + XYK::create_pool( + RuntimeOrigin::signed(user), + 4000, + 100_000_000_000_000, + asset_a, + 10 * 100_000_000_000_000, + ), + Error::::InsufficientAssetBalance + ); + + assert_noop!( + XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 100_000_000_000_000, + 4000, + 10 * 100_000_000_000_000, + ), + Error::::InsufficientAssetBalance + ); + }); +} + +#[test] +fn create_pool_with_insufficient_liquidity_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + XYK::create_pool(RuntimeOrigin::signed(ALICE), ACA, 500, HDX, 5000), + Error::::InsufficientLiquidity + ); + + assert_noop!( + XYK::create_pool(RuntimeOrigin::signed(ALICE), ACA, 5000, HDX, 500), + Error::::InsufficientLiquidity + ); + }); +} + +#[test] +fn create_pool_small_fixed_point_amount_should_work() { + new_test_ext().execute_with(|| { + let asset_a = HDX; + let asset_b = ACA; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 100_000_000_000_000, + asset_b, + 1_000_000_000, + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 100000000000000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 1000000000); + assert_eq!(Currency::free_balance(asset_a, &ALICE), 900000000000000); + assert_eq!(Currency::free_balance(asset_b, &ALICE), 999999000000000); + assert_eq!(Currency::free_balance(share_token, &ALICE), 100000000000000); + assert_eq!(XYK::total_liquidity(pair_account), 100000000000000); + + expect_events(vec![Event::PoolCreated { + who: ALICE, + asset_a, + asset_b, + initial_shares_amount: 100000000000000, + share_token, + pool: pair_account, + } + .into()]); + }); +} + +#[test] +fn destroy_pool_on_remove_liquidity_and_recreate_should_work() { + new_test_ext().execute_with(|| { + let user = ALICE; + let asset_a = HDX; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 100_000_000, + asset_b, + 1_000_000_000_000, + )); + + let asset_pair = AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }; + + let pair_account = XYK::get_pair_id(asset_pair); + let share_token = XYK::share_token(pair_account); + + assert!(XYK::exists(asset_pair)); + + assert_ok!(XYK::remove_liquidity( + RuntimeOrigin::signed(user), + asset_a, + asset_b, + 100_000_000 + )); + + assert_eq!(XYK::total_liquidity(pair_account), 0); + + assert!(!XYK::exists(asset_pair)); + + // It should be possible to recreate the pool again + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 100_000_000, + asset_b, + 1_000_000_000_000 + )); + + expect_events(vec![ + Event::PoolCreated { + who: user, + asset_a, + asset_b, + initial_shares_amount: 100_000_000, + share_token, + pool: pair_account, + } + .into(), + frame_system::Event::KilledAccount { account: pair_account }.into(), + Event::LiquidityRemoved { + who: user, + asset_a, + asset_b, + shares: 100_000_000, + } + .into(), + Event::PoolDestroyed { + who: user, + asset_a, + asset_b, + share_token, + pool: pair_account, + } + .into(), + frame_system::Event::NewAccount { account: pair_account }.into(), + orml_tokens::Event::Endowed { + currency_id: asset_a, + who: pair_account, + amount: 100000000, + } + .into(), + orml_tokens::Event::Endowed { + currency_id: asset_b, + who: pair_account, + amount: 1000000000000, + } + .into(), + orml_tokens::Event::Endowed { + currency_id: share_token, + who: ALICE, + amount: 100000000, + } + .into(), + Event::PoolCreated { + who: user, + asset_a, + asset_b, + initial_shares_amount: 100_000_000, + share_token, + pool: pair_account, + } + .into(), + ]); + }); +} + +#[test] +fn create_pool_with_same_assets_should_not_be_allowed() { + new_test_ext().execute_with(|| { + let user = ALICE; + let asset_a = HDX; + + assert_noop!( + XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 100_000_000, + asset_a, + 100_000_000_000_000_000_000 + ), + Error::::CannotCreatePoolWithSameAssets + ); + }) +} + +#[test] +fn can_create_pool_should_work() { + new_test_ext().execute_with(|| { + let asset_a = 10u32; + let asset_b = 10u32; + assert_noop!( + XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 100_000_000_000_000, + asset_b, + 1_000_000_000_000_000, + ), + Error::::CannotCreatePool + ); + }); +} + +#[test] +fn share_asset_id_should_be_offset() { + // Check that pools are created correctly with offset IDs. + new_test_ext().execute_with(|| { + // Arrange + let asset_pair = AssetPair { + asset_in: HDX, + asset_out: ACA, + }; + + // Next available asset id within the range of reserved IDs + let next_asset_id = AssetRegistry::next_asset_id() + .unwrap() + .checked_sub(::SequentialIdStartAt::get()) + .unwrap(); + + // Register the share token within the range of reserved IDs. + // This is how share tokens were registered before the offset was introduced. + assert_ok!(AssetRegistry::register( + RuntimeOrigin::signed(ALICE), + asset_pair.name(), + AssetType::XYK, + ::MinPoolLiquidity::get(), + Some(next_asset_id), + None, + None, + None, + )); + + // Create_pool doesn't register new share token if it already exists + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + HDX, + 100_000_000_000_000, + ACA, + 10 * 100_000_000_000_000, + )); + + let pair_account = XYK::get_pair_id(asset_pair); + let share_token = XYK::share_token(pair_account); + + assert_eq!(share_token, next_asset_id); + assert_eq!( + AssetRegistry::asset_ids::>(asset_pair.name().try_into().unwrap()) + .unwrap(), + share_token + ); + + // Act + let next_asset_id = AssetRegistry::next_asset_id().unwrap(); + + // Create new pool. The share token should be created with offset ID. + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + HDX, + 100_000_000_000_000, + DOT, + 10 * 100_000_000_000_000, + )); + + let asset_pair = AssetPair { + asset_in: HDX, + asset_out: DOT, + }; + + let pair_account = XYK::get_pair_id(asset_pair); + let share_token = XYK::share_token(pair_account); + + // Assert + assert_eq!(share_token, next_asset_id); + assert_eq!( + AssetRegistry::asset_ids::>(asset_pair.name().try_into().unwrap()) + .unwrap(), + share_token + ); + }); +} diff --git a/pallets/xyk/src/tests/fees.rs b/pallets/xyk/src/tests/fees.rs new file mode 100644 index 00000000000..a81c993a97c --- /dev/null +++ b/pallets/xyk/src/tests/fees.rs @@ -0,0 +1,606 @@ +pub use super::mock::*; +use crate::{Error, Event}; +use frame_support::{assert_noop, assert_ok}; +use hydradx_traits::AMM as AmmPool; +use orml_traits::MultiCurrency; +use pallet_broadcast::types::{Asset, Destination, Fee}; + +use crate::types::AssetPair; + +#[test] +fn fee_calculation() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(XYK::calculate_fee(100_000), Ok(200)); + assert_eq!(XYK::calculate_fee(10_000), Ok(20)); + + assert_eq!(XYK::calculate_discounted_fee(9_999), Ok(0)); + assert_eq!(XYK::calculate_discounted_fee(10_000), Ok(7)); + assert_eq!(XYK::calculate_discounted_fee(100_000), Ok(70)); + }); + ExtBuilder::default() + .with_exchange_fee((10, 1000)) + .with_discounted_fee((10, 1000)) + .build() + .execute_with(|| { + assert_eq!(XYK::calculate_fee(100_000), Ok(1_000)); + assert_eq!(XYK::calculate_fee(10_000), Ok(100)); + + assert_eq!(XYK::calculate_discounted_fee(999), Ok(0)); + assert_eq!(XYK::calculate_discounted_fee(1_000), Ok(10)); + assert_eq!(XYK::calculate_discounted_fee(10_000), Ok(100)); + }); + + ExtBuilder::default() + .with_exchange_fee((10, 0)) + .build() + .execute_with(|| { + assert_eq!(XYK::calculate_fee(100000), Ok(0)); + }); + + ExtBuilder::default() + .with_exchange_fee((10, 1)) + .build() + .execute_with(|| { + assert_noop!(XYK::calculate_fee(u128::MAX), Error::::FeeAmountInvalid); + }); +} + +#[test] +fn get_fee_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + HDX, + 1_000_000_000, + DOT, + 2_000_000_000, + )); + + // existing pool + let fee = XYK::get_fee(&HDX_DOT_POOL_ID); + assert_eq!(fee, (2, 1_000)); + // non existing pool + let fee = XYK::get_fee(&1_234); + assert_eq!(fee, (2, 1_000)); + }); +} + +#[test] +fn discount_sell_fees_should_work() { + let accounts = vec![ + (ALICE, HDX, 1_000_000_000_000_000u128), + (ALICE, ACA, 1_000_000_000_000_000u128), + (ALICE, DOT, 1_000_000_000_000_000u128), + ]; + + let asset_a = ACA; + let asset_b = DOT; + + let mut ext: sp_io::TestExternalities = ExtBuilder::default().with_accounts(accounts.clone()).build(); + ext.execute_with(|| System::set_block_number(1)); + ext.execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 1_000_000_000_000, + HDX, + 2_000_000_000_000, + )); + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 200_000_000_000_000, + asset_b, + 400_000_000_000_000, + )); + + let pair = AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }; + + let pair_account = XYK::get_pair_id(pair); + + let share_token = XYK::get_share_token(pair); + let native_pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: HDX, + }); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200_000_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 400_000_000_000_000); + assert_eq!(Currency::free_balance(asset_a, &native_pair_account), 1_000_000_000_000); + assert_eq!(Currency::free_balance(HDX, &native_pair_account), 2_000_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &ALICE), 799_000_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &ALICE), 600_000_000_000_000); + assert_eq!(Currency::free_balance(HDX, &ALICE), 998_000_000_000_000); + + assert_ok!(XYK::sell( + RuntimeOrigin::signed(ALICE), + asset_a, + asset_b, + 10_000_000, + 1_500, + true, + )); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200_000_010_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 399_999_980_013_994); + assert_eq!(Currency::free_balance(asset_a, &native_pair_account), 1_000_000_000_000); + assert_eq!(Currency::free_balance(HDX, &native_pair_account), 2_000_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &ALICE), 798_999_990_000_000); + assert_eq!(Currency::free_balance(asset_b, &ALICE), 600_000_019_986_006); + assert_eq!(Currency::free_balance(HDX, &ALICE), 997_999_999_972_014); + + expect_events(vec![ + Event::SellExecuted { + who: ALICE, + asset_in: asset_a, + asset_out: asset_b, + amount: 10_000_000, + sale_price: 19_986_006, + fee_asset: asset_b, + fee_amount: 13_993, + pool: pair_account, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: ALICE, + filler: pair_account, + filler_type: pallet_broadcast::types::Filler::XYK(share_token), + operation: pallet_broadcast::types::TradeOperation::ExactIn, + inputs: vec![Asset::new(asset_a, 10_000_000)], + outputs: vec![Asset::new(asset_b, 19_986_006)], + fees: vec![Fee::new(asset_b, 13_993, Destination::Account(pair_account))], + operation_stack: vec![], + } + .into(), + ]); + }); + + // 0.1% discount fee + let mut ext: sp_io::TestExternalities = ExtBuilder::default() + .with_accounts(accounts.clone()) + .with_discounted_fee((10, 10_000)) + .build(); + ext.execute_with(|| System::set_block_number(1)); + ext.execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 1_000_000_000_000, + HDX, + 2_000_000_000_000, + )); + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 200_000_000_000_000, + asset_b, + 400_000_000_000_000, + )); + + let pair = AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }; + let pair_account = XYK::get_pair_id(pair); + + let share_token = XYK::get_share_token(pair); + + let native_pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: HDX, + }); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200_000_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 400_000_000_000_000); + assert_eq!(Currency::free_balance(asset_a, &native_pair_account), 1_000_000_000_000); + assert_eq!(Currency::free_balance(HDX, &native_pair_account), 2_000_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &ALICE), 799_000_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &ALICE), 600_000_000_000_000); + assert_eq!(Currency::free_balance(HDX, &ALICE), 998_000_000_000_000); + + assert_ok!(XYK::sell( + RuntimeOrigin::signed(ALICE), + asset_a, + asset_b, + 10_000_000, + 1_500, + true, + )); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200_000_010_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 399_999_980_019_991); + assert_eq!(Currency::free_balance(asset_a, &native_pair_account), 1_000_000_000_000); + assert_eq!(Currency::free_balance(HDX, &native_pair_account), 2_000_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &ALICE), 798_999_990_000_000); + assert_eq!(Currency::free_balance(asset_b, &ALICE), 600_000_019_980_009); + assert_eq!(Currency::free_balance(HDX, &ALICE), 997_999_999_960_020); + + expect_events(vec![ + Event::SellExecuted { + who: ALICE, + asset_in: asset_a, + asset_out: asset_b, + amount: 10_000_000, + sale_price: 19_980_009, + fee_asset: asset_b, + fee_amount: 19_990, + pool: pair_account, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: ALICE, + filler: pair_account, + filler_type: pallet_broadcast::types::Filler::XYK(share_token), + operation: pallet_broadcast::types::TradeOperation::ExactIn, + inputs: vec![Asset::new(asset_a, 10_000_000)], + outputs: vec![Asset::new(asset_b, 19_980_009)], + fees: vec![Fee::new(asset_b, 19_990, Destination::Account(pair_account))], + operation_stack: vec![], + } + .into(), + ]); + }); + + // zero discount fee + let mut ext: sp_io::TestExternalities = ExtBuilder::default() + .with_accounts(accounts) + .with_discounted_fee((0, 0)) + .build(); + ext.execute_with(|| System::set_block_number(1)); + ext.execute_with(|| { + let asset_a = ACA; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 1_000_000_000_000, + HDX, + 2_000_000_000_000, + )); + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 200_000_000_000_000, + asset_b, + 400_000_000_000_000, + )); + + let pair = AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }; + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + + let share_token = XYK::get_share_token(pair); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200_000_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 400_000_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &ALICE), 799_000_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &ALICE), 600_000_000_000_000); + + assert_ok!(XYK::sell( + RuntimeOrigin::signed(ALICE), + asset_a, + asset_b, + 10_000_000, + 1_500, + true, + )); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200_000_010_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 399_999_980_000_001); + + assert_eq!(Currency::free_balance(asset_a, &ALICE), 798_999_990_000_000); + assert_eq!(Currency::free_balance(asset_b, &ALICE), 600_000_019_999_999); + + expect_events(vec![ + Event::SellExecuted { + who: ALICE, + asset_in: asset_a, + asset_out: asset_b, + amount: 10_000_000, + sale_price: 19_999_999, + fee_asset: asset_b, + fee_amount: 0, + pool: pair_account, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: ALICE, + filler: pair_account, + filler_type: pallet_broadcast::types::Filler::XYK(share_token), + operation: pallet_broadcast::types::TradeOperation::ExactIn, + inputs: vec![Asset::new(asset_a, 10_000_000)], + outputs: vec![Asset::new(asset_b, 19_999_999)], + fees: vec![Fee::new(asset_b, 0, Destination::Account(pair_account))], + operation_stack: vec![], + } + .into(), + ]); + }); +} + +#[test] +fn discount_buy_fees_should_work() { + let accounts = vec![ + (ALICE, HDX, 1_000_000_000_000_000u128), + (ALICE, ACA, 1_000_000_000_000_000u128), + (ALICE, DOT, 1_000_000_000_000_000u128), + ]; + + let asset_a = ACA; + let asset_b = DOT; + + let mut ext: sp_io::TestExternalities = ExtBuilder::default().with_accounts(accounts.clone()).build(); + ext.execute_with(|| System::set_block_number(1)); + ext.execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 1_000_000_000_000, + HDX, + 2_000_000_000_000, + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 200_000_000_000_000, + asset_b, + 400_000_000_000_000, + )); + + let native_pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: HDX, + }); + + let pair = AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }; + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + + let share_token = XYK::get_share_token(pair); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200_000_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 400_000_000_000_000); + assert_eq!(Currency::free_balance(asset_a, &native_pair_account), 1_000_000_000_000); + assert_eq!(Currency::free_balance(HDX, &native_pair_account), 2_000_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &ALICE), 799_000_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &ALICE), 600_000_000_000_000); + assert_eq!(Currency::free_balance(HDX, &ALICE), 998_000_000_000_000); + + assert_ok!(XYK::buy( + RuntimeOrigin::signed(ALICE), + asset_a, + asset_b, + 10_000_000, + 1_000_000_000_000, + true, + )); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 199_999_990_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 400_000_020_014_002); + assert_eq!(Currency::free_balance(asset_a, &native_pair_account), 1_000_000_000_000); + assert_eq!(Currency::free_balance(HDX, &native_pair_account), 2_000_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &ALICE), 799_000_010_000_000); + assert_eq!(Currency::free_balance(asset_b, &ALICE), 599_999_979_985_998); // compare to values in previous test to see difference! + assert_eq!(Currency::free_balance(HDX, &ALICE), 997_999_999_972_000); + + expect_events(vec![ + Event::BuyExecuted { + who: ALICE, + asset_in: asset_b, + asset_out: asset_a, + amount: 10_000_000, + buy_price: 20_000_002, + fee_asset: asset_b, + fee_amount: 14_000, + pool: pair_account, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: ALICE, + filler: pair_account, + filler_type: pallet_broadcast::types::Filler::XYK(share_token), + operation: pallet_broadcast::types::TradeOperation::ExactOut, + inputs: vec![Asset::new(asset_b, 10_000_000)], + outputs: vec![Asset::new(asset_a, 20_000_002)], + fees: vec![Fee::new(asset_b, 14_000, Destination::Account(pair_account))], + operation_stack: vec![], + } + .into(), + ]); + }); + + // 0.1% discount fee + let mut ext: sp_io::TestExternalities = ExtBuilder::default() + .with_accounts(accounts.clone()) + .with_discounted_fee((10, 10_000)) + .build(); + ext.execute_with(|| System::set_block_number(1)); + ext.execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 1_000_000_000_000, + HDX, + 2_000_000_000_000, + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 200_000_000_000_000, + asset_b, + 400_000_000_000_000, + )); + + let native_pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: HDX, + }); + + let pair = AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }; + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + + let share_token = XYK::get_share_token(pair); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200_000_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 400_000_000_000_000); + assert_eq!(Currency::free_balance(asset_a, &native_pair_account), 1_000_000_000_000); + assert_eq!(Currency::free_balance(HDX, &native_pair_account), 2_000_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &ALICE), 799_000_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &ALICE), 600_000_000_000_000); + assert_eq!(Currency::free_balance(HDX, &ALICE), 998_000_000_000_000); + + assert_ok!(XYK::buy( + RuntimeOrigin::signed(ALICE), + asset_a, + asset_b, + 10_000_000, + 1_000_000_000_000, + true, + )); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 199_999_990_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 400_000_020_020_002); + assert_eq!(Currency::free_balance(asset_a, &native_pair_account), 1_000_000_000_000); + assert_eq!(Currency::free_balance(HDX, &native_pair_account), 2_000_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &ALICE), 799_000_010_000_000); + assert_eq!(Currency::free_balance(asset_b, &ALICE), 599_999_979_979_998); // compare to values in previous test to see difference! + assert_eq!(Currency::free_balance(HDX, &ALICE), 997_999_999_960_000); + + expect_events(vec![ + Event::BuyExecuted { + who: ALICE, + asset_in: asset_b, + asset_out: asset_a, + amount: 10_000_000, + buy_price: 20_000_002, + fee_asset: asset_b, + fee_amount: 20_000, + pool: pair_account, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: ALICE, + filler: pair_account, + filler_type: pallet_broadcast::types::Filler::XYK(share_token), + operation: pallet_broadcast::types::TradeOperation::ExactOut, + inputs: vec![Asset::new(asset_b, 10_000_000)], + outputs: vec![Asset::new(asset_a, 20_000_002)], + fees: vec![Fee::new(asset_b, 20_000, Destination::Account(pair_account))], + operation_stack: vec![], + } + .into(), + ]); + }); + + // zero discount fee + let mut ext: sp_io::TestExternalities = ExtBuilder::default() + .with_accounts(accounts) + .with_discounted_fee((0, 0)) + .build(); + ext.execute_with(|| System::set_block_number(1)); + ext.execute_with(|| { + let asset_a = ACA; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 1_000_000_000_000, + HDX, + 2_000_000_000_000, + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 200_000_000_000_000, + asset_b, + 400_000_000_000_000, + )); + + let pair = AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }; + let pair_account = XYK::get_pair_id(pair); + + let share_token = XYK::get_share_token(pair); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200_000_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 400_000_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &ALICE), 799_000_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &ALICE), 600_000_000_000_000); + + assert_ok!(XYK::buy( + RuntimeOrigin::signed(ALICE), + asset_a, + asset_b, + 10_000_000, + 1_000_000_000, + true, + )); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 199_999_990_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 400_000_020_000_002); + + assert_eq!(Currency::free_balance(asset_a, &ALICE), 799_000_010_000_000); + assert_eq!(Currency::free_balance(asset_b, &ALICE), 599_999_979_999_998); + + expect_events(vec![ + Event::BuyExecuted { + who: ALICE, + asset_in: asset_b, + asset_out: asset_a, + amount: 10_000_000, + buy_price: 20_000_002, + fee_asset: asset_b, + fee_amount: 0, + pool: pair_account, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: ALICE, + filler: pair_account, + filler_type: pallet_broadcast::types::Filler::XYK(share_token), + operation: pallet_broadcast::types::TradeOperation::ExactOut, + inputs: vec![Asset::new(asset_b, 10_000_000)], + outputs: vec![Asset::new(asset_a, 20_000_002)], + fees: vec![Fee::new(asset_b, 0, Destination::Account(pair_account))], + operation_stack: vec![], + } + .into(), + ]); + }); +} diff --git a/pallets/xyk/src/tests/invariants.rs b/pallets/xyk/src/tests/invariants.rs new file mode 100644 index 00000000000..f552e7598df --- /dev/null +++ b/pallets/xyk/src/tests/invariants.rs @@ -0,0 +1,560 @@ +use super::mock::*; +use crate::*; + +use proptest::prelude::*; + +use frame_support::assert_ok; +use primitive_types::U256; +use sp_runtime::{FixedPointNumber, FixedU128}; + +const TOLERANCE: Balance = 1_000; + +#[macro_export] +macro_rules! assert_eq_approx { + ( $x:expr, $y:expr, $z:expr, $r:expr) => {{ + let diff = if $x >= $y { $x - $y } else { $y - $x }; + if diff > $z { + panic!("\n{} not equal\n left: {:?}\nright: {:?}\n", $r, $x, $y); + } + }}; +} + +fn asset_reserve() -> impl Strategy { + 1000 * ONE..10_000_000 * ONE +} + +fn trade_amount() -> impl Strategy { + ONE..100 * ONE +} + +fn price() -> impl Strategy { + 0.1f64..2f64 +} + +fn assert_asset_invariant( + old_state: (Balance, Balance), + new_state: (Balance, Balance), + tolerance: FixedU128, + desc: &str, +) { + let new_s = U256::from(new_state.0) * U256::from(new_state.1); + let s1 = new_s.integer_sqrt(); + + let old_s = U256::from(old_state.0) * U256::from(old_state.1); + let s2 = old_s.integer_sqrt(); + + assert!(new_s >= old_s, "Invariant decreased for {desc}"); + + let s1_u128 = Balance::try_from(s1).unwrap(); + let s2_u128 = Balance::try_from(s2).unwrap(); + + let invariant = FixedU128::from((s1_u128, ONE)) / FixedU128::from((s2_u128, ONE)); + assert_eq_approx!(invariant, FixedU128::from(1u128), tolerance, desc); +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1000))] + #[test] + fn add_liquidity(initial_liquidity in asset_reserve(), + added_liquidity in asset_reserve(), + price in price(), + ) { + let asset_a = HDX; + let asset_b = DOT; + + ExtBuilder::default() + .with_exchange_fee((0, 0)) + .with_accounts(vec![ + (ALICE, asset_a,initial_liquidity), + (ALICE, asset_b,initial_liquidity * 1000), + (BOB, asset_a, added_liquidity), + (BOB, asset_b, added_liquidity * 1_000_000), + ]) + .build() + .execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + initial_liquidity, + asset_b, + FixedU128::from_float(price).saturating_mul_int(initial_liquidity), + )); + + let pool_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pool_account); + + let pool_balance_a = Currency::free_balance(asset_a, &pool_account); + let pool_balance_b = Currency::free_balance(asset_b, &pool_account); + + let bob_balance_a = Currency::free_balance(asset_a, &BOB); + let bob_balance_b = Currency::free_balance(asset_b, &BOB); + + let issuance = XYK::total_liquidity(pool_account); + + assert_ok!(XYK::add_liquidity( + RuntimeOrigin::signed(BOB), + asset_a, + asset_b, + added_liquidity, + added_liquidity * 1_000_000, // do not care about the limit here + )); + + let new_pool_balance_a = Currency::free_balance(asset_a, &pool_account); + let new_pool_balance_b = Currency::free_balance(asset_b, &pool_account); + + let new_bob_balance_a = Currency::free_balance(asset_a, &BOB); + let new_bob_balance_b = Currency::free_balance(asset_b, &BOB); + + let bob_shares = Currency::free_balance(share_token, &BOB); + + let p0 = FixedU128::from((pool_balance_a, pool_balance_b)); + let p1 = FixedU128::from((new_pool_balance_a, new_pool_balance_b)); + + // Price should not change + assert_eq_approx!( + p0, + p1, + FixedU128::from_float(0.0000000001), + "Price has changed after add liquidity" + ); + + // The following must hold when adding liquidity. + // delta_S / S <= delta_X / X + // delta_S / S <= delta_Y / Y + // where S is total share issuance, X is asset a and Y is asset b + + let s = U256::from(issuance); + let delta_s = U256::from(bob_shares); + let delta_x = U256::from(bob_balance_a - new_bob_balance_a); + let delta_y = U256::from(bob_balance_b - new_bob_balance_b); + let x = U256::from(pool_balance_a); + let y = U256::from(pool_balance_b); + + let left = delta_s * x; + let right = s * delta_x; + + assert!(left <= right); + + let l = FixedU128::from((bob_shares, issuance)); + let r = FixedU128::from((bob_balance_a - new_bob_balance_a, pool_balance_a)); + + let diff = r - l; + + assert!(diff <= FixedU128::from_float(0.000000001)); + + let left = delta_s * y; + let right = s * delta_y; + + assert!(left <= right); + + let l = FixedU128::from((bob_shares, issuance)); + let r = FixedU128::from((bob_balance_b - new_bob_balance_b, pool_balance_b)); + + let diff = r - l; + + assert!(diff <= FixedU128::from_float(0.000000001)); + }); + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1000))] + #[test] + fn remove_liquidity(initial_liquidity in asset_reserve(), + added_liquidity in asset_reserve(), + price in price(), + ) { + let asset_a = HDX; + let asset_b = DOT; + + ExtBuilder::default() + .with_exchange_fee((0, 0)) + .with_accounts(vec![ + (ALICE, asset_a,initial_liquidity), + (ALICE, asset_b,initial_liquidity * 1000), + (BOB, asset_a, added_liquidity), + (BOB, asset_b, added_liquidity * 1_000_000), + ]) + .build() + .execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + initial_liquidity, + asset_b, + FixedU128::from_float(price).saturating_mul_int(initial_liquidity), + )); + + let pool_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pool_account); + + assert_ok!(XYK::add_liquidity( + RuntimeOrigin::signed(BOB), + asset_a, + asset_b, + added_liquidity, + added_liquidity * 1_000_000, // do not care about the limit here + )); + let pool_balance_a = Currency::free_balance(asset_a, &pool_account); + let pool_balance_b = Currency::free_balance(asset_b, &pool_account); + + let bob_balance_a = Currency::free_balance(asset_a, &BOB); + let bob_balance_b = Currency::free_balance(asset_b, &BOB); + + let bob_shares = Currency::free_balance(share_token, &BOB); + + let issuance = XYK::total_liquidity(pool_account); + + assert_ok!(XYK::remove_liquidity( + RuntimeOrigin::signed(BOB), + asset_a, + asset_b, + bob_shares, + )); + + let new_pool_balance_a = Currency::free_balance(asset_a, &pool_account); + let new_pool_balance_b = Currency::free_balance(asset_b, &pool_account); + + let new_bob_balance_a = Currency::free_balance(asset_a, &BOB); + let new_bob_balance_b = Currency::free_balance(asset_b, &BOB); + + let p0 = FixedU128::from((pool_balance_a, pool_balance_b)); + let p1 = FixedU128::from((new_pool_balance_a, new_pool_balance_b)); + + // Price should not change + assert_eq_approx!( + p0, + p1, + FixedU128::from_float(0.0000000001), + "Price has changed after remove liquidity" + ); + + let s = U256::from(issuance); + let delta_s = U256::from(bob_shares); + let delta_x = U256::from(new_bob_balance_a - bob_balance_a); + let delta_y = U256::from(new_bob_balance_b - bob_balance_b); + let x = U256::from(pool_balance_a); + let y = U256::from(pool_balance_b); + + let left = delta_s * x; + let right = s * delta_x; + + assert!(left >= right); + + let l = FixedU128::from((bob_shares, issuance)); + let r = FixedU128::from((new_bob_balance_a - bob_balance_a, pool_balance_a)); + + let diff = l - r; + + assert!(diff <= FixedU128::from_float(0.000000001)); + + let left = delta_s * y; + let right = s * delta_y; + + assert!(left >= right); + + let l = FixedU128::from((bob_shares, issuance)); + let r = FixedU128::from((new_bob_balance_b - bob_balance_b, pool_balance_b)); + + let diff = l - r; + + assert!(diff <= FixedU128::from_float(0.000000001)) + }); + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1000))] + #[test] + fn sell_invariant(initial_liquidity in asset_reserve(), + added_liquidity in asset_reserve(), + amount in trade_amount(), + price in price(), + ) { + let asset_a = HDX; + let asset_b = DOT; + + ExtBuilder::default() + .with_exchange_fee((0, 0)) + .with_accounts(vec![ + (ALICE, asset_a,initial_liquidity), + (ALICE, asset_b,initial_liquidity * 1000), + (BOB, asset_a, added_liquidity), + (BOB, asset_b, added_liquidity * 1_000_000), + (CHARLIE, asset_a, amount), + ]) + .build() + .execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + initial_liquidity, + asset_b, + FixedU128::from_float(price).saturating_mul_int(initial_liquidity), + )); + + let pool_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + + assert_ok!(XYK::add_liquidity( + RuntimeOrigin::signed(BOB), + asset_a, + asset_b, + added_liquidity, + added_liquidity * 1_000_000, // do not care about the limit here + )); + let pool_balance_a = Currency::free_balance(asset_a, &pool_account); + let pool_balance_b = Currency::free_balance(asset_b, &pool_account); + + assert_ok!(XYK::sell( + RuntimeOrigin::signed(CHARLIE), + asset_a, + asset_b, + amount, + 0u128, // limit not interesting here, + false, + )); + + let new_pool_balance_a = Currency::free_balance(asset_a, &pool_account); + let new_pool_balance_b = Currency::free_balance(asset_b, &pool_account); + + assert_asset_invariant((pool_balance_a, pool_balance_b), + (new_pool_balance_a, new_pool_balance_b), + FixedU128::from((TOLERANCE,ONE)), + "sell" + ); + + }); + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1000))] + #[test] + fn buy_invariant(initial_liquidity in asset_reserve(), + added_liquidity in asset_reserve(), + amount in trade_amount(), + price in price(), + ) { + let asset_a = ACA; + let asset_b = DOT; + + ExtBuilder::default() + .with_exchange_fee((0, 0)) + .with_accounts(vec![ + (ALICE, asset_a,initial_liquidity * 1000), + (ALICE, HDX,initial_liquidity), + (ALICE, asset_b,initial_liquidity * 1000), + (BOB, asset_a, added_liquidity), + (BOB, asset_b, added_liquidity * 1_000_000), + (CHARLIE, asset_a, amount * 1_000), + (CHARLIE, HDX, amount * 1_000), + ]) + .build() + .execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + initial_liquidity, + asset_b, + FixedU128::from_float(price).saturating_mul_int(initial_liquidity), + )); + + let pool_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + + assert_ok!(XYK::add_liquidity( + RuntimeOrigin::signed(BOB), + asset_a, + asset_b, + added_liquidity, + added_liquidity * 1_000_000, // do not care about the limit here + )); + let pool_balance_a = Currency::free_balance(asset_a, &pool_account); + let pool_balance_b = Currency::free_balance(asset_b, &pool_account); + + assert_ok!(XYK::buy( + RuntimeOrigin::signed(CHARLIE), + asset_b, + asset_a, + amount, + u128::MAX, // limit not interesting here, + false, + )); + + let new_pool_balance_a = Currency::free_balance(asset_a, &pool_account); + let new_pool_balance_b = Currency::free_balance(asset_b, &pool_account); + + assert_asset_invariant((pool_balance_a, pool_balance_b), + (new_pool_balance_a, new_pool_balance_b), + FixedU128::from((TOLERANCE,ONE)), + "buy" + ); + + }); + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1000))] + #[test] + fn buy_invariant_with_discount(initial_liquidity in asset_reserve(), + added_liquidity in asset_reserve(), + amount in trade_amount(), + price in price(), + ) { + let asset_a = ACA; + let asset_b = DOT; + + ExtBuilder::default() + .with_exchange_fee((0, 0)) + .with_discounted_fee((0,0)) + .with_accounts(vec![ + (ALICE, asset_a,initial_liquidity * 1000), + (ALICE, HDX,initial_liquidity), + (ALICE, asset_b,initial_liquidity * 1000), + (BOB, asset_a, added_liquidity), + (BOB, asset_b, added_liquidity * 1_000_000), + (CHARLIE, asset_a, amount * 1_000), + (CHARLIE, HDX, amount * 1_000), + ]) + .build() + .execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + initial_liquidity, + asset_b, + FixedU128::from_float(price).saturating_mul_int(initial_liquidity), + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_b, + 10 * ONE, + HDX, + 10 * ONE, + )); + + let pool_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + + assert_ok!(XYK::add_liquidity( + RuntimeOrigin::signed(BOB), + asset_a, + asset_b, + added_liquidity, + added_liquidity * 1_000_000, // do not care about the limit here + )); + let _pool_balance_a = Currency::free_balance(asset_a, &pool_account); + let _pool_balance_b = Currency::free_balance(asset_b, &pool_account); + + assert_ok!(XYK::buy( + RuntimeOrigin::signed(CHARLIE), + asset_b, + asset_a, + amount, + u128::MAX, // limit not interesting here, + true, + )); + + let _new_pool_balance_a = Currency::free_balance(asset_a, &pool_account); + let _new_pool_balance_b = Currency::free_balance(asset_b, &pool_account); + + assert_asset_invariant((_pool_balance_a, _pool_balance_b), + (_new_pool_balance_a, _new_pool_balance_b), + FixedU128::from((TOLERANCE,ONE)), + "buy with discount" + ); + }); + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1000))] + #[test] + fn sell_invariant_with_discount(initial_liquidity in asset_reserve(), + added_liquidity in asset_reserve(), + amount in trade_amount(), + price in price(), + ) { + let asset_a = ACA; + let asset_b = DOT; + + ExtBuilder::default() + .with_exchange_fee((0, 0)) + .with_discounted_fee((0,0)) + .with_accounts(vec![ + (ALICE, asset_a,initial_liquidity * 1000), + (ALICE, HDX,initial_liquidity), + (ALICE, asset_b,initial_liquidity * 1000), + (BOB, asset_a, added_liquidity), + (BOB, asset_b, added_liquidity * 1_000_000), + (CHARLIE, asset_a, amount * 1_000), + (CHARLIE, HDX, amount * 1_000), + ]) + .build() + .execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + initial_liquidity, + asset_b, + FixedU128::from_float(price).saturating_mul_int(initial_liquidity), + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 10 * ONE, + HDX, + 10 * ONE, + )); + + let pool_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + + assert_ok!(XYK::add_liquidity( + RuntimeOrigin::signed(BOB), + asset_a, + asset_b, + added_liquidity, + added_liquidity * 1_000_000, // do not care about the limit here + )); + let _pool_balance_a = Currency::free_balance(asset_a, &pool_account); + let _pool_balance_b = Currency::free_balance(asset_b, &pool_account); + + assert_ok!(XYK::sell( + RuntimeOrigin::signed(CHARLIE), + asset_a, + asset_b, + amount, + 0u128, // limit not interesting here, + true, + )); + + let _new_pool_balance_a = Currency::free_balance(asset_a, &pool_account); + let _new_pool_balance_b = Currency::free_balance(asset_b, &pool_account); + + assert_asset_invariant((_pool_balance_a, _pool_balance_b), + (_new_pool_balance_a, _new_pool_balance_b), + FixedU128::from((TOLERANCE,ONE)), + "sell with discount" + ); + }); + } +} diff --git a/pallets/xyk/src/tests/liquidity.rs b/pallets/xyk/src/tests/liquidity.rs new file mode 100644 index 00000000000..efe0f7833ce --- /dev/null +++ b/pallets/xyk/src/tests/liquidity.rs @@ -0,0 +1,689 @@ +pub use super::mock::*; +use crate::types::{AssetPair, Balance}; +use crate::{Error, Event}; +use frame_support::{assert_noop, assert_ok}; +use hydradx_traits::AMM as AmmPool; +use orml_traits::MultiCurrency; + +#[test] +fn add_liquidity_should_work() { + new_test_ext().execute_with(|| { + let user = ALICE; + let asset_a = DOT; + let asset_b = HDX; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 100_000_000, + asset_b, + 65_400_000 + )); + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + assert_eq!(Currency::free_balance(asset_b, &pair_account), 65_400_000); + assert_eq!(XYK::total_liquidity(pair_account), 65400000); + + assert_ok!(XYK::add_liquidity( + RuntimeOrigin::signed(user), + asset_a, + asset_b, + 400_000, + 1_000_000_000_000 + )); + + assert_eq!(Currency::free_balance(share_token, &user), 65661600); + + assert_eq!(Currency::free_balance(asset_b, &pair_account), 65_661_601); + assert_eq!(Currency::free_balance(asset_a, &pair_account), 100400000); + assert_eq!(Currency::free_balance(asset_a, &user), 999999899600000); + assert_eq!(XYK::total_liquidity(pair_account), 65661600); + + expect_events(vec![ + Event::PoolCreated { + who: ALICE, + asset_a, + asset_b, + initial_shares_amount: 65400000, + share_token, + pool: pair_account, + } + .into(), + Event::LiquidityAdded { + who: ALICE, + asset_a, + asset_b, + amount_a: 400000, + amount_b: 261601, + } + .into(), + ]); + }); +} + +#[test] +fn add_liquidity_mints_correct_shares() { + new_test_ext().execute_with(|| { + let user = ALICE; + let asset_a = DOT; + let asset_b = HDX; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 100_000_000, + asset_b, + 65_400_000 + )); + + assert_ok!(XYK::add_liquidity( + RuntimeOrigin::signed(user), + asset_b, + asset_a, + 261600, + 1_000_000_000_000 + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + assert_eq!(Currency::free_balance(share_token, &user), 65661600); + }); +} + +#[test] +fn add_liquidity_as_another_user_should_work() { + new_test_ext().execute_with(|| { + let user = ALICE; + let asset_a = HDX; + let asset_b = ACA; + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_b, + 100_000_000, + asset_a, + 1_000_000_000_000 + )); + assert_ok!(XYK::add_liquidity( + RuntimeOrigin::signed(user), + asset_b, + asset_a, + 400_000, + 1_000_000_000_000 + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 1004000000001); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 100400000); + assert_eq!(Currency::free_balance(asset_b, &user), 999999899600000); + assert_eq!(Currency::free_balance(share_token, &user), 1004000000000); + assert_eq!(XYK::total_liquidity(pair_account), 1004000000000); + + assert_ok!(XYK::add_liquidity( + RuntimeOrigin::signed(BOB), + asset_b, + asset_a, + 1_000_000, + 1_000_000_000_000 + )); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 1014000000002); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 101400000); + assert_eq!(Currency::free_balance(asset_b, &user), 999999899600000); + assert_eq!(Currency::free_balance(asset_b, &BOB), 999999999000000); + assert_eq!(Currency::free_balance(share_token, &user), 1004000000000); + assert_eq!(Currency::free_balance(share_token, &BOB), 10000000000); + assert_eq!(XYK::total_liquidity(pair_account), 1014000000000); + + expect_events(vec![ + Event::PoolCreated { + who: ALICE, + asset_a: asset_b, + asset_b: asset_a, + initial_shares_amount: 1000000000000, + share_token, + pool: pair_account, + } + .into(), + Event::LiquidityAdded { + who: ALICE, + asset_a: asset_b, + asset_b: asset_a, + amount_a: 400000, + amount_b: 4000000001, + } + .into(), + orml_tokens::Event::Endowed { + currency_id: share_token, + who: 2, + amount: 10000000000, + } + .into(), + Event::LiquidityAdded { + who: BOB, + asset_a: asset_b, + asset_b: asset_a, + amount_a: 1000000, + amount_b: 10000000001, + } + .into(), + ]); + }); +} + +#[test] +fn add_liquidity_should_work_when_limit_is_set_above_account_balance() { + new_test_ext().execute_with(|| { + let user = ALICE; + let asset_a = DOT; + let asset_b = HDX; + let amount_b_max_limit = 2_000_000_000_000_000; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 100_000_000, + asset_b, + 100_000_000, + )); + + assert!(Currency::free_balance(asset_b, &user) < amount_b_max_limit); + + assert_ok!(XYK::add_liquidity( + RuntimeOrigin::signed(user), + asset_a, + asset_b, + 400_000, + amount_b_max_limit, + )); + }); +} + +#[test] +fn remove_liquidity_should_work() { + new_test_ext().execute_with(|| { + let user = ALICE; + let asset_a = HDX; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 100_000_000, + asset_b, + 1_000_000_000_000 + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + assert_eq!(Currency::free_balance(share_token, &user), 100000000); + assert_eq!(Currency::free_balance(asset_a, &user), 999999900000000); + assert_eq!(Currency::free_balance(asset_a, &pair_account), 100000000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 1000000000000); + + assert_ok!(XYK::remove_liquidity( + RuntimeOrigin::signed(user), + asset_a, + asset_b, + 355_000 + )); + + assert_eq!(Currency::free_balance(asset_b, &pair_account), 996450000000); + assert_eq!(Currency::free_balance(asset_a, &user), 999999900355000); + + assert_eq!(Currency::free_balance(share_token, &user), 99645000); + assert_eq!(XYK::total_liquidity(pair_account), 99645000); + + expect_events(vec![ + Event::PoolCreated { + who: ALICE, + asset_a, + asset_b, + initial_shares_amount: 100000000, + share_token, + pool: pair_account, + } + .into(), + Event::LiquidityRemoved { + who: ALICE, + asset_a, + asset_b, + shares: 355_000, + } + .into(), + ]); + }); +} + +#[test] +fn remove_liquidity_without_shares_should_not_work() { + new_test_ext().execute_with(|| { + let user = ALICE; + let asset_a = HDX; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 100_000_000, + asset_b, + 100_000_000, + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + let shares = Currency::free_balance(share_token, &user); + + assert_ok!(Currency::transfer( + RuntimeOrigin::signed(ALICE), + BOB, + share_token, + shares + )); + + assert_noop!( + XYK::remove_liquidity(RuntimeOrigin::signed(user), asset_a, asset_b, 355_000), + Error::::InsufficientAssetBalance + ); + + expect_events(vec![ + Event::PoolCreated { + who: ALICE, + asset_a, + asset_b, + initial_shares_amount: 100000000, + share_token, + pool: pair_account, + } + .into(), + orml_tokens::Event::Endowed { + currency_id: share_token, + who: BOB, + amount: shares, + } + .into(), + orml_tokens::Event::Transfer { + currency_id: share_token, + from: ALICE, + to: BOB, + amount: shares, + } + .into(), + ]); + }); +} + +// events in the following test do not occur during standard chain operation +#[test] +fn remove_liquidity_from_reduced_pool_should_not_work() { + new_test_ext().execute_with(|| { + let user = ALICE; + let asset_a = HDX; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 100_000_000, + asset_b, + 100_000_000, + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + + // remove some amount from the pool + assert_ok!(Currency::transfer( + RuntimeOrigin::signed(pair_account), + BOB, + asset_a, + 90_000_000 + )); + + assert_noop!( + XYK::remove_liquidity(RuntimeOrigin::signed(user), asset_a, asset_b, 200_000_000), + Error::::InsufficientLiquidity + ); + + // return it back to the pool + assert_ok!(Currency::transfer( + RuntimeOrigin::signed(BOB), + pair_account, + asset_a, + 90_000_000 + )); + // do it again with asset_b + assert_ok!(Currency::transfer( + RuntimeOrigin::signed(pair_account), + BOB, + asset_b, + 90_000_000 + )); + + assert_noop!( + XYK::remove_liquidity(RuntimeOrigin::signed(user), asset_a, asset_b, 200_000_000), + Error::::InsufficientLiquidity + ); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + expect_events(vec![ + Event::PoolCreated { + who: ALICE, + asset_a, + asset_b, + initial_shares_amount: 100000000, + share_token, + pool: pair_account, + } + .into(), + orml_tokens::Event::Transfer { + currency_id: asset_a, + from: pair_account, + to: BOB, + amount: 90_000_000, + } + .into(), + orml_tokens::Event::Transfer { + currency_id: asset_a, + from: BOB, + to: pair_account, + amount: 90_000_000, + } + .into(), + orml_tokens::Event::Transfer { + currency_id: asset_b, + from: pair_account, + to: BOB, + amount: 90_000_000, + } + .into(), + ]); + }); +} + +#[test] +fn add_liquidity_more_than_owner_should_not_work() { + new_test_ext().execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + HDX, + 200_000_000, + ACA, + 600_000_000_000_000, + )); + + assert_eq!(Currency::free_balance(ACA, &ALICE), 400_000_000_000_000); + + assert_noop!( + XYK::add_liquidity( + RuntimeOrigin::signed(ALICE), + HDX, + ACA, + 200_000_000_000_000_000, + 600_000_000 + ), + Error::::InsufficientAssetBalance + ); + + assert_noop!( + XYK::add_liquidity( + RuntimeOrigin::signed(ALICE), + HDX, + ACA, + 600_000_000, + 200_000_000_000_000_000 + ), + Error::::InsufficientAssetBalance + ); + }); +} + +#[test] +fn add_insufficient_liquidity_should_not_work() { + new_test_ext().execute_with(|| { + assert_ok!(XYK::create_pool(RuntimeOrigin::signed(ALICE), HDX, 1000, ACA, 1500,)); + + assert_noop!( + XYK::add_liquidity(RuntimeOrigin::signed(ALICE), HDX, ACA, 0, 0), + Error::::InsufficientTradingAmount + ); + + assert_noop!( + XYK::add_liquidity(RuntimeOrigin::signed(ALICE), HDX, ACA, 1000, 0), + Error::::ZeroLiquidity + ); + + assert_noop!( + XYK::add_liquidity(RuntimeOrigin::signed(BOB), ACA, HDX, 1000, 2000), + Error::::InsufficientLiquidity + ); + }); +} + +#[test] +fn add_liquidity_exceeding_max_limit_should_not_work() { + new_test_ext().execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + HDX, + 100_000_000_000_000, + ACA, + 100_000_000_000_000, + )); + + assert_noop!( + XYK::add_liquidity(RuntimeOrigin::signed(ALICE), HDX, ACA, 10_000_000, 1_000_000), + Error::::AssetAmountExceededLimit + ); + }); +} +#[test] +fn remove_liquidity_should_respect_min_pool_limit() { + new_test_ext().execute_with(|| { + assert_ok!(XYK::create_pool(RuntimeOrigin::signed(ALICE), HDX, 1000, ACA, 1500,)); + + assert_ok!(XYK::add_liquidity(RuntimeOrigin::signed(BOB), ACA, HDX, 2000, 2000)); + + assert_noop!( + XYK::remove_liquidity(RuntimeOrigin::signed(BOB), ACA, HDX, 500), + Error::::InsufficientLiquidity + ); + }); +} + +#[test] +fn remove_zero_liquidity_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + XYK::remove_liquidity(RuntimeOrigin::signed(ALICE), HDX, ACA, 0), + Error::::ZeroLiquidity + ); + }); +} + +#[test] +fn add_liquidity_to_non_existing_pool_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + XYK::add_liquidity( + RuntimeOrigin::signed(ALICE), + HDX, + ACA, + 200_000_000_000_000_000, + 600_000_000 + ), + Error::::TokenPoolNotFound + ); + }); +} + +#[test] +fn remove_zero_liquidity_from_non_existing_pool_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + XYK::remove_liquidity(RuntimeOrigin::signed(ALICE), HDX, ACA, 100), + Error::::TokenPoolNotFound + ); + }); +} + +#[test] +fn add_liquidity_overflow_work() { + let user = ALICE; + let asset_a = DOT; + let asset_b = HDX; + ExtBuilder::default() + .with_accounts(vec![(ALICE, DOT, Balance::MAX), (ALICE, HDX, Balance::MAX)]) + .build() + .execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 100_000, + asset_b, + 10_u128.pow(38) + )); + + assert_noop!( + XYK::add_liquidity( + RuntimeOrigin::signed(user), + asset_a, + asset_b, + 10_u128.pow(33), + 1_000_000_000_000 + ), + Error::::AddAssetAmountInvalid + ); + }); +} + +#[test] +fn share_ratio_calculations_are_correct() { + ExtBuilder::default() + .with_exchange_fee((0, 0)) + .build() + .execute_with(|| { + let asset_a = HDX; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + 100 * ONE, + asset_b, + 65_440_000_000_000, + )); + + assert_eq!(Currency::free_balance(asset_a, &BOB), 1_000 * ONE); + assert_eq!(Currency::free_balance(asset_b, &BOB), 1_000 * ONE); + + let balance_a = Currency::free_balance(asset_a, &BOB); + let balance_b = Currency::free_balance(asset_b, &BOB); + + let bob_initial_balance = balance_a + balance_b; + + assert_eq!(bob_initial_balance, 2000 * ONE); + + assert_ok!(XYK::add_liquidity( + RuntimeOrigin::signed(BOB), + asset_b, + asset_a, + 10 * ONE, + 200 * ONE + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + let expected_shares = 15_281_173_594_132u128; + + assert_eq!(Currency::free_balance(share_token, &BOB), expected_shares); + + assert_ok!(XYK::sell( + RuntimeOrigin::signed(CHARLIE), + asset_a, + asset_b, + 10 * ONE, + 0u128, + false, + )); + + assert_ok!(XYK::remove_liquidity( + RuntimeOrigin::signed(BOB), + asset_a, + asset_b, + expected_shares + )); + + assert_eq!(Currency::free_balance(share_token, &BOB), 0); + + for _ in 0..10 { + let balance_a = Currency::free_balance(asset_a, &BOB); + let balance_b = Currency::free_balance(asset_b, &BOB); + + let bob_previous_balance = balance_a + balance_b; + + let balance_pool_a = Currency::free_balance(asset_a, &pair_account); + let balance_pool_b = Currency::free_balance(asset_a, &pair_account); + + let initial_pool_liquidity = balance_pool_a + balance_pool_b; + + assert_ok!(XYK::add_liquidity( + RuntimeOrigin::signed(BOB), + asset_b, + asset_a, + 10 * ONE, + 200 * ONE + )); + + let shares = Currency::free_balance(share_token, &BOB); + + assert_ok!(XYK::remove_liquidity( + RuntimeOrigin::signed(BOB), + asset_a, + asset_b, + shares + )); + let balance_a = Currency::free_balance(asset_a, &BOB); + let balance_b = Currency::free_balance(asset_b, &BOB); + let bob_new_balance = balance_a + balance_b; + + let balance_pool_a = Currency::free_balance(asset_a, &pair_account); + let balance_pool_b = Currency::free_balance(asset_a, &pair_account); + + let total_pool_liquidity = balance_pool_a + balance_pool_b; + + assert!(bob_new_balance <= bob_previous_balance); + assert!(initial_pool_liquidity <= total_pool_liquidity); + } + }); +} diff --git a/pallets/xyk/src/tests/mock.rs b/pallets/xyk/src/tests/mock.rs new file mode 100644 index 00000000000..d936f53fa62 --- /dev/null +++ b/pallets/xyk/src/tests/mock.rs @@ -0,0 +1,359 @@ +// This file is part of HydraDX-node. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate as xyk; +use crate::*; +use frame_support::parameter_types; +use frame_system as system; +use orml_traits::parameter_type_with_key; +use sp_core::H256; +use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup, One}, + BuildStorage, +}; + +use crate::types::{AssetId, Balance}; +use frame_support::traits::{Everything, Get, Nothing}; +use hydradx_traits::{AssetPairAccountIdFor, CanCreatePool, Source}; + +use frame_system::EnsureSigned; +use hydradx_traits::pools::DustRemovalAccountWhitelist; +use std::cell::RefCell; + +pub type Amount = i128; +pub type AccountId = u64; + +pub const ALICE: AccountId = 1; +pub const BOB: AccountId = 2; +pub const CHARLIE: AccountId = 3; +pub const TREASURY: AccountId = 4; + +pub const HDX: AssetId = 1000; +pub const DOT: AssetId = 2000; +pub const ACA: AssetId = 3000; + +pub const HDX_DOT_POOL_ID: AccountId = 1_002_000; + +pub const ONE: Balance = 1_000_000_000_000; + +type Block = frame_system::mocking::MockBlock; + +type AssetLocation = u8; + +frame_support::construct_runtime!( + pub enum Test + { + System: frame_system, + XYK: xyk, + Currency: orml_tokens, + AssetRegistry: pallet_asset_registry, + Broadcast: pallet_broadcast, + } + +); + +thread_local! { + static EXCHANGE_FEE: RefCell<(u32, u32)> = const { RefCell::new((2, 1_000)) }; + static DISCOUNTED_FEE: RefCell<(u32, u32)> = const { RefCell::new((7, 10_000)) }; + static MAX_OUT_RATIO: RefCell = const { RefCell::new(3) }; +} + +struct ExchangeFee; +impl Get<(u32, u32)> for ExchangeFee { + fn get() -> (u32, u32) { + EXCHANGE_FEE.with(|v| *v.borrow()) + } +} + +struct DiscountedFee; +impl Get<(u32, u32)> for DiscountedFee { + fn get() -> (u32, u32) { + DISCOUNTED_FEE.with(|v| *v.borrow()) + } +} + +struct MaximumOutRatio; +impl Get for MaximumOutRatio { + fn get() -> u128 { + MAX_OUT_RATIO.with(|v| *v.borrow()) + } +} + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 63; + pub const NativeAssetId: AssetId = HDX; + #[derive(PartialEq, Debug)] + pub RegistryStringLimit: u32 = 100; + #[derive(PartialEq, Debug)] + pub MinRegistryStringLimit: u32 = 2; + pub const SequentialIdOffset: u32 = 1_000_000; + pub const StoreFees: Balance = 10 * ONE; + pub const FeesBeneficiarry: u64 = TREASURY; +} + +impl pallet_asset_registry::Config for Test { + type RuntimeEvent = RuntimeEvent; + type RegistryOrigin = EnsureSigned; + type AssetId = AssetId; + type Balance = Balance; + type AssetNativeLocation = AssetLocation; + type StringLimit = RegistryStringLimit; + type SequentialIdStartAt = SequentialIdOffset; + type NativeAssetId = NativeAssetId; + type WeightInfo = (); +} + +impl system::Config for Test { + type BaseCallFilter = Everything; + type BlockWeights = (); + type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; + type Nonce = u64; + type Block = Block; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; + type SingleBlockMigrations = (); + type MultiBlockMigrator = (); + type PreInherents = (); + type PostInherents = (); + type PostTransactions = (); + type ExtensionsWeightInfo = (); +} + +parameter_type_with_key! { + pub ExistentialDeposits: |_currency_id: AssetId| -> Balance { + One::one() + }; +} + +impl orml_tokens::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type Amount = Amount; + type CurrencyId = AssetId; + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; + type MaxLocks = (); + type DustRemovalWhitelist = Nothing; + type ReserveIdentifier = (); + type MaxReserves = (); + type CurrencyHooks = (); +} + +pub struct AssetPairAccountIdTest(); + +impl AssetPairAccountIdFor for AssetPairAccountIdTest { + fn from_assets(asset_a: AssetId, asset_b: AssetId, _: &str) -> u64 { + let mut a = asset_a as u128; + let mut b = asset_b as u128; + if a > b { + std::mem::swap(&mut a, &mut b) + } + (a * 1000 + b) as u64 + } +} + +parameter_types! { + pub const MinTradingLimit: Balance = 1_000; + pub const MinPoolLiquidity: Balance = 1_000; + pub const MaxInRatio: u128 = 3; + pub MaxOutRatio: u128 = MaximumOutRatio::get(); + pub ExchangeFeeRate: (u32, u32) = ExchangeFee::get(); + pub DiscountedFeeRate: (u32, u32) = DiscountedFee::get(); + pub const OracleSourceIdentifier: Source = *b"hydraxyk"; +} + +pub struct Disallow10_10Pool(); + +impl CanCreatePool for Disallow10_10Pool { + fn can_create(asset_a: AssetId, asset_b: AssetId) -> bool { + !matches!((asset_a, asset_b), (10u32, 10u32)) + } +} + +pub struct MockAMMHandler(); + +impl basilisk_traits::OnCreatePoolHandler for MockAMMHandler { + fn on_create_pool(_asset_a: AssetId, _asset_b: AssetId) -> sp_runtime::DispatchResult { + Ok(()) + } +} + +impl hydradx_traits::OnCreatePoolHandler for MockAMMHandler { + fn on_create_pool(_asset_a: AssetId, _asset_b: AssetId) -> sp_runtime::DispatchResult { + Ok(()) + } +} + +impl basilisk_traits::OnTradeHandler for MockAMMHandler { + fn on_trade( + _source: hydradx_traits::Source, + _asset_a: AssetId, + _asset_b: AssetId, + _amount_a: Balance, + _amount_b: Balance, + _liquidity_a: Balance, + _liquidity_b: Balance, + _price: basilisk_math::ratio::Ratio, + ) -> Result { + Ok(frame_support::weights::Weight::zero()) + } + + fn on_trade_weight() -> frame_support::weights::Weight { + frame_support::weights::Weight::zero() + } +} + +impl basilisk_traits::OnLiquidityChangedHandler for MockAMMHandler { + fn on_liquidity_changed( + _source: hydradx_traits::Source, + _asset_a: AssetId, + _asset_b: AssetId, + _amount_a: Balance, + _amount_b: Balance, + _liquidity_a: Balance, + _liquidity_b: Balance, + _price: basilisk_math::ratio::Ratio, + ) -> Result { + Ok(frame_support::weights::Weight::zero()) + } + + fn on_liquidity_changed_weight() -> frame_support::weights::Weight { + frame_support::weights::Weight::zero() + } +} + +impl pallet_broadcast::Config for Test { + type RuntimeEvent = RuntimeEvent; +} + +impl xyk::Config for Test { + type RuntimeEvent = RuntimeEvent; + type AssetRegistry = AssetRegistry; + type AssetPairAccountId = AssetPairAccountIdTest; + type Currency = Currency; + type NativeAssetId = NativeAssetId; + type WeightInfo = (); + type GetExchangeFee = ExchangeFeeRate; + type MinTradingLimit = MinTradingLimit; + type MinPoolLiquidity = MinPoolLiquidity; + type MaxInRatio = MaxInRatio; + type MaxOutRatio = MaxOutRatio; + type CanCreatePool = Disallow10_10Pool; + type AMMHandler = MockAMMHandler; + type DiscountedFee = DiscountedFeeRate; + type NonDustableWhitelistHandler = Whitelist; + type OracleSource = OracleSourceIdentifier; +} + +pub struct ExtBuilder { + endowed_accounts: Vec<(AccountId, AssetId, Balance)>, +} + +// Returns default values for genesis config +impl Default for ExtBuilder { + fn default() -> Self { + Self { + endowed_accounts: vec![ + (ALICE, HDX, 1_000_000_000_000_000u128), + (BOB, HDX, 1_000_000_000_000_000u128), + (ALICE, ACA, 1_000_000_000_000_000u128), + (BOB, ACA, 1_000_000_000_000_000u128), + (ALICE, DOT, 1_000_000_000_000_000u128), + (BOB, DOT, 1_000_000_000_000_000u128), + (CHARLIE, HDX, 1_000_000_000_000_000u128), + ], + } + } +} + +impl ExtBuilder { + // builds genesis config + + pub fn with_accounts(mut self, accounts: Vec<(AccountId, AssetId, Balance)>) -> Self { + self.endowed_accounts = accounts; + self + } + + pub fn with_exchange_fee(self, f: (u32, u32)) -> Self { + EXCHANGE_FEE.with(|v| *v.borrow_mut() = f); + self + } + + pub fn with_discounted_fee(self, f: (u32, u32)) -> Self { + DISCOUNTED_FEE.with(|v| *v.borrow_mut() = f); + self + } + + pub fn with_max_out_ratio(self, f: u128) -> Self { + MAX_OUT_RATIO.with(|v| *v.borrow_mut() = f); + self + } + + pub fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + + orml_tokens::GenesisConfig:: { + balances: self.endowed_accounts, + } + .assimilate_storage(&mut t) + .unwrap(); + + t.into() + } +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut ext = ExtBuilder::default().build(); + ext.execute_with(|| System::set_block_number(1)); + ext +} + +pub fn expect_events(e: Vec) { + e.into_iter().for_each(frame_system::Pallet::::assert_has_event); +} + +pub struct Whitelist; + +impl DustRemovalAccountWhitelist for Whitelist { + type Error = DispatchError; + + fn add_account(_account: &AccountId) -> Result<(), Self::Error> { + Ok(()) + } + + fn remove_account(_account: &AccountId) -> Result<(), Self::Error> { + Ok(()) + } +} diff --git a/pallets/xyk/src/tests/mod.rs b/pallets/xyk/src/tests/mod.rs new file mode 100644 index 00000000000..1bc9a4421b9 --- /dev/null +++ b/pallets/xyk/src/tests/mod.rs @@ -0,0 +1,8 @@ +mod amm_position; +mod creation; +mod fees; +mod invariants; +mod liquidity; +pub(crate) mod mock; +mod spot_price; +mod trades; diff --git a/pallets/xyk/src/tests/spot_price.rs b/pallets/xyk/src/tests/spot_price.rs new file mode 100644 index 00000000000..725514506ce --- /dev/null +++ b/pallets/xyk/src/tests/spot_price.rs @@ -0,0 +1,174 @@ +#![allow(clippy::excessive_precision)] + +use super::mock::*; +use crate::types::{AssetPair, Price}; +use crate::XYKSpotPrice; +use crate::*; +use basilisk_traits::router::PoolType; +use basilisk_traits::router::TradeExecution; +use frame_support::assert_ok; +use frame_support::dispatch::RawOrigin; +use frame_support::storage::with_transaction; +use hydradx_traits::pools::SpotPriceProvider; +use sp_runtime::FixedPointNumber; +use sp_runtime::FixedU128; +use sp_runtime::TransactionOutcome; +#[test] +fn spot_price_provider_should_return_correct_price_when_pool_exists() { + let asset_a = ACA; + let asset_b = DOT; + + let initial = 99_000_000_000_000u128; + + ExtBuilder::default() + .with_accounts(vec![(ALICE, asset_a, initial), (ALICE, asset_b, initial)]) + .build() + .execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + initial, + asset_b, + 39_600_000_000_000 + )); + + let price = XYKSpotPrice::::spot_price(asset_a, asset_b); + + assert_eq!(price, Some(Price::from_float(2.5))); // 99_000 / 39_600 = 2.5 + }); +} + +#[test] +fn spot_price_provider_should_return_none_when_pool_does_not_exist() { + let asset_a = ACA; + let asset_b = DOT; + + ExtBuilder::default().build().execute_with(|| { + let price = XYKSpotPrice::::spot_price(asset_a, asset_b); + + assert_eq!(price, None); + }); +} + +#[test] +fn spot_price_provider_should_return_none_when_asset_reserve_is_zero() { + let asset_a = ACA; + let asset_b = DOT; + + let initial = 99_000_000_000_000u128; + + ExtBuilder::default() + .with_accounts(vec![(ALICE, asset_a, initial), (ALICE, asset_b, initial)]) + .build() + .execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + initial, + asset_b, + 39_600_000_000_000 + )); + + let pool_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + + // Force the pool balance to be zero in this test + assert_ok!(Currency::set_balance( + RawOrigin::Root.into(), + pool_account, + asset_b, + 0u128, + 0u128 + )); + + let price = XYKSpotPrice::::spot_price(asset_a, asset_b); + + assert_eq!(price, None); + }); +} + +#[test] +fn compare_sell_spot_price_with_and_without_fee() { + let asset_a = ACA; + let asset_b = DOT; + + let initial_a = 1000 * ONE; + let initial_b = 500 * ONE; + + ExtBuilder::default() + .with_accounts(vec![(ALICE, asset_a, initial_a * 2), (ALICE, asset_b, initial_b)]) + .build() + .execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + asset_a, + initial_a, + asset_b, + initial_b + )); + + let spot_price_without_fee = XYKSpotPrice::::spot_price(asset_a, asset_b).unwrap(); + + let sell_amount = 1000; + let received = with_transaction::(|| { + assert_eq!(Currency::free_balance(asset_b, &ALICE), 0); + assert_ok!(XYK::sell( + RuntimeOrigin::signed(ALICE), + asset_a, + asset_b, + sell_amount, + 0, + false, + )); + let received = Currency::free_balance(asset_b, &ALICE); + assert_eq!(received, 499); + TransactionOutcome::Rollback(Ok(received)) + }) + .unwrap(); + + //Check spot price without fee + let calculated_amount_out_without_fee = spot_price_without_fee + .reciprocal() + .unwrap() + .checked_mul_int(sell_amount) + .unwrap(); + let difference = calculated_amount_out_without_fee - received; + let relative_difference_without_fee = FixedU128::from_rational(difference, received); + let tolerated_difference = FixedU128::from_rational(1, 100); + // The difference of the amount out calculated with spot price should be less than 1% + assert_eq!( + relative_difference_without_fee, + FixedU128::from_float(0.002004008016032064) + ); + assert!(relative_difference_without_fee < tolerated_difference); + + //Check spot price with fee + let spot_price_with_fee = XYK::calculate_spot_price_with_fee(PoolType::XYK, asset_a, asset_b).unwrap(); + let calculated_amount_out_with_fee = spot_price_with_fee + .reciprocal() + .unwrap() + .checked_mul_int(sell_amount) + .unwrap(); + let difference = calculated_amount_out_with_fee - received; + let relative_difference_with_fee = FixedU128::from_rational(difference, received); + let tolerated_difference = FixedU128::from_rational(1, 100); + + assert_eq_approx!( + relative_difference_with_fee, + FixedU128::from_float(0.000000000000000000), + FixedU128::from((2, (ONE / 10_000))), + "the relative difference is not as expected" + ); + assert!(relative_difference_with_fee < tolerated_difference); + + //Compare the two + assert!(relative_difference_with_fee < relative_difference_without_fee); + + assert!( + spot_price_with_fee > spot_price_without_fee, + "Spot price with fee should be smaller than without fee" + ); + }); +} diff --git a/pallets/xyk/src/tests/trades.rs b/pallets/xyk/src/tests/trades.rs new file mode 100644 index 00000000000..a2ec5364797 --- /dev/null +++ b/pallets/xyk/src/tests/trades.rs @@ -0,0 +1,1183 @@ +pub use super::mock::*; +use crate::{AMMTransfer, Error, Event}; +use frame_support::{assert_noop, assert_ok}; +use hydradx_traits::AMM as AmmPool; +use orml_traits::MultiCurrency; +use pallet_broadcast::types::{Asset, Destination, Fee}; + +use crate::types::AssetPair; + +#[test] +fn sell_test() { + new_test_ext().execute_with(|| { + let user_1 = ALICE; + let asset_a = ACA; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user_1), + asset_a, + 200_000_000_000, + asset_b, + 600_000_000_000_000, + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999800000000000); + assert_eq!(Currency::free_balance(asset_b, &user_1), 400000000000000); + assert_eq!(Currency::free_balance(share_token, &user_1), 600000000000000); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200000000000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 600000000000000); + + assert_ok!(XYK::sell( + RuntimeOrigin::signed(user_1), + asset_a, + asset_b, + 456_444_678, + 1000000000000, + false, + )); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999799543555322); + assert_eq!(Currency::free_balance(asset_b, &user_1), 401363483591788); + assert_eq!(Currency::free_balance(share_token, &user_1), 600000000000000); + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200456444678); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 598636516408212); + + expect_events(vec![ + Event::PoolCreated { + who: ALICE, + asset_a, + asset_b, + initial_shares_amount: 600000000000000, + share_token, + pool: pair_account, + } + .into(), + Event::SellExecuted { + who: ALICE, + asset_in: asset_a, + asset_out: asset_b, + amount: 456444678, + sale_price: 1363483591788, + fee_asset: asset_b, + fee_amount: 2732432046, + pool: pair_account, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: ALICE, + filler: pair_account, + filler_type: pallet_broadcast::types::Filler::XYK(share_token), + operation: pallet_broadcast::types::TradeOperation::ExactIn, + inputs: vec![Asset::new(asset_a, 456444678)], + outputs: vec![Asset::new(asset_b, 1363483591788)], + fees: vec![Fee::new(asset_b, 2732432046, Destination::Account(pair_account))], + operation_stack: vec![], + } + .into(), + ]); + }); +} + +#[test] +fn execute_sell_should_use_event_id() { + new_test_ext().execute_with(|| { + let user_1 = ALICE; + let asset_a = ACA; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user_1), + asset_a, + 200_000_000_000, + asset_b, + 600_000_000_000_000, + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + + let share_token = XYK::share_token(pair_account); + + let t = AMMTransfer { + origin: user_1, + assets: AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }, + amount: 456_444_678, + amount_b: 1363483591788, + discount: false, + discount_amount: 0_u128, + fee: (asset_b, 2732432046), + }; + + assert_ok!(XYK::execute_sell(&t)); + + expect_events(vec![ + Event::SellExecuted { + who: ALICE, + asset_in: asset_a, + asset_out: asset_b, + amount: 456444678, + sale_price: 1363483591788, + fee_asset: asset_b, + fee_amount: 2732432046, + pool: pair_account, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: ALICE, + filler: pair_account, + filler_type: pallet_broadcast::types::Filler::XYK(share_token), + operation: pallet_broadcast::types::TradeOperation::ExactIn, + inputs: vec![Asset::new(asset_a, 456444678)], + outputs: vec![Asset::new(asset_b, 1363483591788)], + fees: vec![Fee::new(asset_b, 2732432046, Destination::Account(pair_account))], + operation_stack: vec![], + } + .into(), + ]); + }); +} + +#[test] +fn work_flow_happy_path_should_work() { + new_test_ext().execute_with(|| { + let user_1 = ALICE; + let user_2 = BOB; + let asset_a = HDX; + let asset_b = ACA; + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + + // Check initial balances + + assert_eq!(Currency::free_balance(asset_a, &user_1), 1000000000000000); + assert_eq!(Currency::free_balance(asset_b, &user_2), 1000000000000000); + assert_eq!(Currency::free_balance(asset_a, &pair_account), 0); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user_1), + asset_a, + 350_000_000_000, + asset_b, + 14_000_000_000_000, + )); + + // User 1 really tries! + assert_noop!( + XYK::add_liquidity( + RuntimeOrigin::signed(user_1), + asset_a, + asset_b, + 800_000_000_000_000_000, + 100 + ), + Error::::InsufficientAssetBalance + ); + + // Total liquidity + assert_eq!(XYK::total_liquidity(pair_account), 350_000_000_000); + + let share_token = XYK::share_token(pair_account); + + // Check balance after add liquidity for user 1 and user 2 + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999_650_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &user_1), 986_000_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &user_2), 1_000_000_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &user_2), 1_000_000_000_000_000); + + assert_eq!(Currency::free_balance(share_token, &user_1), 350_000_000_000); + assert_eq!(Currency::free_balance(share_token, &user_2), 0); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 350_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 14_000_000_000_000); + + // User 2 adds liquidity + let current_b_balance = Currency::free_balance(asset_b, &user_2); + assert_ok!(XYK::add_liquidity( + RuntimeOrigin::signed(user_2), + asset_a, + asset_b, + 300_000_000_000, + current_b_balance + )); + + assert_eq!(XYK::total_liquidity(pair_account), 650_000_000_000); + + // Check balance after add liquidity for user 1 and user 2 + assert_eq!(Currency::free_balance(asset_a, &user_1), 999_650_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &user_1), 986_000_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &user_2), 999_700_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &user_2), 988_000_000_000_000 - 1); // - 1 because of liquidity_in rounds up in favor of pool + + assert_eq!(Currency::free_balance(share_token, &user_1), 350_000_000_000); + assert_eq!(Currency::free_balance(share_token, &user_2), 300_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 650_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 26_000_000_000_001); + + // User 2 SELLs + assert_ok!(XYK::sell( + RuntimeOrigin::signed(user_2), + asset_a, + asset_b, + 216_666_666_666, + 100_000_000_000, + false, + )); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999_650_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &user_1), 986_000_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &user_2), 999_483_333_333_334); + assert_eq!(Currency::free_balance(asset_b, &user_2), 994_486_999_999_986); + + assert_eq!(Currency::free_balance(share_token, &user_1), 350_000_000_000); + assert_eq!(Currency::free_balance(share_token, &user_2), 300_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 866_666_666_666); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 19_513_000_000_014); + + // User 1 SELLs + assert_ok!(XYK::sell( + RuntimeOrigin::signed(user_1), + asset_a, + asset_b, + 288_888_888_888, + 100_000_000_000, + false, + )); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999_361_111_111_112); + assert_eq!(Currency::free_balance(asset_b, &user_1), 990_868_493_499_997); + + let user_2_original_balance_1 = Currency::free_balance(asset_a, &user_2); + let user_2_original_balance_2 = Currency::free_balance(asset_b, &user_2); + + assert_eq!(user_2_original_balance_1, 999_483_333_333_334); + assert_eq!(user_2_original_balance_2, 994_486_999_999_986); + + assert_eq!(Currency::free_balance(share_token, &user_1), 350_000_000_000); + assert_eq!(Currency::free_balance(share_token, &user_2), 300_000_000_000); + + // User 2 removes liquidity + + assert_ok!(XYK::remove_liquidity( + RuntimeOrigin::signed(user_2), + asset_a, + asset_b, + 10_000 + )); + + let user_2_remove_1_balance_1 = Currency::free_balance(asset_a, &user_2); + let user_2_remove_1_balance_2 = Currency::free_balance(asset_b, &user_2); + + assert_eq!(user_2_remove_1_balance_1, 999_483_333_351_111); + assert_eq!(user_2_remove_1_balance_2, 994_487_000_225_286); + assert_eq!(Currency::free_balance(share_token, &user_2), 299_999_990_000); + + assert_ok!(XYK::remove_liquidity( + RuntimeOrigin::signed(user_2), + asset_b, + asset_a, + 10_000 + )); + + let user_2_remove_2_balance_1 = Currency::free_balance(asset_a, &user_2); + let user_2_remove_2_balance_2 = Currency::free_balance(asset_b, &user_2); + + assert_eq!(user_2_remove_2_balance_1, 999_483_333_368_888); + assert_eq!(user_2_remove_2_balance_2, 994_487_000_450_586); + assert_eq!(Currency::free_balance(share_token, &user_2), 299_999_980_000); + + // The two removes should be equal (this could slip by 1 because of rounding error) + + assert_eq!( + user_2_remove_1_balance_1 - user_2_original_balance_1, + user_2_remove_2_balance_1 - user_2_remove_1_balance_1 + ); + + assert_eq!( + user_2_remove_1_balance_2 - user_2_original_balance_2, + user_2_remove_2_balance_2 - user_2_remove_1_balance_2 + ); + + assert_eq!(XYK::total_liquidity(pair_account), 649_999_980_000); + + assert_ok!(XYK::remove_liquidity( + RuntimeOrigin::signed(user_2), + asset_a, + asset_b, + 18_000 + )); + assert_eq!(Currency::free_balance(share_token, &user_2), 299_999_962_000); + + assert_eq!(XYK::total_liquidity(pair_account), 649_999_962_000); + + expect_events(vec![ + Event::PoolCreated { + who: user_1, + asset_a, + asset_b, + initial_shares_amount: 350_000_000_000, + share_token, + pool: pair_account, + } + .into(), + orml_tokens::Event::Endowed { + currency_id: share_token, + who: 2, + amount: 300000000000, + } + .into(), + Event::LiquidityAdded { + who: user_2, + asset_a, + asset_b, + amount_a: 300_000_000_000, + amount_b: 12_000_000_000_001, + } + .into(), + ]); + }); +} + +#[test] +fn sell_with_correct_fees_should_work() { + let accounts = vec![ + (ALICE, HDX, 1_000_000_000_000_000u128), + (BOB, HDX, 1_000_000_000_000_000u128), + (ALICE, ACA, 1_000_000_000_000_000u128), + (BOB, ACA, 1_000_000_000_000_000u128), + (ALICE, DOT, 1_000_000_000_000_000u128), + (BOB, DOT, 1_000_000_000_000_000u128), + ]; + + let mut ext: sp_io::TestExternalities = ExtBuilder::default().with_accounts(accounts).build(); + ext.execute_with(|| System::set_block_number(1)); + ext.execute_with(|| { + let user_1 = ALICE; + let user_2 = BOB; + let asset_a = ACA; + let asset_b = HDX; + + // Verify initial balances + assert_eq!(Currency::free_balance(asset_a, &user_1), 1_000_000_000_000_000); + assert_eq!(Currency::free_balance(asset_a, &user_2), 1_000_000_000_000_000); + + assert_eq!(Currency::free_balance(asset_b, &user_1), 1_000_000_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &user_2), 1_000_000_000_000_000); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user_1), + asset_a, + 10_000_000, + asset_b, + 2_000_000_000, + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999999990000000); + assert_eq!(Currency::free_balance(asset_b, &user_1), 999998000000000); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 10000000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 2000000000); + + assert_eq!(Currency::free_balance(share_token, &user_1), 2000000000); + + assert_ok!(XYK::sell( + RuntimeOrigin::signed(user_1), + asset_a, + asset_b, + 100_000, + 1_000_000, + false, + )); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 10100000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 1980237622); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999999989900000); + assert_eq!(Currency::free_balance(asset_b, &user_1), 999998019762378); + expect_events(vec![ + Event::PoolCreated { + who: user_1, + asset_a, + asset_b, + initial_shares_amount: 2000000000, + share_token, + pool: pair_account, + } + .into(), + Event::SellExecuted { + who: user_1, + asset_in: asset_a, + asset_out: asset_b, + amount: 100_000, + sale_price: 19_762_378, + fee_asset: asset_b, + fee_amount: 39_602, + pool: pair_account, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: user_1, + filler: pair_account, + filler_type: pallet_broadcast::types::Filler::XYK(share_token), + operation: pallet_broadcast::types::TradeOperation::ExactIn, + inputs: vec![Asset::new(asset_a, 100_000)], + outputs: vec![Asset::new(asset_b, 19_762_378)], + fees: vec![Fee::new(asset_b, 39_602, Destination::Account(pair_account))], + operation_stack: vec![], + } + .into(), + ]); + }); +} + +#[test] +fn sell_without_sufficient_balance_should_not_work() { + new_test_ext().execute_with(|| { + let user = ALICE; + let asset_a = ACA; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 1_000_000_000, + asset_b, + 1_000_000_000, + )); + + assert_ok!(Currency::transfer( + RuntimeOrigin::signed(user), + BOB, + ACA, + 999_998_999_999_999 + )); + + assert_noop!( + XYK::sell(RuntimeOrigin::signed(user), ACA, DOT, 1_000, 100, false), + Error::::InsufficientAssetBalance + ); + }); +} + +#[test] +fn sell_without_sufficient_discount_balance_should_not_work() { + new_test_ext().execute_with(|| { + let user = ALICE; + let asset_a = ACA; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 1_000_000_000_000, + asset_b, + 1_000_000_000_000, + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 1_000_000_000_000, + HDX, + 1_000_000_000_000, + )); + + assert_ok!(Currency::transfer( + RuntimeOrigin::signed(user), + BOB, + HDX, + 998_999_999_999_999 + )); + + assert_noop!( + XYK::sell(RuntimeOrigin::signed(user), ACA, DOT, 1_000_000_000, 100, true), + Error::::InsufficientNativeCurrencyBalance + ); + }); +} + +#[test] +fn buy_without_sufficient_balance_should_not_work() { + new_test_ext().execute_with(|| { + let user = ALICE; + let asset_a = ACA; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 1_000_000_000, + asset_b, + 1_000_000_000, + )); + + assert_ok!(Currency::transfer( + RuntimeOrigin::signed(user), + BOB, + ACA, + 999_998_999_999_999 + )); + + assert_noop!( + XYK::buy(RuntimeOrigin::signed(user), DOT, ACA, 1_000, 10_000, false), + Error::::InsufficientAssetBalance + ); + }); +} + +#[test] +fn buy_without_sufficient_discount_balance_should_not_work() { + new_test_ext().execute_with(|| { + let user = ALICE; + let asset_a = ACA; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_a, + 1_000_000_000_000, + asset_b, + 1_000_000_000_000, + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user), + asset_b, + 1_000_000_000_000, + HDX, + 1_000_000_000_000, + )); + + assert_ok!(Currency::transfer( + RuntimeOrigin::signed(user), + BOB, + HDX, + 998_999_999_999_999 + )); + + assert_noop!( + XYK::buy( + RuntimeOrigin::signed(user), + DOT, + ACA, + 1_000_000_000, + 10_000_000_000, + true + ), + Error::::InsufficientNativeCurrencyBalance + ); + }); +} + +#[test] +fn single_buy_should_work() { + new_test_ext().execute_with(|| { + let user_1 = ALICE; + let asset_a = ACA; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user_1), + asset_a, + 200_000_000, + asset_b, + 640_000_000_000, + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999_999_800_000_000); + assert_eq!(Currency::free_balance(asset_b, &user_1), 999_360_000_000_000); + assert_eq!(Currency::free_balance(share_token, &user_1), 640_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 640_000_000_000); + + assert_ok!(XYK::buy( + RuntimeOrigin::signed(user_1), + asset_a, + asset_b, + 6_666_666, + 1_000_000_000_000, + false, + )); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999_999_806_666_666); + assert_eq!(Currency::free_balance(asset_b, &user_1), 999_337_886_898_839); + assert_eq!(Currency::free_balance(share_token, &user_1), 640_000_000_000); + assert_eq!(Currency::free_balance(asset_a, &pair_account), 193_333_334); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 662_113_101_161); + + expect_events(vec![ + Event::PoolCreated { + who: user_1, + asset_a, + asset_b, + initial_shares_amount: 640_000_000_000, + share_token, + pool: pair_account, + } + .into(), + Event::BuyExecuted { + who: user_1, + asset_out: asset_a, + asset_in: asset_b, + amount: 6_666_666, + buy_price: 22_068_963_235, + fee_asset: asset_b, + fee_amount: 44_137_926, + pool: pair_account, + } + .into(), + pallet_broadcast::Event::Swapped3 { + swapper: user_1, + filler: pair_account, + filler_type: pallet_broadcast::types::Filler::XYK(share_token), + operation: pallet_broadcast::types::TradeOperation::ExactOut, + inputs: vec![Asset::new(asset_b, 6_666_666)], + outputs: vec![Asset::new(asset_a, 22_068_963_235)], + fees: vec![Fee::new(asset_b, 44_137_926, Destination::Account(pair_account))], + operation_stack: vec![], + } + .into(), + ]); + }); +} + +#[test] +fn create_pool_with_insufficient_liquidity_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + XYK::create_pool(RuntimeOrigin::signed(ALICE), ACA, 500, HDX, 1_600_000), + Error::::InsufficientLiquidity + ); + + assert_noop!( + XYK::create_pool(RuntimeOrigin::signed(ALICE), ACA, 5000, HDX, 500), + Error::::InsufficientLiquidity + ); + }); +} + +#[test] +fn add_liquidity_to_non_existing_pool_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + XYK::add_liquidity( + RuntimeOrigin::signed(ALICE), + HDX, + ACA, + 200_000_000_000_000_000, + 600_000_000 + ), + Error::::TokenPoolNotFound + ); + }); +} + +#[test] +fn remove_zero_liquidity_from_non_existing_pool_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + XYK::remove_liquidity(RuntimeOrigin::signed(ALICE), HDX, ACA, 100), + Error::::TokenPoolNotFound + ); + }); +} + +#[test] +fn sell_with_non_existing_pool_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + XYK::sell(RuntimeOrigin::signed(ALICE), HDX, DOT, 456_444_678, 1_000_000, false), + Error::::TokenPoolNotFound + ); + }); +} + +#[test] +fn discount_sell_with_no_native_pool_should_not_work() { + new_test_ext().execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + ACA, + 1000, + DOT, + 3_200_000 + )); + + assert_noop!( + XYK::sell(RuntimeOrigin::signed(ALICE), ACA, DOT, 456_444_678, 1_000_000, true), + Error::::CannotApplyDiscount + ); + }); +} + +#[test] +fn buy_with_non_existing_pool_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + XYK::buy( + RuntimeOrigin::signed(ALICE), + HDX, + DOT, + 456_444_678, + 1_000_000_000, + false + ), + Error::::TokenPoolNotFound + ); + }); +} + +#[test] +fn discount_buy_with_no_native_pool_should_not_work() { + new_test_ext().execute_with(|| { + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(ALICE), + ACA, + 10_000, + DOT, + 32_000_000 + )); + + assert_noop!( + XYK::buy(RuntimeOrigin::signed(ALICE), ACA, DOT, 1000, 1_000_000_000, true), + Error::::CannotApplyDiscount + ); + }); +} + +#[test] +fn money_in_sell_money_out_should_leave_the_same_balance() { + new_test_ext().execute_with(|| { + let user_1 = ALICE; + let asset_a = ACA; + let asset_b = DOT; + + let user_1_balance_a_before = Currency::free_balance(asset_a, &user_1); + let user_1_balance_b_before = Currency::free_balance(asset_b, &user_1); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user_1), + asset_a, + 200_000_000_000, + asset_b, + 600_000_000_000_000, + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999800000000000); + assert_eq!(Currency::free_balance(asset_b, &user_1), 400000000000000); + assert_eq!(Currency::free_balance(share_token, &user_1), 600000000000000); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200000000000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 600000000000000); + + assert_ok!(XYK::sell( + RuntimeOrigin::signed(user_1), + asset_a, + asset_b, + 456_444_678, + 1000000000000, + false, + )); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999799543555322); + assert_eq!(Currency::free_balance(asset_b, &user_1), 401363483591788); + assert_eq!(Currency::free_balance(share_token, &user_1), 600000000000000); + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200456444678); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 598636516408212); + + assert_ok!(XYK::remove_liquidity( + RuntimeOrigin::signed(user_1), + asset_a, + asset_b, + 600000000000000 + )); + + let user_1_balance_a_after = Currency::free_balance(asset_a, &user_1); + let user_1_balance_b_after = Currency::free_balance(asset_b, &user_1); + + assert_eq!(user_1_balance_a_before, user_1_balance_a_after); + assert_eq!(user_1_balance_b_before, user_1_balance_b_after); + }); +} + +#[test] +fn money_in_money_out_should_leave_the_same_balance_for_both_accounts() { + new_test_ext().execute_with(|| { + let user_1 = ALICE; + let user_2 = BOB; + let asset_a = HDX; + let asset_b = DOT; + + let user_1_balance_a_before = Currency::free_balance(asset_a, &user_1); + let user_1_balance_b_before = Currency::free_balance(asset_b, &user_1); + let user_2_balance_a_before = Currency::free_balance(asset_a, &user_2); + let user_2_balance_b_before = Currency::free_balance(asset_b, &user_2); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user_1), + asset_a, + 100_000_000, + asset_b, + 1_000_000_000_000, + )); + + let asset_pair = AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }; + + let pair_account = XYK::get_pair_id(asset_pair); + let share_token = XYK::share_token(pair_account); + + assert!(XYK::exists(asset_pair)); + + assert_ok!(XYK::add_liquidity( + RuntimeOrigin::signed(user_2), + asset_a, + asset_b, + 100_000_000, + 1_100_000_000_000 + )); + + assert_eq!(Currency::free_balance(share_token, &user_1), 100_000_000); + assert_eq!(Currency::free_balance(share_token, &user_2), 100_000_000); + + assert_ok!(XYK::remove_liquidity( + RuntimeOrigin::signed(user_1), + asset_a, + asset_b, + 100_000_000 + )); + + assert_ok!(XYK::remove_liquidity( + RuntimeOrigin::signed(user_2), + asset_a, + asset_b, + 100_000_000 + )); + + assert_eq!(XYK::total_liquidity(pair_account), 0); + + let user_1_balance_a_after = Currency::free_balance(asset_a, &user_1); + let user_1_balance_b_after = Currency::free_balance(asset_b, &user_1); + let user_2_balance_a_after = Currency::free_balance(asset_a, &user_2); + let user_2_balance_b_after = Currency::free_balance(asset_b, &user_2); + + assert_eq!(user_1_balance_a_before, user_1_balance_a_after); + assert_eq!(user_1_balance_b_before, user_1_balance_b_after); + assert_eq!(user_2_balance_a_before, user_2_balance_a_after); + assert_eq!(user_2_balance_b_before, user_2_balance_b_after); + + assert!(!XYK::exists(asset_pair)); + }); +} + +#[test] +fn sell_test_not_reaching_limit() { + ExtBuilder::default().build().execute_with(|| { + let user_1 = ALICE; + let asset_a = ACA; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user_1), + asset_a, + 200_000_000_000, + asset_b, + 600_000_000_000_000, + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999800000000000); + assert_eq!(Currency::free_balance(asset_b, &user_1), 400000000000000); + assert_eq!(Currency::free_balance(share_token, &user_1), 600000000000000); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200000000000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 600000000000000); + + assert_noop!( + XYK::sell( + RuntimeOrigin::signed(user_1), + asset_a, + asset_b, + 456_444_678, + 1_000_000_000_000_000, + false, + ), + Error::::AssetAmountNotReachedLimit + ); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999800000000000); + assert_eq!(Currency::free_balance(asset_b, &user_1), 400000000000000); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200000000000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 600000000000000); + }); +} + +#[test] +fn buy_test_exceeding_max_limit() { + ExtBuilder::default().build().execute_with(|| { + let user_1 = ALICE; + let asset_a = ACA; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user_1), + asset_a, + 200_000_000_000, + asset_b, + 600_000_000_000_000, + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999800000000000); + assert_eq!(Currency::free_balance(asset_b, &user_1), 400000000000000); + assert_eq!(Currency::free_balance(share_token, &user_1), 600000000000000); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200000000000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 600000000000000); + + assert_noop!( + XYK::buy( + RuntimeOrigin::signed(user_1), + asset_a, + asset_b, + 456_444_678, + 1_000_000_000, + false, + ), + Error::::AssetAmountExceededLimit + ); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999800000000000); + assert_eq!(Currency::free_balance(asset_b, &user_1), 400000000000000); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200000000000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 600000000000000); + }); +} + +#[test] +fn single_buy_more_than_ratio_out_should_not_work() { + new_test_ext().execute_with(|| { + let user_1 = ALICE; + let asset_a = ACA; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user_1), + asset_a, + 200_000_000, + asset_b, + 640_000_000_000, + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999_999_800_000_000); + assert_eq!(Currency::free_balance(asset_b, &user_1), 999_360_000_000_000); + assert_eq!(Currency::free_balance(share_token, &user_1), 640_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 640_000_000_000); + + assert_noop!( + XYK::buy( + RuntimeOrigin::signed(user_1), + asset_a, + asset_b, + 66_666_667, + 1_000_000_000_000, + false, + ), + Error::::MaxOutRatioExceeded + ); + }); +} + +#[test] +fn single_buy_more_than_ratio_in_should_not_work() { + new_test_ext().execute_with(|| { + let user_1 = ALICE; + let asset_a = ACA; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user_1), + asset_a, + 100_000_000_000, + asset_b, + 100_000_000_000 + )); + + assert_noop!( + XYK::buy( + RuntimeOrigin::signed(user_1), + asset_a, + asset_b, + 33_333_333_333, + 1_000_000_000_000, + false, + ), + Error::::MaxInRatioExceeded + ); + }); +} + +#[test] +fn single_sell_more_than_ratio_in_should_not_work() { + new_test_ext().execute_with(|| { + let user_1 = ALICE; + let asset_a = ACA; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user_1), + asset_a, + 200_000_000_000, + asset_b, + 600_000_000_000_000, + )); + + let pair_account = XYK::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + let share_token = XYK::share_token(pair_account); + + assert_eq!(Currency::free_balance(asset_a, &user_1), 999_800_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &user_1), 400_000_000_000_000); + assert_eq!(Currency::free_balance(share_token, &user_1), 600_000_000_000_000); + + assert_eq!(Currency::free_balance(asset_a, &pair_account), 200_000_000_000); + assert_eq!(Currency::free_balance(asset_b, &pair_account), 600_000_000_000_000); + + assert_noop!( + XYK::sell( + RuntimeOrigin::signed(user_1), + asset_a, + asset_b, + 66_666_666_667, + 10_000_000, + false, + ), + Error::::MaxInRatioExceeded + ); + }); +} + +#[test] +fn single_sell_more_than_ratio_out_should_not_work() { + ExtBuilder::default().with_max_out_ratio(5).build().execute_with(|| { + let user_1 = ALICE; + let asset_a = ACA; + let asset_b = DOT; + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(user_1), + asset_a, + 100_000_000_000, + asset_b, + 100_000_000_000 + )); + + assert_noop!( + XYK::sell( + RuntimeOrigin::signed(user_1), + asset_a, + asset_b, + 33_333_333_333, + 10_000_000, + false, + ), + Error::::MaxOutRatioExceeded + ); + }); +} + +#[test] +fn sell_with_low_amount_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + XYK::sell(RuntimeOrigin::signed(ALICE), HDX, DOT, 1, 1_000_000, false), + Error::::InsufficientTradingAmount + ); + }); +} + +#[test] +fn buy_with_low_amount_should_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + XYK::buy(RuntimeOrigin::signed(ALICE), HDX, DOT, 1, 1_000_000, false), + Error::::InsufficientTradingAmount + ); + }); +} + +#[test] +fn buy_with_excesive_amount_should_not_work() { + new_test_ext().execute_with(|| { + assert_ok!(XYK::create_pool(RuntimeOrigin::signed(ALICE), HDX, 10_000, DOT, 10_000,)); + + assert_noop!( + XYK::buy(RuntimeOrigin::signed(ALICE), HDX, DOT, 20_000, 1_000_000, false), + Error::::InsufficientPoolAssetBalance + ); + }); +} diff --git a/pallets/xyk/src/trade_execution.rs b/pallets/xyk/src/trade_execution.rs new file mode 100644 index 00000000000..322f660d814 --- /dev/null +++ b/pallets/xyk/src/trade_execution.rs @@ -0,0 +1,173 @@ +use crate::types::{AssetId, AssetPair, Balance}; +use crate::{Config, Error, Pallet}; +use basilisk_traits::router::{ExecutorError, PoolType, TradeExecution}; +use frame_support::ensure; +use frame_support::traits::Get; +use hydradx_traits::AMM; +use orml_traits::MultiCurrency; +use sp_runtime::DispatchError::Corruption; +use sp_runtime::{ArithmeticError, DispatchError, FixedPointNumber, FixedU128}; + +impl TradeExecution for Pallet { + type Error = DispatchError; + + fn calculate_sell( + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_in: Balance, + ) -> Result> { + if pool_type != PoolType::XYK { + return Err(ExecutorError::NotSupported); + } + + let assets = AssetPair { asset_in, asset_out }; + + if !Self::exists(assets) { + return Err(ExecutorError::Error(Error::::TokenPoolNotFound.into())); + } + + let pair_account = Self::get_pair_id(assets); + + let asset_in_reserve = T::Currency::free_balance(assets.asset_in, &pair_account); + let asset_out_reserve = T::Currency::free_balance(assets.asset_out, &pair_account); + + let amount_out = hydra_dx_math::xyk::calculate_out_given_in(asset_in_reserve, asset_out_reserve, amount_in) + .map_err(|_| ExecutorError::Error(Error::::SellAssetAmountInvalid.into()))?; + + ensure!( + asset_out_reserve > amount_out, + ExecutorError::Error(Error::::InsufficientPoolAssetBalance.into()) + ); + + let transfer_fee = Self::calculate_fee(amount_out).map_err(ExecutorError::Error)?; + + let amount_out_without_fee = amount_out + .checked_sub(transfer_fee) + .ok_or_else(|| ExecutorError::Error(Error::::SellAssetAmountInvalid.into()))?; + + Ok(amount_out_without_fee) + } + + fn calculate_buy( + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_out: Balance, + ) -> Result> { + if pool_type != PoolType::XYK { + return Err(ExecutorError::NotSupported); + } + + let assets = AssetPair { asset_in, asset_out }; + + ensure!( + Self::exists(assets), + ExecutorError::Error(Error::::TokenPoolNotFound.into()) + ); + + let pair_account = Self::get_pair_id(assets); + + let asset_out_reserve = T::Currency::free_balance(assets.asset_out, &pair_account); + let asset_in_reserve = T::Currency::free_balance(assets.asset_in, &pair_account); + + ensure!( + asset_out_reserve > amount_out, + ExecutorError::Error(Error::::InsufficientPoolAssetBalance.into()) + ); + + ensure!( + amount_out >= T::MinTradingLimit::get(), + ExecutorError::Error(Error::::InsufficientTradingAmount.into()) + ); + + let amount_in = hydra_dx_math::xyk::calculate_in_given_out(asset_out_reserve, asset_in_reserve, amount_out) + .map_err(|_| ExecutorError::Error(Error::::BuyAssetAmountInvalid.into()))?; + + let transfer_fee = Self::calculate_fee(amount_in).map_err(ExecutorError::Error)?; + + let amount_in_with_fee = amount_in + .checked_add(transfer_fee) + .ok_or_else(|| ExecutorError::Error(Error::::BuyAssetAmountInvalid.into()))?; + + Ok(amount_in_with_fee) + } + + fn execute_sell( + who: T::RuntimeOrigin, + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_in: Balance, + min_limit: Balance, + ) -> Result<(), ExecutorError> { + if pool_type != PoolType::XYK { + return Err(ExecutorError::NotSupported); + } + + Self::sell(who, asset_in, asset_out, amount_in, min_limit, false).map_err(ExecutorError::Error) + } + + fn execute_buy( + who: T::RuntimeOrigin, + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_out: Balance, + max_limit: Balance, + ) -> Result<(), ExecutorError> { + if pool_type != PoolType::XYK { + return Err(ExecutorError::NotSupported); + } + + Self::buy(who, asset_out, asset_in, amount_out, max_limit, false).map_err(ExecutorError::Error) + } + + fn get_liquidity_depth( + pool_type: PoolType, + asset_a: AssetId, + asset_b: AssetId, + ) -> Result> { + if pool_type != PoolType::XYK { + return Err(ExecutorError::NotSupported); + } + + let pair_account = Self::get_pair_id(AssetPair { + asset_in: asset_a, + asset_out: asset_b, + }); + + let liquidty = T::Currency::free_balance(asset_a, &pair_account); + + Ok(liquidty) + } + + fn calculate_spot_price_with_fee( + pool_type: PoolType, + asset_a: AssetId, + asset_b: AssetId, + ) -> Result> { + if pool_type != PoolType::XYK { + return Err(ExecutorError::NotSupported); + } + + let pair_account = >::get_pair_id(AssetPair { + asset_out: asset_a, + asset_in: asset_b, + }); + + let asset_a_reserve = T::Currency::free_balance(asset_a, &pair_account); + let asset_b_reserve = T::Currency::free_balance(asset_b, &pair_account); + + let spot_price_with_fee = hydra_dx_math::xyk::calculate_spot_price_with_fee( + asset_a_reserve, + asset_b_reserve, + Some(T::GetExchangeFee::get()), + ) + .map_err(|_| ExecutorError::Error(ArithmeticError::Overflow.into()))? + .reciprocal() + .ok_or(ExecutorError::Error(Corruption))?; + + Ok(spot_price_with_fee) + } +} diff --git a/pallets/xyk/src/types.rs b/pallets/xyk/src/types.rs new file mode 100644 index 00000000000..40cb3d84cbf --- /dev/null +++ b/pallets/xyk/src/types.rs @@ -0,0 +1,69 @@ +// This file is part of Basilisk-node. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub type AssetId = u32; +pub type Amount = i128; +pub type Balance = u128; +pub type Price = FixedU128; + +use codec::{Decode, DecodeWithMemTracking, Encode}; +use scale_info::TypeInfo; +use sp_runtime::FixedU128; +use sp_std::vec::Vec; + +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; + +/// Asset Pair representation for AMM trades +/// ( asset_a, asset_b ) combination where asset_a is meant to be exchanged for asset_b +/// +/// asset_in represents asset coming into the pool +/// asset_out represents asset coming out of the pool +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Debug, Encode, Decode, DecodeWithMemTracking, Copy, Clone, PartialEq, Eq, Default, TypeInfo)] +pub struct AssetPair { + pub asset_in: AssetId, + pub asset_out: AssetId, +} + +impl AssetPair { + pub fn new(asset_in: AssetId, asset_out: AssetId) -> Self { + Self { asset_in, asset_out } + } + + /// Return ordered asset tuple (A,B) where A < B + /// Used in storage + pub fn ordered_pair(&self) -> (AssetId, AssetId) { + match self.asset_in <= self.asset_out { + true => (self.asset_in, self.asset_out), + false => (self.asset_out, self.asset_in), + } + } + + /// Return share token name + pub fn name(&self) -> Vec { + let mut buf: Vec = Vec::new(); + + let (asset_a, asset_b) = self.ordered_pair(); + + buf.extend_from_slice(&asset_a.to_le_bytes()); + buf.extend_from_slice(b"HDT"); + buf.extend_from_slice(&asset_b.to_le_bytes()); + + buf + } +} diff --git a/pallets/xyk/src/weights.rs b/pallets/xyk/src/weights.rs new file mode 100644 index 00000000000..1f378a8240b --- /dev/null +++ b/pallets/xyk/src/weights.rs @@ -0,0 +1,325 @@ +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_xyk. +pub trait WeightInfo { + fn create_pool() -> Weight; + fn add_liquidity() -> Weight; + fn remove_liquidity() -> Weight; + fn sell() -> Weight; + fn buy() -> Weight; + fn router_execution_sell(c: u32, e: u32) -> Weight; + fn router_execution_buy(c: u32, e: u32) -> Weight; + fn calculate_spot_price_with_fee() -> Weight; +} + +/// Weights for amm using the hydraDX node and recommended hardware. +impl WeightInfo for () { + /// Storage: `AssetRegistry::Assets` (r:3 w:1) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `LBP::PoolData` (r:1 w:0) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `XYK::ShareToken` (r:1 w:1) + /// Proof: `XYK::ShareToken` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:7 w:7) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::AssetIds` (r:1 w:1) + /// Proof: `AssetRegistry::AssetIds` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::NextAssetId` (r:1 w:1) + /// Proof: `AssetRegistry::NextAssetId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:1 w:1) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:4 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:3 w:0) + /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AcceptedCurrencyPrice` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AcceptedCurrencyPrice` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AcceptedCurrencies` (r:3 w:0) + /// Proof: `MultiTransactionPayment::AcceptedCurrencies` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::ExistentialDepositCounter` (r:1 w:1) + /// Proof: `AssetRegistry::ExistentialDepositCounter` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Tokens::TotalIssuance` (r:1 w:1) + /// Proof: `Tokens::TotalIssuance` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `EVM::AccountCodesMetadata` (r:0 w:1) + /// Proof: `EVM::AccountCodesMetadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `EVM::AccountCodes` (r:0 w:1) + /// Proof: `EVM::AccountCodes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XYK::TotalLiquidity` (r:0 w:1) + /// Proof: `XYK::TotalLiquidity` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `XYK::PoolAssets` (r:0 w:1) + /// Proof: `XYK::PoolAssets` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn create_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `3930` + // Estimated: `19071` + // Minimum execution time: 562_857_000 picoseconds. + Weight::from_parts(565_541_000, 19071) + .saturating_add(RocksDbWeight::get().reads(34_u64)) + .saturating_add(RocksDbWeight::get().writes(22_u64)) + } + /// Storage: `XYK::ShareToken` (r:1 w:0) + /// Proof: `XYK::ShareToken` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:4 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:7 w:7) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `XYK::TotalLiquidity` (r:1 w:1) + /// Proof: `XYK::TotalLiquidity` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:1 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:4 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::ExistentialDepositCounter` (r:1 w:1) + /// Proof: `AssetRegistry::ExistentialDepositCounter` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AcceptedCurrencyPrice` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AcceptedCurrencyPrice` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `Tokens::TotalIssuance` (r:1 w:1) + /// Proof: `Tokens::TotalIssuance` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::WhitelistedAssets` (r:1 w:0) + /// Proof: `EmaOracle::WhitelistedAssets` (`max_values`: Some(1), `max_size`: Some(641), added: 1136, mode: `MaxEncodedLen`) + fn add_liquidity() -> Weight { + // Proof Size summary in bytes: + // Measured: `4566` + // Estimated: `19071` + // Minimum execution time: 372_530_000 picoseconds. + Weight::from_parts(373_917_000, 19071) + .saturating_add(RocksDbWeight::get().reads(28_u64)) + .saturating_add(RocksDbWeight::get().writes(13_u64)) + } + /// Storage: `XYK::ShareToken` (r:1 w:1) + /// Proof: `XYK::ShareToken` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `XYK::TotalLiquidity` (r:1 w:1) + /// Proof: `XYK::TotalLiquidity` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:4 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:7 w:7) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:2 w:1) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:3 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:2 w:0) + /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AcceptedCurrencyPrice` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AcceptedCurrencyPrice` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::ExistentialDepositCounter` (r:1 w:1) + /// Proof: `AssetRegistry::ExistentialDepositCounter` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Tokens::TotalIssuance` (r:1 w:1) + /// Proof: `Tokens::TotalIssuance` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::WhitelistedAssets` (r:1 w:0) + /// Proof: `EmaOracle::WhitelistedAssets` (`max_values`: Some(1), `max_size`: Some(641), added: 1136, mode: `MaxEncodedLen`) + /// Storage: `XYK::PoolAssets` (r:0 w:1) + /// Proof: `XYK::PoolAssets` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn remove_liquidity() -> Weight { + // Proof Size summary in bytes: + // Measured: `4616` + // Estimated: `19071` + // Minimum execution time: 512_976_000 picoseconds. + Weight::from_parts(514_773_000, 19071) + .saturating_add(RocksDbWeight::get().reads(30_u64)) + .saturating_add(RocksDbWeight::get().writes(17_u64)) + } + /// Storage: `XYK::ShareToken` (r:1 w:0) + /// Proof: `XYK::ShareToken` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:3 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:6 w:6) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:2 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:3 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::ExistentialDepositCounter` (r:1 w:1) + /// Proof: `AssetRegistry::ExistentialDepositCounter` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AcceptedCurrencyPrice` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AcceptedCurrencyPrice` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::WhitelistedAssets` (r:1 w:0) + /// Proof: `EmaOracle::WhitelistedAssets` (`max_values`: Some(1), `max_size`: Some(641), added: 1136, mode: `MaxEncodedLen`) + fn sell() -> Weight { + // Proof Size summary in bytes: + // Measured: `4465` + // Estimated: `16488` + // Minimum execution time: 322_473_000 picoseconds. + Weight::from_parts(324_925_000, 16488) + .saturating_add(RocksDbWeight::get().reads(25_u64)) + .saturating_add(RocksDbWeight::get().writes(10_u64)) + } + /// Storage: `XYK::ShareToken` (r:1 w:0) + /// Proof: `XYK::ShareToken` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:3 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:6 w:6) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:2 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:3 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AcceptedCurrencyPrice` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AcceptedCurrencyPrice` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::ExistentialDepositCounter` (r:1 w:1) + /// Proof: `AssetRegistry::ExistentialDepositCounter` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::WhitelistedAssets` (r:1 w:0) + /// Proof: `EmaOracle::WhitelistedAssets` (`max_values`: Some(1), `max_size`: Some(641), added: 1136, mode: `MaxEncodedLen`) + fn buy() -> Weight { + // Proof Size summary in bytes: + // Measured: `4465` + // Estimated: `16488` + // Minimum execution time: 319_664_000 picoseconds. + Weight::from_parts(321_488_000, 16488) + .saturating_add(RocksDbWeight::get().reads(25_u64)) + .saturating_add(RocksDbWeight::get().writes(10_u64)) + } + /// Storage: `XYK::ShareToken` (r:1 w:0) + /// Proof: `XYK::ShareToken` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:3 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:6 w:6) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:2 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:3 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::ExistentialDepositCounter` (r:1 w:1) + /// Proof: `AssetRegistry::ExistentialDepositCounter` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AcceptedCurrencyPrice` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AcceptedCurrencyPrice` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::WhitelistedAssets` (r:1 w:0) + /// Proof: `EmaOracle::WhitelistedAssets` (`max_values`: Some(1), `max_size`: Some(641), added: 1136, mode: `MaxEncodedLen`) + /// The range of component `c` is `[1, 2]`. + /// The range of component `e` is `[0, 1]`. + fn router_execution_sell(c: u32, e: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1786 + e * (2679 ±0)` + // Estimated: `8799 + e * (10332 ±0)` + // Minimum execution time: 46_983_000 picoseconds. + Weight::from_parts(23_427_016, 8799) + // Standard Error: 117_050 + .saturating_add(Weight::from_parts(12_284_937, 0).saturating_mul(c.into())) + // Standard Error: 117_050 + .saturating_add(Weight::from_parts(286_660_358, 0).saturating_mul(e.into())) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().reads((20_u64).saturating_mul(e.into()))) + .saturating_add(RocksDbWeight::get().writes((10_u64).saturating_mul(e.into()))) + .saturating_add(Weight::from_parts(0, 10332).saturating_mul(e.into())) + } + /// Storage: `XYK::ShareToken` (r:1 w:0) + /// Proof: `XYK::ShareToken` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:3 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:6 w:6) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:2 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:3 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AcceptedCurrencyPrice` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AcceptedCurrencyPrice` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::ExistentialDepositCounter` (r:1 w:1) + /// Proof: `AssetRegistry::ExistentialDepositCounter` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::WhitelistedAssets` (r:1 w:0) + /// Proof: `EmaOracle::WhitelistedAssets` (`max_values`: Some(1), `max_size`: Some(641), added: 1136, mode: `MaxEncodedLen`) + /// The range of component `c` is `[1, 3]`. + /// The range of component `e` is `[0, 1]`. + fn router_execution_buy(c: u32, e: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1786 + e * (2679 ±0)` + // Estimated: `6190 + e * (10332 ±6_084_484_329_818_434)` + // Minimum execution time: 58_308_000 picoseconds. + Weight::from_parts(24_469_761, 6190) + // Standard Error: 35_338 + .saturating_add(Weight::from_parts(11_612_542, 0).saturating_mul(c.into())) + // Standard Error: 58_822 + .saturating_add(Weight::from_parts(284_359_512, 0).saturating_mul(e.into())) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().reads((20_u64).saturating_mul(e.into()))) + .saturating_add(RocksDbWeight::get().writes((10_u64).saturating_mul(e.into()))) + .saturating_add(Weight::from_parts(0, 10332).saturating_mul(e.into())) + } + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:2 w:0) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + fn calculate_spot_price_with_fee() -> Weight { + // Proof Size summary in bytes: + // Measured: `1586` + // Estimated: `6190` + // Minimum execution time: 40_317_000 picoseconds. + Weight::from_parts(40_698_000, 6190) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + } +} diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 7d6ae242cf1..023a509d44d 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "primitives" -version = "6.6.5" +version = "6.7.0" authors = ["GalacticCouncil"] edition = "2021" repository = "https://github.com/galacticcouncil/Basilisk-node" diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index a9b18e98e36..098a5c4714e 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -20,7 +20,7 @@ use codec::{Decode, Encode}; -use primitive_types::U256; +use primitive_types::{H160, U256}; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; @@ -48,6 +48,8 @@ pub type Signature = MultiSignature; /// to the public key of our transaction signing scheme. pub type AccountId = <::Signer as IdentifyAccount>::AccountId; +pub type EvmAddress = H160; + /// The type for looking up accounts. We don't expect more than 4 billion of them, but you /// never know... pub type AccountIndex = u32; diff --git a/runtime/adapters/Cargo.toml b/runtime/adapters/Cargo.toml new file mode 100644 index 00000000000..0b3bd6d7057 --- /dev/null +++ b/runtime/adapters/Cargo.toml @@ -0,0 +1,102 @@ +[package] +name = "basilisk-adapters" +version = "1.4.0" +description = "Structs and other generic types for building runtimes." +authors = ["GalacticCouncil"] +edition = "2021" +license = "Apache 2.0" +repository = "https://github.com/galacticcouncil/warehouse/tree/master/adapters" + +[dependencies] +codec = { workspace = true } +log = { workspace = true } +scale-info = { workspace = true } + +basilisk-traits = { workspace = true } + +# HydraDX dependencies +primitives = { workspace = true } +hydradx-traits = { workspace = true } +hydra-dx-math = { workspace = true } +pallet-transaction-multi-payment = { workspace = true } +pallet-ema-oracle = { workspace = true } +warehouse-liquidity-mining = { workspace = true } +pallet-uniques = { workspace = true } +pallet-route-executor = { workspace = true } +pallet-currencies = { workspace = true } +pallet-lbp = { workspace = true } +pallet-asset-registry = { workspace = true } +pallet-broadcast = { workspace = true } + +# Substrate dependencies +frame-support = { workspace = true } +frame-system = { workspace = true } +sp-runtime = { workspace = true } +sp-std = { workspace = true } +primitive-types = { workspace = true } +sp-core = { workspace = true } +sp-io = { workspace = true } + +# Polkadot dependencies +polkadot-parachain = { workspace = true } +polkadot-xcm = { workspace = true } +xcm-builder = { workspace = true } +xcm-executor = { workspace = true } + +# Cumulus dependencies +cumulus-pallet-parachain-system = { workspace = true } +cumulus-primitives-core = { workspace = true } + +# ORML dependencies +orml-xcm-support = { workspace = true } +orml-traits = { workspace = true } +orml-vesting = { workspace = true } +orml-utilities = { workspace = true } +orml-tokens = { workspace = true } + +# Pallets +pallet-balances = { workspace = true } + +[dev-dependencies] +lazy_static = { workspace = true } +pretty_assertions = { workspace = true } +pallet-xyk = { workspace = true } + +[features] +default = ["std"] +runtime-benchmarks = [ + "xcm-builder/runtime-benchmarks", + "xcm-executor/runtime-benchmarks", + "pallet-ema-oracle/runtime-benchmarks", + "pallet-uniques/runtime-benchmarks", + "pallet-route-executor/runtime-benchmarks", + "pallet-lbp/runtime-benchmarks", + "pallet-asset-registry/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "cumulus-pallet-parachain-system/runtime-benchmarks", + "cumulus-primitives-core/runtime-benchmarks", + "orml-vesting/runtime-benchmarks", + "orml-tokens/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", +] +std = [ + "codec/std", + "orml-tokens/std", + "pallet-balances/std", + "frame-support/std", + "frame-system/std", + "basilisk-traits/std", + "hydradx-traits/std", + "pallet-transaction-multi-payment/std", + "polkadot-xcm/std", + "sp-runtime/std", + "sp-std/std", + "xcm-builder/std", + "xcm-executor/std", + "cumulus-pallet-parachain-system/std", + "polkadot-parachain/std", + "orml-tokens/std", + "pallet-asset-registry/std", +] diff --git a/runtime/adapters/src/lib.rs b/runtime/adapters/src/lib.rs new file mode 100644 index 00000000000..f5aec1362c1 --- /dev/null +++ b/runtime/adapters/src/lib.rs @@ -0,0 +1,277 @@ +// This file is part of basilisk-adapters. + +// Copyright (C) 2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg_attr(not(feature = "std"), no_std)] + +use basilisk_traits::oracle::NativePriceOracle; +use cumulus_primitives_core::relay_chain::Hash; +use frame_support::{ + sp_runtime::{ + traits::{AtLeast32BitUnsigned, Convert, Get, Saturating, Zero}, + FixedPointNumber, FixedPointOperand, SaturatedConversion, + }, + weights::{Weight, WeightToFee}, +}; +use pallet_transaction_multi_payment::DepositFee; +use polkadot_xcm::v5::prelude::*; +use sp_runtime::traits::BlockNumberProvider; +use sp_std::{collections::btree_map::BTreeMap, marker::PhantomData}; +use xcm_builder::TakeRevenue; +use xcm_executor::{traits::WeightTrader, AssetsInHolding}; + +pub mod xcm_exchange; + +pub mod xyk; + +/// Weight trader that accepts multiple assets as weight fee payment. +/// +/// It uses `WeightToFee` in combination with a `NativePriceOracle` to set the right price for weight. +/// Keeps track of the assets used to pay for weight and can refund them one by one (interface only +/// allows returning one asset per refund). Will pass any remaining assets on `Drop` to +/// `TakeRevenue`. +pub struct MultiCurrencyTrader< + AssetId, + Balance: FixedPointOperand + TryInto, + Price: FixedPointNumber, + ConvertWeightToFee: WeightToFee, + AcceptedCurrencyPrices: NativePriceOracle, + ConvertCurrency: Convert>, + Revenue: TakeRevenue, +> { + weight: Weight, + paid_assets: BTreeMap<(Location, Price), u128>, + _phantom: PhantomData<( + AssetId, + Balance, + Price, + ConvertWeightToFee, + AcceptedCurrencyPrices, + ConvertCurrency, + Revenue, + )>, +} + +impl< + AssetId, + Balance: FixedPointOperand + TryInto, + Price: FixedPointNumber, + ConvertWeightToFee: WeightToFee, + AcceptedCurrencyPrices: NativePriceOracle, + ConvertCurrency: Convert>, + Revenue: TakeRevenue, + > MultiCurrencyTrader +{ + /// Get the asset id of the first asset in `payment` and try to determine its price via the + /// price oracle. + fn get_asset_and_price(&mut self, payment: &AssetsInHolding) -> Option<(Location, Price)> { + if let Some(asset) = payment.fungible_assets_iter().next() { + ConvertCurrency::convert(asset.clone()) + .and_then(|currency| AcceptedCurrencyPrices::price(currency)) + .map(|price| (asset.id.0, price)) + } else { + None + } + } +} + +impl< + AssetId, + Balance: FixedPointOperand + TryInto, + Price: FixedPointNumber, + ConvertWeightToFee: WeightToFee, + AcceptedCurrencyPrices: NativePriceOracle, + ConvertCurrency: Convert>, + Revenue: TakeRevenue, + > WeightTrader + for MultiCurrencyTrader +{ + fn new() -> Self { + Self { + weight: Default::default(), + paid_assets: Default::default(), + _phantom: PhantomData, + } + } + + /// Will try to buy weight with the first asset in `payment`. + /// + /// This is a reasonable strategy as the `BuyExecution` XCM instruction only passes one asset + /// per buy. + /// The fee is determined by `ConvertWeightToFee` in combination with the price determined by + /// `AcceptedCurrencyPrices`. + fn buy_weight( + &mut self, + weight: Weight, + payment: AssetsInHolding, + _context: &XcmContext, + ) -> Result { + log::trace!( + target: "xcm::weight", "MultiCurrencyTrader::buy_weight weight: {:?}, payment: {:?}", + weight, payment + ); + let (asset_loc, price) = self.get_asset_and_price(&payment).ok_or(XcmError::AssetNotFound)?; + let fee = ConvertWeightToFee::weight_to_fee(&weight); + let converted_fee = price.checked_mul_int(fee).ok_or(XcmError::Overflow)?; + let amount: u128 = converted_fee.try_into().map_err(|_| XcmError::Overflow)?; + let required = (asset_loc.clone(), amount).into(); + let unused = payment.checked_sub(required).map_err(|_| XcmError::TooExpensive)?; + self.weight = self.weight.saturating_add(weight); + let key = (asset_loc, price); + match self.paid_assets.get_mut(&key) { + Some(v) => v.saturating_accrue(amount), + None => { + self.paid_assets.insert(key, amount); + } + } + Ok(unused) + } + + /// Will refund up to `weight` from the first asset tracked by the trader. + fn refund_weight(&mut self, weight: Weight, _context: &XcmContext) -> Option { + log::trace!( + target: "xcm::weight", "MultiCurrencyTrader::refund_weight weight: {:?}, paid_assets: {:?}", + weight, self.paid_assets + ); + let weight = weight.min(self.weight); + self.weight -= weight; // Will not underflow because of `min()` above. + let fee = ConvertWeightToFee::weight_to_fee(&weight); + if let Some(((asset_loc, price), amount)) = self.paid_assets.iter_mut().next() { + let converted_fee: u128 = price.saturating_mul_int(fee).saturated_into(); + let refund = converted_fee.min(*amount); + *amount -= refund; // Will not underflow because of `min()` above. + + let refund_asset = asset_loc.clone(); + if amount.is_zero() { + let key = (asset_loc.clone(), *price); + self.paid_assets.remove(&key); + } + Some((refund_asset, refund).into()) + } else { + None + } + } +} + +/// We implement `Drop` so that when the weight trader is dropped at the end of XCM execution, the +/// generated revenue is stored on-chain. This is configurable via the `Revenue` generic. +impl< + AssetId, + Balance: FixedPointOperand + TryInto, + Price: FixedPointNumber, + ConvertWeightToFee: WeightToFee, + AcceptedCurrencyPrices: NativePriceOracle, + ConvertCurrency: Convert>, + Revenue: TakeRevenue, + > Drop + for MultiCurrencyTrader +{ + fn drop(&mut self) { + for ((asset_loc, _), amount) in self.paid_assets.iter() { + Revenue::take_revenue((asset_loc.clone(), *amount).into()); + } + } +} + +/// Implements `TakeRevenue` by sending the assets to the fee receiver, using an implementor of +/// `DepositFee`. +/// +/// Note: Only supports concrete fungible assets. +pub struct ToFeeReceiver( + PhantomData<(AccountId, AssetId, Balance, Price, C, D, F)>, +); +impl< + AccountId, + AssetId, + Balance: AtLeast32BitUnsigned, + Price, + C: Convert>, + D: DepositFee, + F: Get, + > TakeRevenue for ToFeeReceiver +{ + fn take_revenue(asset: Asset) { + match asset.clone() { + Asset { + id: _asset_id, + fun: Fungibility::Fungible(amount), + } => { + C::convert(asset).and_then(|id| { + let receiver = F::get(); + D::deposit_fee(&receiver, id, amount.saturated_into::()) + .map_err(|e| log::trace!(target: "xcm::take_revenue", "Could not deposit fee: {:?}", e)) + .ok() + }); + } + _ => { + debug_assert!(false, "Can only accept concrete fungible tokens as revenue."); + log::trace!(target: "xcm::take_revenue", "Can only accept concrete fungible tokens as revenue."); + } + } + } +} + +// Relay chain Block number provider. +// Reason why the implementation is different for benchmarks is that it is not possible +// to set or change the block number in a benchmark using parachain system pallet. +// That's why we revert to using the system pallet in the benchmark. +pub struct RelayChainBlockNumberProvider(sp_std::marker::PhantomData); + +#[cfg(not(feature = "runtime-benchmarks"))] +impl BlockNumberProvider for RelayChainBlockNumberProvider { + type BlockNumber = polkadot_parachain::primitives::RelayChainBlockNumber; + + fn current_block_number() -> Self::BlockNumber { + let maybe_data = cumulus_pallet_parachain_system::ValidationData::::get(); + + if let Some(data) = maybe_data { + data.relay_parent_number + } else { + Self::BlockNumber::default() + } + } +} + +#[cfg(feature = "runtime-benchmarks")] +impl BlockNumberProvider for RelayChainBlockNumberProvider { + type BlockNumber = frame_system::pallet_prelude::BlockNumberFor; + + fn current_block_number() -> Self::BlockNumber { + frame_system::Pallet::::current_block_number() + } +} + +pub trait RelayChainBlockHashProvider { + fn parent_hash() -> Option; +} +// The reason why there is difference between PROD and benchmark is that it is not possible +// to set validation data in parachain system pallet in the benchmarks. +// So for benchmarking, we mock it out and return some hardcoded parent hash +pub struct RelayChainBlockHashProviderAdapter(sp_std::marker::PhantomData); + +#[cfg(not(feature = "runtime-benchmarks"))] +impl RelayChainBlockHashProvider for RelayChainBlockHashProviderAdapter +where + Runtime: cumulus_pallet_parachain_system::Config, +{ + fn parent_hash() -> Option { + let validation_data = cumulus_pallet_parachain_system::ValidationData::::get(); + match validation_data { + Some(data) => Some(data.parent_head.hash()), + None => None, + } + } +} diff --git a/runtime/adapters/src/xcm_exchange.rs b/runtime/adapters/src/xcm_exchange.rs new file mode 100644 index 00000000000..4af886e7e7a --- /dev/null +++ b/runtime/adapters/src/xcm_exchange.rs @@ -0,0 +1,147 @@ +use frame_support::traits::ExistenceRequirement; +use orml_traits::MultiCurrency; +use pallet_broadcast::types::ExecutionType; +use polkadot_xcm::v5::prelude::*; +use sp_core::Get; +use sp_runtime::traits::{Convert, Zero}; +use sp_std::marker::PhantomData; +use sp_std::vec; +use xcm_executor::traits::AssetExchange; +use xcm_executor::AssetsInHolding; + +/// Implements `AssetExchange` to support the `ExchangeAsset` XCM instruction. +/// +/// Uses pallet-route-executor to execute trades. +/// +/// Will map exchange instructions with `maximal = true` to sell (selling all of `give` asset) and `false` to buy +/// (buying exactly `want` amount of asset). +/// +/// NOTE: Currenty limited to one asset each for `give` and `want`. +pub struct XcmAssetExchanger( + PhantomData<(Runtime, TempAccount, CurrencyIdConvert, Currency)>, +); + +impl AssetExchange + for XcmAssetExchanger +where + Runtime: pallet_route_executor::Config, + TempAccount: Get, + CurrencyIdConvert: Convert>, + Currency: MultiCurrency, + Runtime::Balance: From + Zero + Into, + Runtime::AssetId: Into, +{ + fn exchange_asset( + _origin: Option<&Location>, + give: AssetsInHolding, + want: &Assets, + maximal: bool, + ) -> Result { + use orml_utilities::with_transaction_result; + + let account = TempAccount::get(); + let origin = Runtime::RuntimeOrigin::from(frame_system::RawOrigin::Signed(account.clone())); + + if give.len() != 1 { + log::warn!(target: "xcm::exchange-asset", "Only one give asset is supported."); + return Err(give); + }; + + //We assume only one asset wanted as translating into buy and sell is ambigous for multiple want assets + if want.len() != 1 { + log::warn!(target: "xcm::exchange-asset", "Only one want asset is supported."); + return Err(give); + }; + let Some(given) = give.fungible_assets_iter().next() else { + return Err(give); + }; + + let Some(asset_in) = CurrencyIdConvert::convert(given.clone()) else { + return Err(give); + }; + let Some(wanted) = want.get(0) else { return Err(give) }; + let Some(asset_out) = CurrencyIdConvert::convert(wanted.clone()) else { + return Err(give); + }; + let use_onchain_route = vec![]; + + let _ = pallet_broadcast::Pallet::::add_to_context(ExecutionType::XcmExchange); + + let trade_result = if maximal { + // sell + let Fungible(amount) = given.fun else { return Err(give) }; + let Fungible(min_buy_amount) = wanted.fun else { + return Err(give); + }; + + with_transaction_result(|| { + Currency::deposit(asset_in, &account, amount.into())?; // mint the incoming tokens + pallet_route_executor::Pallet::::sell( + origin, + asset_in, + asset_out, + amount.into(), + min_buy_amount.into(), + use_onchain_route, + )?; + debug_assert!( + Currency::free_balance(asset_in, &account) == Runtime::Balance::zero(), + "Sell should not leave any of the incoming asset." + ); + let amount_received = Currency::free_balance(asset_out, &account); + debug_assert!( + amount_received >= min_buy_amount.into(), + "Sell should return more than mininum buy amount." + ); + Currency::withdraw(asset_out, &account, amount_received, ExistenceRequirement::AllowDeath)?; // burn the received tokens + let holding: Asset = (wanted.id.clone(), amount_received.into()).into(); + + Ok(holding.into()) + }) + .map_err(|_| give.clone()) + } else { + // buy + let Fungible(amount) = wanted.fun else { return Err(give) }; + let Fungible(max_sell_amount) = given.fun else { + return Err(give); + }; + + with_transaction_result(|| { + Currency::deposit(asset_in, &account, max_sell_amount.into())?; // mint the incoming tokens + pallet_route_executor::Pallet::::buy( + origin, + asset_in, + asset_out, + amount.into(), + max_sell_amount.into(), + use_onchain_route, + )?; + let mut assets = sp_std::vec::Vec::with_capacity(2); + let left_over = Currency::free_balance(asset_in, &account); + if left_over > Runtime::Balance::zero() { + Currency::withdraw(asset_in, &account, left_over, ExistenceRequirement::AllowDeath)?; // burn left over tokens + let holding: Asset = (given.id.clone(), left_over.into()).into(); + assets.push(holding); + } + let amount_received = Currency::free_balance(asset_out, &account); + debug_assert!( + amount_received == amount.into(), + "Buy should return exactly the amount we specified." + ); + Currency::withdraw(asset_out, &account, amount_received, ExistenceRequirement::AllowDeath)?; // burn the received tokens + let holding: Asset = (wanted.id.clone(), amount_received.into()).into(); + assets.push(holding); + Ok(assets.into()) + }) + .map_err(|_| give.clone()) + }; + + let _ = pallet_broadcast::Pallet::::remove_from_context(); + + trade_result + } + + fn quote_exchange_price(_give: &Assets, _want: &Assets, _maximal: bool) -> Option { + todo!() // TODO: + } +} diff --git a/runtime/adapters/src/xyk.rs b/runtime/adapters/src/xyk.rs new file mode 100644 index 00000000000..9b1aca69f68 --- /dev/null +++ b/runtime/adapters/src/xyk.rs @@ -0,0 +1,27 @@ +use hydradx_traits::CanCreatePool; +use hydradx_traits::Inspect; +use primitives::AssetId; + +pub struct AllowPoolCreation(sp_std::marker::PhantomData<(LBP, R)>); + +impl CanCreatePool for AllowPoolCreation +where + LBP: pallet_lbp::Config, + R: Inspect, +{ + fn can_create(asset_a: AssetId, asset_b: AssetId) -> bool { + let Some(asset_a_type) = R::asset_type(asset_a) else { + return false; + }; + if asset_a_type == hydradx_traits::AssetKind::XYK { + return false; + } + let Some(asset_b_type) = R::asset_type(asset_b) else { + return false; + }; + if asset_b_type == hydradx_traits::AssetKind::XYK { + return false; + } + pallet_lbp::DisallowWhenLBPPoolRunning::::can_create(asset_a, asset_b) + } +} diff --git a/runtime/basilisk/Cargo.toml b/runtime/basilisk/Cargo.toml index 9206d1e696e..5ec7f30937e 100644 --- a/runtime/basilisk/Cargo.toml +++ b/runtime/basilisk/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "basilisk-runtime" -version = "127.0.0" +version = "128.0.0" authors = ["GalacticCouncil"] edition = "2021" homepage = "https://github.com/galacticcouncil/Basilisk-node" @@ -13,6 +13,9 @@ targets = ["x86_64-unknown-linux-gnu"] [build-dependencies] substrate-wasm-builder = { workspace = true } +[dev-dependencies] +frame-metadata = { workspace = true } + [dependencies] hex-literal = { workspace = true } serde = { workspace = true, optional = true } @@ -22,7 +25,9 @@ smallvec = { workspace = true } log = { workspace = true } # local dependencies +basilisk-math = { workspace = true } primitives = { default-features = false, path = "../../primitives" } +basilisk-traits = { workspace = true, default-features = false } pallet-marketplace = { workspace = true, default-features = false } pallet-xyk-liquidity-mining = { workspace = true , default-features = false } pallet-xyk-liquidity-mining-benchmarking = { workspace = true, optional = true, default-features = false } @@ -41,7 +46,7 @@ hydra-dx-math = { workspace = true } pallet-transaction-multi-payment = { workspace = true } pallet-relaychain-info = { workspace = true } pallet-asset-registry = { workspace = true } -hydradx-adapters = { workspace = true } +basilisk-adapters = { workspace = true } pallet-nft = { workspace = true } pallet-currencies = { workspace = true } pallet-transaction-pause = { workspace = true } @@ -180,6 +185,8 @@ runtime-benchmarks = [ "pallet-whitelist/runtime-benchmarks", "pallet-message-queue/runtime-benchmarks", "cumulus-pallet-parachain-system/runtime-benchmarks", + "pallet-transaction-multi-payment/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", ] std = [ "codec/std", @@ -232,7 +239,7 @@ std = [ "pallet-broadcast/std", "pallet-staking/std", "hydradx-traits/std", - "hydradx-adapters/std", + "basilisk-adapters/std", "sp-api/std", "sp-arithmetic/std", "sp-block-builder/std", @@ -270,6 +277,7 @@ std = [ "cumulus-primitives-utility/std", "parachains-common/std", "polkadot-runtime-common/std", + "basilisk-traits/std", ] try-runtime= [ "frame-try-runtime", diff --git a/runtime/basilisk/src/adapter.rs b/runtime/basilisk/src/adapter.rs index 11109a4fdcd..a22d1f2a3e2 100644 --- a/runtime/basilisk/src/adapter.rs +++ b/runtime/basilisk/src/adapter.rs @@ -1,14 +1,12 @@ -use frame_support::sp_runtime::DispatchResult; -use frame_support::traits::BalanceStatus; -use frame_system::pallet_prelude::BlockNumberFor; -use hydra_dx_math::{ - ema::EmaPrice, - support::rational::{round_u512_to_rational, Rounding}, -}; -use hydradx_traits::{ +use basilisk_math::ema::EmaPrice; +use basilisk_traits::{ + oracle::{AggregatedPriceOracle, OraclePeriod, PriceOracle}, router::{PoolType, Trade}, - AggregatedPriceOracle, OraclePeriod, PriceOracle, }; +use frame_support::sp_runtime::DispatchResult; +use frame_support::traits::{BalanceStatus, ExistenceRequirement}; +use frame_system::pallet_prelude::BlockNumberFor; +use hydra_dx_math::support::rational::{round_u512_to_rational, Rounding}; use orml_traits::currency::TransferAll; use orml_traits::{ LockIdentifier, MultiCurrency, MultiCurrencyExtended, MultiLockableCurrency, MultiReservableCurrency, @@ -51,8 +49,15 @@ impl MultiCurrency from: &T::AccountId, to: &T::AccountId, amount: Self::Balance, + existence_requirement: ExistenceRequirement, ) -> DispatchResult { - let res = as MultiCurrency>::transfer(currency_id, from, to, amount); + let res = as MultiCurrency>::transfer( + currency_id, + from, + to, + amount, + existence_requirement, + ); if res.is_ok() { >::deposit_event( @@ -73,8 +78,18 @@ impl MultiCurrency as MultiCurrency>::deposit(currency_id, who, amount) } - fn withdraw(currency_id: Self::CurrencyId, who: &T::AccountId, amount: Self::Balance) -> DispatchResult { - as MultiCurrency>::withdraw(currency_id, who, amount) + fn withdraw( + currency_id: Self::CurrencyId, + who: &T::AccountId, + amount: Self::Balance, + existence_requirement: ExistenceRequirement, + ) -> DispatchResult { + as MultiCurrency>::withdraw( + currency_id, + who, + amount, + existence_requirement, + ) } fn can_slash(currency_id: Self::CurrencyId, who: &T::AccountId, value: Self::Balance) -> bool { diff --git a/runtime/basilisk/src/apis.rs b/runtime/basilisk/src/apis.rs index ab2790f9f4c..9dc4e07ab57 100644 --- a/runtime/basilisk/src/apis.rs +++ b/runtime/basilisk/src/apis.rs @@ -16,6 +16,7 @@ // limitations under the License. use crate::*; +use basilisk_traits::oracle::NativePriceOracle; use frame_support::{ genesis_builder_helper::{build_state, get_preset}, sp_runtime::{ @@ -25,7 +26,7 @@ use frame_support::{ }, weights::WeightToFee as _, }; -use hydradx_traits::NativePriceOracle; +use polkadot_xcm::prelude::XcmVersion; use polkadot_xcm::{IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm}; use primitives::constants::chain::CORE_ASSET_ID; use sp_api::impl_runtime_apis; @@ -193,23 +194,23 @@ impl_runtime_apis! { impl xcm_runtime_apis::fees::XcmPaymentApi for Runtime { fn query_acceptable_payment_assets(xcm_version: polkadot_xcm::Version) -> Result, XcmPaymentApiError> { - if !matches!(xcm_version, 3 | 4) { + if !matches!(xcm_version, 3..=5) { return Err(XcmPaymentApiError::UnhandledXcmVersion); } let mut asset_locations = vec![ - AssetLocation(polkadot_xcm::v3::MultiLocation { + AssetLocation(polkadot_xcm::v5::Location { parents: 1, interior: [ - polkadot_xcm::v3::Junction::Parachain(ParachainInfo::get().into()), - polkadot_xcm::v3::Junction::GeneralIndex(CORE_ASSET_ID.into()), + polkadot_xcm::v5::Junction::Parachain(ParachainInfo::get().into()), + polkadot_xcm::v5::Junction::GeneralIndex(CORE_ASSET_ID.into()), ] .into(), }), - AssetLocation(polkadot_xcm::v3::MultiLocation { + AssetLocation(polkadot_xcm::v5::Location { parents: 0, interior: [ - polkadot_xcm::v3::Junction::GeneralIndex(CORE_ASSET_ID.into()), + polkadot_xcm::v5::Junction::GeneralIndex(CORE_ASSET_ID.into()), ] .into(), })]; @@ -217,7 +218,7 @@ impl_runtime_apis! { let mut asset_registry_locations: Vec = pallet_asset_registry::LocationAssets::::iter_keys().collect(); asset_locations.append(&mut asset_registry_locations); - let versioned_locations = asset_locations.iter().map(|loc| VersionedAssetId::V3(polkadot_xcm::v3::AssetId::Concrete(loc.0))); + let versioned_locations = asset_locations.iter().map(|loc| VersionedAssetId::V5(polkadot_xcm::v5::AssetId(loc.0.clone()))); Ok(versioned_locations .filter_map(|asset| asset.into_version(xcm_version).ok()) @@ -225,10 +226,10 @@ impl_runtime_apis! { } fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result { - let v4_xcm_asset_id = asset.into_version(4).map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?; + let v5_xcm_asset_id = asset.into_version(5).map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?; // get nested polkadot_xcm::AssetId type - let xcm_asset_id: &polkadot_xcm::v4::AssetId = v4_xcm_asset_id.try_as().map_err(|_| XcmPaymentApiError::WeightNotComputable)?; + let xcm_asset_id: &polkadot_xcm::v5::AssetId = v5_xcm_asset_id.try_as().map_err(|_| XcmPaymentApiError::WeightNotComputable)?; let asset_id: AssetId = CurrencyIdConvert::convert(xcm_asset_id.clone().0).ok_or(XcmPaymentApiError::AssetNotFound)?; @@ -251,9 +252,17 @@ impl_runtime_apis! { } impl xcm_runtime_apis::dry_run::DryRunApi for Runtime { - fn dry_run_call(origin: OriginCaller, call: RuntimeCall) -> Result, XcmDryRunApiError> { - PolkadotXcm::dry_run_call::(origin, call) - } + fn dry_run_call( + origin: OriginCaller, + call: RuntimeCall, + result_xcms_version: XcmVersion + ) -> Result, XcmDryRunApiError> { + PolkadotXcm::dry_run_call::< + Runtime, + xcm::XcmRouter, + OriginCaller, + RuntimeCall>(origin, call, result_xcms_version) + } fn dry_run_xcm(origin_location: VersionedLocation, xcm: VersionedXcm) -> Result, XcmDryRunApiError> { PolkadotXcm::dry_run_xcm::(origin_location, xcm) @@ -287,9 +296,8 @@ impl_runtime_apis! { Vec, Vec, ) { - use frame_benchmarking::{Benchmarking, BenchmarkList}; + use frame_benchmarking::BenchmarkList; use frame_support::traits::StorageInfoTrait; - use orml_benchmarking::list_benchmark as orml_list_benchmark; use frame_system_benchmarking::Pallet as SystemBench; use pallet_xyk_liquidity_mining_benchmarking::Pallet as XYKLiquidityMiningBench; @@ -298,28 +306,19 @@ impl_runtime_apis! { let mut list = Vec::::new(); list_benchmarks!(list, extra); - orml_list_benchmark!(list, extra, pallet_currencies, benchmarking::currencies); - orml_list_benchmark!(list, extra, pallet_xyk, benchmarking::xyk); - orml_list_benchmark!(list, extra, orml_tokens, benchmarking::tokens); - orml_list_benchmark!(list, extra, orml_vesting, benchmarking::vesting); - orml_list_benchmark!(list, extra, pallet_duster, benchmarking::duster); - orml_list_benchmark!(list, extra, pallet_transaction_multi_payment, benchmarking::multi_payment); - orml_list_benchmark!(list, extra, pallet_route_executor, benchmarking::route_executor); - orml_list_benchmark!(list, extra, pallet_marketplace, benchmarking::marketplace); let storage_info = AllPalletsWithSystem::storage_info(); (list, storage_info) } + #[allow(non_local_definitions)] fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig - ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{BenchmarkError, Benchmarking, BenchmarkBatch}; + ) -> Result, alloc::string::String> { + use frame_benchmarking::{BenchmarkError, BenchmarkBatch}; use frame_support::traits::TrackedStorageKey; use sp_std::sync::Arc; - use orml_benchmarking::add_benchmark as orml_add_benchmark; - use frame_system_benchmarking::Pallet as SystemBench; use pallet_xyk_liquidity_mining_benchmarking::Pallet as XYKLiquidityMiningBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; @@ -436,15 +435,6 @@ impl_runtime_apis! { let params = (&config, &whitelist); add_benchmarks!(params, batches); - orml_add_benchmark!(params, batches, pallet_xyk, benchmarking::xyk); - orml_add_benchmark!(params, batches, pallet_currencies, benchmarking::currencies); - orml_add_benchmark!(params, batches, orml_tokens, benchmarking::tokens); - orml_add_benchmark!(params, batches, orml_vesting, benchmarking::vesting); - orml_add_benchmark!(params, batches, pallet_duster, benchmarking::duster); - orml_add_benchmark!(params, batches, pallet_transaction_multi_payment, benchmarking::multi_payment); - orml_add_benchmark!(params, batches, pallet_route_executor, benchmarking::route_executor); - orml_add_benchmark!(params, batches, pallet_marketplace, benchmarking::marketplace); - if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) } diff --git a/runtime/basilisk/src/assets.rs b/runtime/basilisk/src/assets.rs index 3f3e7cdf476..756be970fd9 100644 --- a/runtime/basilisk/src/assets.rs +++ b/runtime/basilisk/src/assets.rs @@ -19,10 +19,17 @@ use super::*; use crate::governance::origins::GeneralAdmin; use crate::system::NativeAssetId; +use basilisk_traits::{ + OnTradeHandler, + { + oracle::OraclePeriod, + router::{inverse_route, AmmTradeWeights, PoolType, Trade}, + }, +}; + use hydradx_traits::{ fee::{InspectTransactionFeeCurrency, SwappablePaymentAssetTrader}, - router::{inverse_route, AmmTradeWeights, PoolType, Trade}, - AssetKind, AssetPairAccountIdFor, LockedBalance, OnTradeHandler, OraclePeriod, Source, AMM, + AssetKind, AssetPairAccountIdFor, LockedBalance, Source, AMM, }; use pallet_currencies::fungibles::FungibleCurrencies; use pallet_currencies::BasicCurrencyAdapter; @@ -41,8 +48,8 @@ use frame_support::{ app_crypto::sp_core::crypto::UncheckedFrom, traits::Zero, ArithmeticError, DispatchError, DispatchResult, }, traits::{ - AsEnsureOriginWithArg, Contains, Currency, Defensive, EitherOf, EnsureOrigin, Get, Imbalance, LockIdentifier, - NeverEnsureOrigin, OnUnbalanced, + AsEnsureOriginWithArg, Contains, Currency, Defensive, EitherOf, EnsureOrigin, ExistenceRequirement, Get, + Imbalance, LockIdentifier, NeverEnsureOrigin, OnUnbalanced, }, BoundedVec, PalletId, }; @@ -97,6 +104,7 @@ impl pallet_balances::Config for Runtime { type MaxFreezes = (); type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; + type DoneSlashHandler = (); } pub struct CurrencyHooks; @@ -200,6 +208,7 @@ impl MultiCurrency for NoEvmSupport { _from: &AccountId, _to: &AccountId, _amount: Self::Balance, + _existence_requirement: ExistenceRequirement, ) -> sp_runtime::DispatchResult { Err(DispatchError::Other("EVM not supported")) } @@ -208,7 +217,12 @@ impl MultiCurrency for NoEvmSupport { Err(DispatchError::Other("EVM not supported")) } - fn withdraw(_contract: Self::CurrencyId, _who: &AccountId, _amount: Self::Balance) -> sp_runtime::DispatchResult { + fn withdraw( + _contract: Self::CurrencyId, + _who: &AccountId, + _amount: Self::Balance, + _existence_requirement: ExistenceRequirement, + ) -> sp_runtime::DispatchResult { Err(DispatchError::Other("EVM not supported")) } @@ -221,6 +235,32 @@ impl MultiCurrency for NoEvmSupport { } } +pub struct NoErc20Support; + +impl hydradx_traits::evm::Erc20Inspect for NoErc20Support { + fn contract_address(_id: AssetId) -> Option { + None + } + + fn is_atoken(_asset_id: AssetId) -> bool { + false + } +} + +impl hydradx_traits::evm::Erc20OnDust for NoErc20Support { + fn on_dust( + _account: &AccountId, + _dust_dest_account: &AccountId, + _currency_id: AssetId, + ) -> frame_support::dispatch::DispatchResult { + Err(DispatchError::Other("EVM not supported")) + } +} + +parameter_types! { + pub ReserveAccount: AccountId = PalletId( * b"curreser").into_account_truncating(); +} + // The latest versions of the orml-currencies pallet don't emit events. // The infrastructure relies on the events from this pallet, so we use the latest version of // the pallet that contains and emit events and was updated to the polkadot version we use. @@ -230,6 +270,7 @@ impl pallet_currencies::Config for Runtime { type NativeCurrency = BasicCurrencyAdapter; type Erc20Currency = NoEvmSupport; type BoundErc20 = NoEvmSupport; + type ReserveAccount = ReserveAccount; type GetNativeCurrencyId = NativeAssetId; type WeightInfo = weights::pallet_currencies::BasiliskWeight; } @@ -255,14 +296,11 @@ parameter_types! { impl pallet_duster::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type Balance = Balance; - type Amount = Amount; - type CurrencyId = AssetId; - type MultiCurrency = Currencies; - type MinCurrencyDeposits = AssetRegistry; - type Reward = DustingReward; - type NativeCurrencyId = NativeAssetId; - type BlacklistUpdateOrigin = EitherOf, GeneralAdmin>; + type AssetId = AssetId; + type MultiCurrency = FungibleCurrencies; + type ExistentialDeposit = AssetRegistry; + type WhitelistUpdateOrigin = EitherOf, GeneralAdmin>; + type Erc20Support = NoErc20Support; type TreasuryAccountId = TreasuryAccount; type WeightInfo = weights::pallet_duster::BasiliskWeight; } @@ -314,7 +352,7 @@ impl pallet_xyk::Config for Runtime { type MaxInRatio = MaxInRatio; type MaxOutRatio = MaxOutRatio; type OracleSource = XYKOracleSourceIdentifier; - type CanCreatePool = hydradx_adapters::xyk::AllowPoolCreation; + type CanCreatePool = basilisk_adapters::xyk::AllowPoolCreation; type AMMHandler = pallet_ema_oracle::OnActivityHandler; type DiscountedFee = DiscountedFee; type NonDustableWhitelistHandler = Duster; @@ -372,7 +410,7 @@ impl pallet_lbp::Config for Runtime { #[cfg(feature = "runtime-benchmarks")] use codec::Decode; use frame_support::traits::Everything; -use hydradx_traits::evm::EvmAddress; +use primitives::EvmAddress; pub struct RootAsVestingPallet; impl EnsureOrigin for RootAsVestingPallet { @@ -782,7 +820,7 @@ parameter_types! { pub struct RefundAndLockedEdCalculator; -use hydradx_traits::router::RefundEdCalculator; +use basilisk_traits::router::RefundEdCalculator; impl RefundEdCalculator for RefundAndLockedEdCalculator { fn calculate() -> Balance { // all assets are sufficient so `RefundAndLockedEdCalculator` is never called. diff --git a/runtime/basilisk/src/benchmarking/duster.rs b/runtime/basilisk/src/benchmarking/duster.rs index b41e8cb44f3..82f2199dec6 100644 --- a/runtime/basilisk/src/benchmarking/duster.rs +++ b/runtime/basilisk/src/benchmarking/duster.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{AccountId, AssetId, Balance, Duster, DustingReward, NativeAssetId, Runtime, Tokens}; +use crate::{AccountId, AssetId, Balance, Runtime, Tokens, TreasuryAccount}; use super::*; @@ -44,16 +44,13 @@ runtime_benchmarks! { dust_account{ let caller: AccountId = account("caller", 0, SEED); let to_dust_account: AccountId = account("dust", 0, SEED); - let dust_dest_account: AccountId = account("dest", 1, SEED); - pallet_duster::DustAccount::::put(dust_dest_account); + let dest_account = TreasuryAccount::get(); let asset_id = register_asset(b"TST".to_vec(), 100u128).map_err(|_| BenchmarkError::Stop("Failed to register asset"))?; - let reward = DustingReward::get(); - let dest_account = Duster::dust_dest_account(); let min_deposit = AssetRegistry::get(&asset_id); - update_balance(asset_id, &dest_account.clone().unwrap(), min_deposit); + update_balance(asset_id, &dest_account, min_deposit); let dust_amount = min_deposit; @@ -62,31 +59,28 @@ runtime_benchmarks! { update_asset(asset_id, b"TST".to_vec(), 110u128).map_err(|_| BenchmarkError::Stop("Failed to update asset"))?; assert_eq!(Tokens::free_balance(asset_id, &to_dust_account), dust_amount); - let current_balance = Tokens::free_balance(asset_id, &dest_account.clone().unwrap()); + let current_balance = Tokens::free_balance(asset_id, &dest_account); - }: { pallet_duster::Pallet::::dust_account(RawOrigin::Signed(caller.clone()).into(), to_dust_account.clone(),asset_id)? } + }: { pallet_duster::Pallet::::dust_account(RawOrigin::Signed(caller.clone()).into(), to_dust_account.clone(), asset_id)? } verify { assert_eq!(Tokens::free_balance(asset_id, &to_dust_account), 0u128); - assert_eq!(Tokens::free_balance(NativeAssetId::get(), &caller), reward); - assert_eq!(Tokens::free_balance(asset_id, &dest_account.unwrap()), current_balance + dust_amount); + assert_eq!(Tokens::free_balance(asset_id, &dest_account), current_balance + dust_amount); } - add_nondustable_account{ - let caller: AccountId = account("caller", 0, SEED); + whitelist_account{ let nondustable_account: AccountId = account("dust", 0, SEED); - }: { pallet_duster::Pallet::::add_nondustable_account(RawOrigin::Root.into(), nondustable_account.clone())? } + }: { pallet_duster::Pallet::::whitelist_account(RawOrigin::Root.into(), nondustable_account.clone())? } verify { - assert!(pallet_duster::Pallet::::blacklisted(&nondustable_account).is_some()); + assert!(pallet_duster::Pallet::::whitelisted(&nondustable_account).is_some()); } - remove_nondustable_account{ - let caller: AccountId = account("caller", 0, SEED); + remove_from_whitelist{ let nondustable_account: AccountId = account("dust", 0, SEED); - pallet_duster::Pallet::::add_nondustable_account(RawOrigin::Root.into(), nondustable_account.clone())?; + pallet_duster::Pallet::::whitelist_account(RawOrigin::Root.into(), nondustable_account.clone())?; - }: { pallet_duster::Pallet::::remove_nondustable_account(RawOrigin::Root.into(), nondustable_account.clone())? } + }: { pallet_duster::Pallet::::remove_from_whitelist(RawOrigin::Root.into(), nondustable_account.clone())? } verify { - assert!(pallet_duster::Pallet::::blacklisted(&nondustable_account).is_none()); + assert!(pallet_duster::Pallet::::whitelisted(&nondustable_account).is_none()); } } diff --git a/runtime/basilisk/src/benchmarking/mod.rs b/runtime/basilisk/src/benchmarking/mod.rs index 5068a0eb87d..fb87560b917 100644 --- a/runtime/basilisk/src/benchmarking/mod.rs +++ b/runtime/basilisk/src/benchmarking/mod.rs @@ -27,6 +27,7 @@ use sp_std::vec::Vec; use frame_support::storage::with_transaction; use hydradx_traits::{AssetKind, Create}; use orml_traits::MultiCurrencyExtended; +use polkadot_xcm::v5::Location; use sp_runtime::{ traits::{One, SaturatedConversion}, FixedU128, TransactionOutcome, @@ -86,7 +87,7 @@ pub fn set_location(asset_id: AssetId, location: AssetLocation) -> Result<(), () AssetRegistry::set_location(RawOrigin::Root.into(), asset_id, location).map_err(|_| ()) } -pub const DOT_ASSET_LOCATION: AssetLocation = AssetLocation(polkadot_xcm::v3::MultiLocation::parent()); +pub const DOT_ASSET_LOCATION: AssetLocation = AssetLocation(Location::parent()); fn setup_insufficient_asset_with_dot() -> Result { let dot = register_asset(b"DOT".to_vec(), 1u128).map_err(|_| BenchmarkError::Stop("Failed to register asset"))?; set_location(dot, DOT_ASSET_LOCATION).map_err(|_| BenchmarkError::Stop("Failed to set location for weth"))?; diff --git a/runtime/basilisk/src/benchmarking/multi_payment.rs b/runtime/basilisk/src/benchmarking/multi_payment.rs index 5e7875027f9..939230c888c 100644 --- a/runtime/basilisk/src/benchmarking/multi_payment.rs +++ b/runtime/basilisk/src/benchmarking/multi_payment.rs @@ -19,6 +19,8 @@ use super::*; use crate::{AccountId, AssetId, Balance, Currencies, EmaOracle, Runtime, System}; +use basilisk_traits::router::PoolType; +use basilisk_traits::{oracle::PriceOracle, router::RouteProvider}; use frame_benchmarking::account; use frame_benchmarking::BenchmarkError; use frame_support::{assert_ok, parameter_types}; @@ -27,9 +29,6 @@ use frame_support::{ traits::{OnFinalize, OnInitialize}, }; use frame_system::RawOrigin; -use hydradx_traits::router::PoolType; -use hydradx_traits::router::RouteProvider; -use hydradx_traits::PriceOracle; use orml_benchmarking::runtime_benchmarks; use orml_traits::MultiCurrencyExtended; use pallet_route_executor::MAX_NUMBER_OF_TRADES; @@ -43,9 +42,9 @@ use sp_runtime::{FixedPointNumber, FixedU128}; type MultiPaymentPallet = pallet_transaction_multi_payment::Pallet; type XykPallet = pallet_xyk::Pallet; type Router = pallet_route_executor::Pallet; -use hydradx_traits::router::AssetPair; -use hydradx_traits::router::Trade; -use hydradx_traits::OraclePeriod; +use basilisk_traits::oracle::OraclePeriod; +use basilisk_traits::router::AssetPair; +use basilisk_traits::router::Trade; parameter_types! { //NOTE: This should always be > 1 otherwise we will payout more than we collected as ED for @@ -195,7 +194,7 @@ runtime_benchmarks! { let tip = 0; let mut tx_result : Result, Price>>, TransactionValidityError> = Err(TransactionValidityError::Invalid(InvalidTransaction::Payment)); }: { - tx_result = , TreasuryAccount> as OnChargeTransaction>::withdraw_fee(&from, &call, &info, fee, tip); + tx_result = , TreasuryAccount> as OnChargeTransaction>::withdraw_fee(&from, &call, &info, fee, tip); } verify { assert!(tx_result.is_ok()); diff --git a/runtime/basilisk/src/benchmarking/route_executor.rs b/runtime/basilisk/src/benchmarking/route_executor.rs index 7229be92357..73af32d9f8f 100644 --- a/runtime/basilisk/src/benchmarking/route_executor.rs +++ b/runtime/basilisk/src/benchmarking/route_executor.rs @@ -19,6 +19,10 @@ use crate::{AccountId, AssetId, Balance, Currencies, EmaOracle, Router, Runtime, RuntimeOrigin, System, LBP, XYK}; use super::*; +use basilisk_traits::{ + oracle::PriceOracle, + router::{inverse_route, AssetPair, PoolType, RouteProvider, RouteSpotPriceProvider, RouterT, Trade}, +}; use frame_benchmarking::{account, BenchmarkError, BenchmarkResult}; use frame_support::{ assert_ok, @@ -28,10 +32,6 @@ use frame_support::{ weights::Weight, }; use frame_system::RawOrigin; -use hydradx_traits::{ - router::{inverse_route, AssetPair, PoolType, RouteProvider, RouteSpotPriceProvider, RouterT, Trade}, - PriceOracle, -}; use orml_benchmarking::runtime_benchmarks; use orml_traits::{MultiCurrency, MultiCurrencyExtended}; use pallet_ema_oracle::OraclePeriod; diff --git a/runtime/basilisk/src/benchmarking/xyk.rs b/runtime/basilisk/src/benchmarking/xyk.rs index c35892c463b..947dee3bc57 100644 --- a/runtime/basilisk/src/benchmarking/xyk.rs +++ b/runtime/basilisk/src/benchmarking/xyk.rs @@ -3,12 +3,13 @@ use crate::{AccountId, AssetId, Balance, Currencies, MultiTransactionPayment, Pr use super::*; use frame_benchmarking::{account, BenchmarkError}; +use frame_support::traits::ExistenceRequirement; use frame_system::RawOrigin; use orml_benchmarking::runtime_benchmarks; use orml_traits::{MultiCurrency, MultiCurrencyExtended}; use sp_std::prelude::*; -use hydradx_traits::router::{PoolType, TradeExecution}; +use basilisk_traits::router::{PoolType, TradeExecution}; const SEED: u32 = 1; @@ -87,7 +88,7 @@ runtime_benchmarks! { XYK::create_pool(RawOrigin::Signed(maker.clone()).into(), asset_a, INITIAL_BALANCE - 10, asset_b, INITIAL_BALANCE - 10)?; - >::transfer(asset_a, &caller, &maker, INITIAL_BALANCE - amount)?; + >::transfer(asset_a, &caller, &maker, INITIAL_BALANCE - amount, ExistenceRequirement::AllowDeath)?; assert_eq!(frame_system::Pallet::::account(caller.clone()).sufficients, 0); }: _(RawOrigin::Signed(caller.clone()), asset_a, asset_b, amount, max_limit) @@ -142,7 +143,7 @@ runtime_benchmarks! { XYK::create_pool(RawOrigin::Signed(maker.clone()).into(), asset_a, INITIAL_BALANCE, asset_b, INITIAL_BALANCE)?; - >::transfer(asset_a, &caller, &maker, INITIAL_BALANCE - amount)?; + >::transfer(asset_a, &caller, &maker, INITIAL_BALANCE - amount, ExistenceRequirement::AllowDeath)?; assert_eq!(frame_system::Pallet::::account(caller.clone()).sufficients, 0); }: _(RawOrigin::Signed(caller.clone()), asset_a, asset_b, amount, min_bought, discount) @@ -173,7 +174,7 @@ runtime_benchmarks! { XYK::create_pool(RawOrigin::Signed(maker.clone()).into(), asset_a, INITIAL_BALANCE, asset_b, INITIAL_BALANCE)?; - >::transfer(asset_a, &caller, &maker, 749_249_999_999_999_u128)?; + >::transfer(asset_a, &caller, &maker, 749_249_999_999_999_u128, ExistenceRequirement::AllowDeath)?; assert_eq!(frame_system::Pallet::::account(caller.clone()).sufficients, 0); }: _(RawOrigin::Signed(caller.clone()), asset_b, asset_a, amount, max_sold, discount) @@ -207,7 +208,7 @@ runtime_benchmarks! { XYK::create_pool(RawOrigin::Signed(maker.clone()).into(), asset_a, INITIAL_BALANCE, asset_b, INITIAL_BALANCE)?; - >::transfer(asset_a, &caller, &maker, INITIAL_BALANCE - amount)?; + >::transfer(asset_a, &caller, &maker, INITIAL_BALANCE - amount, ExistenceRequirement::AllowDeath)?; assert_eq!(frame_system::Pallet::::account(caller.clone()).sufficients, 0); }: { for _ in 1..c { @@ -248,7 +249,7 @@ runtime_benchmarks! { XYK::create_pool(RawOrigin::Signed(maker.clone()).into(), asset_a, INITIAL_BALANCE, asset_b, INITIAL_BALANCE)?; - >::transfer(asset_a, &caller, &maker, 749_249_999_999_999_u128)?; + >::transfer(asset_a, &caller, &maker, 749_249_999_999_999_u128, ExistenceRequirement::AllowDeath)?; assert_eq!(frame_system::Pallet::::account(caller.clone()).sufficients, 0); }: { @@ -287,7 +288,7 @@ runtime_benchmarks! { XYK::create_pool(RawOrigin::Signed(maker.clone()).into(), asset_a, INITIAL_BALANCE, asset_b, INITIAL_BALANCE)?; - >::transfer(asset_a, &caller, &maker, 749_249_999_999_999_u128)?; + >::transfer(asset_a, &caller, &maker, 749_249_999_999_999_u128, ExistenceRequirement::AllowDeath)?; assert_eq!(frame_system::Pallet::::account(caller).sufficients, 0); }: { diff --git a/runtime/basilisk/src/governance/mod.rs b/runtime/basilisk/src/governance/mod.rs index 7301c616ae1..8af54a06e0b 100644 --- a/runtime/basilisk/src/governance/mod.rs +++ b/runtime/basilisk/src/governance/mod.rs @@ -17,7 +17,7 @@ use super::*; use crate::governance::tracks::TracksInfo; -use crate::origins::{ReferendumCanceller, ReferendumKiller, Spender, Treasurer, WhitelistedCaller}; +use crate::origins::{GeneralAdmin, ReferendumCanceller, ReferendumKiller, Spender, Treasurer, WhitelistedCaller}; use frame_support::{ parameter_types, sp_runtime::Permill, @@ -60,6 +60,9 @@ impl pallet_collective::Config for Runtime { type WeightInfo = weights::pallet_collective::BasiliskWeight; type MaxProposalWeight = MaxProposalWeight; type SetMembersOrigin = EnsureRoot; + type DisapproveOrigin = EitherOf, GeneralAdmin>; + type KillOrigin = EitherOf, GeneralAdmin>; + type Consideration = (); } parameter_types! { @@ -75,6 +78,9 @@ impl pallet_conviction_voting::Config for Runtime { type MaxVotes = ConstU32<512>; type VoteLockingPeriod = VoteLockingPeriod; type VotingHooks = (); + // Any single technical committee member may remove a vote. + type VoteRemovalOrigin = frame_system::EnsureSignedBy; + type BlockNumberProvider = System; } parameter_types! { @@ -117,6 +123,7 @@ impl pallet_referenda::Config for Runtime { type AlarmInterval = AlarmInterval; type Tracks = TracksInfo; type Preimages = Preimage; + type BlockNumberProvider = System; } parameter_types! { @@ -155,6 +162,7 @@ impl pallet_treasury::Config for Runtime { type PayoutPeriod = TreasuryPayoutPeriod; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = benchmarking::BenchmarkHelper; + type BlockNumberProvider = System; } pub struct PayFromTreasuryAccount; diff --git a/runtime/basilisk/src/governance/origins.rs b/runtime/basilisk/src/governance/origins.rs index ef05ae5a730..205737bb4dc 100644 --- a/runtime/basilisk/src/governance/origins.rs +++ b/runtime/basilisk/src/governance/origins.rs @@ -33,7 +33,7 @@ pub mod pallet_custom_origins { #[pallet::pallet] pub struct Pallet(_); - #[derive(PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, TypeInfo, RuntimeDebug)] + #[derive(PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, DecodeWithMemTracking, TypeInfo, RuntimeDebug)] #[pallet::origin] pub enum Origin { /// Origin able to dispatch a whitelisted call. diff --git a/runtime/basilisk/src/governance/tracks.rs b/runtime/basilisk/src/governance/tracks.rs index 552efffe37a..9abfa2b4ec4 100644 --- a/runtime/basilisk/src/governance/tracks.rs +++ b/runtime/basilisk/src/governance/tracks.rs @@ -22,11 +22,12 @@ use primitives::constants::{ currency::UNITS, time::{HOURS, MINUTES}, }; +use sp_runtime::{str_array as s, Cow}; const fn percent(x: i32) -> sp_arithmetic::FixedI64 { sp_arithmetic::FixedI64::from_rational(x as u128, 100) } -use pallet_referenda::Curve; +use pallet_referenda::{Curve, Track, TrackInfo}; const APP_LINEAR: Curve = Curve::make_linear(7, 7, percent(50), percent(100)); const APP_LINEAR_FLAT: Curve = Curve::make_linear(4, 7, percent(50), percent(100)); const APP_RECIP: Curve = Curve::make_reciprocal(1, 7, percent(80), percent(50), percent(100)); @@ -35,26 +36,26 @@ const SUP_RECIP: Curve = Curve::make_reciprocal(5, 7, percent(1), percent(0), pe const SUP_FAST_RECIP: Curve = Curve::make_reciprocal(3, 7, percent(1), percent(0), percent(50)); const SUP_WHITELISTED_CALLER: Curve = Curve::make_linear(1, 7, percent(0), percent(1)); -const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 8] = [ - ( - 0, - pallet_referenda::TrackInfo { - name: "root", - max_deciding: 1, +const TRACKS_DATA: [Track; 8] = [ + Track { + id: 0, + info: TrackInfo { + name: s("root"), + max_deciding: 3, decision_deposit: 100_000_000 * UNITS, - prepare_period: 24 * HOURS, + prepare_period: HOURS, decision_period: 7 * DAYS, - confirm_period: 24 * HOURS, - min_enactment_period: 24 * HOURS, + confirm_period: 12 * HOURS, + min_enactment_period: 10 * MINUTES, min_approval: APP_RECIP, min_support: SUP_LINEAR, }, - ), - ( - 1, - pallet_referenda::TrackInfo { - name: "whitelisted_caller", - max_deciding: 10, + }, + Track { + id: 1, + info: TrackInfo { + name: s("whitelisted_caller"), + max_deciding: 3, decision_deposit: 1_000_000 * UNITS, prepare_period: 10 * MINUTES, decision_period: DAYS, @@ -63,25 +64,25 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 8] min_approval: APP_RECIP, min_support: SUP_WHITELISTED_CALLER, }, - ), - ( - 2, - pallet_referenda::TrackInfo { - name: "referendum_canceller", + }, + Track { + id: 2, + info: TrackInfo { + name: s("referendum_canceller"), max_deciding: 10, decision_deposit: 10_000_000 * UNITS, prepare_period: 60 * MINUTES, decision_period: 3 * DAYS, - confirm_period: 12 * HOURS, + confirm_period: 60 * MINUTES, min_enactment_period: 10 * MINUTES, min_approval: APP_LINEAR_FLAT, min_support: SUP_FAST_RECIP, }, - ), - ( - 3, - pallet_referenda::TrackInfo { - name: "referendum_killer", + }, + Track { + id: 3, + info: TrackInfo { + name: s("referendum_killer"), max_deciding: 10, decision_deposit: 50_000_000 * UNITS, prepare_period: 60 * MINUTES, @@ -91,11 +92,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 8] min_approval: APP_LINEAR_FLAT, min_support: SUP_FAST_RECIP, }, - ), - ( - 4, - pallet_referenda::TrackInfo { - name: "general_admin", + }, + Track { + id: 4, + info: TrackInfo { + name: s("general_admin"), max_deciding: 10, decision_deposit: 10_000_000 * UNITS, prepare_period: 60 * MINUTES, @@ -105,11 +106,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 8] min_approval: APP_RECIP, min_support: SUP_RECIP, }, - ), - ( - 5, - pallet_referenda::TrackInfo { - name: "treasurer", + }, + Track { + id: 5, + info: TrackInfo { + name: s("treasurer"), max_deciding: 10, decision_deposit: 50_000_000 * UNITS, prepare_period: 60 * MINUTES, @@ -119,11 +120,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 8] min_approval: APP_RECIP, min_support: SUP_LINEAR, }, - ), - ( - 6, - pallet_referenda::TrackInfo { - name: "spender", + }, + Track { + id: 6, + info: TrackInfo { + name: s("spender"), max_deciding: 10, decision_deposit: 5_000_000 * UNITS, prepare_period: 60 * MINUTES, @@ -133,11 +134,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 8] min_approval: APP_LINEAR, min_support: SUP_RECIP, }, - ), - ( - 7, - pallet_referenda::TrackInfo { - name: "tipper", + }, + Track { + id: 7, + info: TrackInfo { + name: s("tipper"), max_deciding: 10, decision_deposit: 500_000 * UNITS, prepare_period: 60 * MINUTES, @@ -147,16 +148,17 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 8] min_approval: APP_LINEAR_FLAT, min_support: SUP_FAST_RECIP, }, - ), + }, ]; pub struct TracksInfo; impl pallet_referenda::TracksInfo for TracksInfo { type Id = u16; type RuntimeOrigin = ::PalletsOrigin; - fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] { - &TRACKS_DATA[..] + fn tracks() -> impl Iterator>> { + TRACKS_DATA.iter().map(Cow::Borrowed) } + fn track_for(id: &Self::RuntimeOrigin) -> Result { if let Ok(system_origin) = frame_system::RawOrigin::try_from(id.clone()) { match system_origin { @@ -178,4 +180,3 @@ impl pallet_referenda::TracksInfo for TracksInfo { } } } -pallet_referenda::impl_tracksinfo_get!(TracksInfo, Balance, BlockNumber); diff --git a/runtime/basilisk/src/lib.rs b/runtime/basilisk/src/lib.rs index be650e08d80..e5dc9d0bbe0 100644 --- a/runtime/basilisk/src/lib.rs +++ b/runtime/basilisk/src/lib.rs @@ -33,6 +33,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); mod tests; mod benchmarking; +mod migrations; pub mod weights; mod adapter; @@ -48,10 +49,6 @@ pub use governance::*; pub use system::*; pub use xcm::*; -use frame_support::sp_runtime::{ - create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdConversion, BlakeTwo256, Block as BlockT}, -}; use frame_system::pallet_prelude::BlockNumberFor; pub use primitives::{ constants::time::SLOT_DURATION, AccountId, Amount, AssetId, Balance, BlockNumber, CollectionId, Hash, Index, @@ -59,10 +56,16 @@ pub use primitives::{ }; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::ConstU32; +use sp_runtime::{ + generic, impl_opaque_keys, + traits::{AccountIdConversion, BlakeTwo256, Block as BlockT, BlockNumberProvider}, + Cow, +}; use sp_std::{convert::From, marker::PhantomData, prelude::*, vec}; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; +extern crate alloc; // A few exports that help ease life for downstream crates. use frame_support::{construct_runtime, weights::Weight}; @@ -97,14 +100,14 @@ pub mod opaque { #[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("basilisk"), - impl_name: create_runtime_str!("basilisk"), + spec_name: Cow::Borrowed("basilisk"), + impl_name: Cow::Borrowed("basilisk"), authoring_version: 1, - spec_version: 127, + spec_version: 128, impl_version: 0, apis: apis::RUNTIME_API_VERSIONS, transaction_version: 1, - state_version: 1, + system_version: 1, }; /// The version information used to identify this runtime when compiled natively. @@ -123,8 +126,6 @@ pub fn get_all_module_accounts() -> vec::Vec { ] } -use sp_runtime::traits::BlockNumberProvider; - // Relay chain Block number provider. // Reason why the implementation is different for benchmarks is that it is not possible // to set or change the block number in a benchmark using parachain system pallet. @@ -270,18 +271,10 @@ pub type Executive = frame_executive::Executive< migrations::Migrations, >; -pub mod migrations { - use super::*; - - impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { - type ChannelList = ParachainSystem; - } - - pub type Migrations = (cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5,); -} - #[cfg(feature = "runtime-benchmarks")] mod benches { + use super::*; + frame_support::parameter_types! { pub const BenchmarkMaxBalance: crate::Balance = crate::Balance::MAX; } @@ -293,6 +286,7 @@ mod benches { [pallet_transaction_pause, TransactionPause] [pallet_ema_oracle, EmaOracle] [frame_system, SystemBench::] + [frame_system_extensions, frame_system_benchmarking::extensions::Pallet::] [pallet_balances, Balances] [pallet_timestamp, Timestamp] [pallet_democracy, Democracy] @@ -313,6 +307,15 @@ mod benches { [pallet_conviction_voting, ConvictionVoting] [pallet_referenda, Referenda] [pallet_whitelist, Whitelist] + [pallet_transaction_payment, TransactionPayment] + [pallet_xyk, benchmarking::xyk::Benchmark] + [pallet_currencies, benchmarking::currencies::Benchmark] + [orml_tokens, benchmarking::tokens::Benchmark] + [orml_vesting, benchmarking::vesting::Benchmark] + [pallet_duster, benchmarking::duster::Benchmark] + [pallet_transaction_multi_payment, benchmarking::multi_payment::Benchmark] + [pallet_route_executor, benchmarking::route_executor::Benchmark] + [pallet_marketplace, benchmarking::marketplace::Benchmark] ); } diff --git a/runtime/basilisk/src/migrations/asset_registry.rs b/runtime/basilisk/src/migrations/asset_registry.rs new file mode 100644 index 00000000000..3994af9880b --- /dev/null +++ b/runtime/basilisk/src/migrations/asset_registry.rs @@ -0,0 +1,317 @@ +// Copyright (C) 2020-2025 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use codec::{Decode, Encode, MaxEncodedLen}; +use core::convert::TryFrom; +use frame_support::pallet_prelude::OptionQuery; +use frame_support::{storage_alias, traits::OnRuntimeUpgrade, weights::Weight, Blake2_128Concat, Twox64Concat}; +use pallet_asset_registry::*; +use scale_info::TypeInfo; +use sp_core::Get; +use sp_std::vec::Vec; + +// Import XCM types +use polkadot_xcm::v3::MultiLocation as V3MultiLocation; +use polkadot_xcm::v5::Location as V5Location; +use polkadot_xcm::VersionedLocation; + +/// Old AssetLocation wrapper type that matches the on-chain encoding +/// The old type was: `pub struct AssetLocation(pub MultiLocation);` +#[derive(Debug, Default, Encode, Decode, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +pub struct OldAssetLocation(pub V3MultiLocation); + +/// Module containing old storage type aliases with correct storage names +mod old_storage { + use super::*; + + #[storage_alias] + pub type AssetLocations = + StorageMap, Twox64Concat, ::AssetId, OldAssetLocation, OptionQuery>; + + #[storage_alias] + pub type LocationAssets = + StorageMap, Blake2_128Concat, OldAssetLocation, ::AssetId, OptionQuery>; +} + +// This migration re-encodes AssetLocations storage to ensure proper v5 Location encoding. +// +// Even though v3 MultiLocation and v5 Location have compatible SCALE encodings for most cases, +// we want to ensure the data is stored with the canonical v5 encoding. +// +// The migration does not use a StorageVersion, make sure it is removed from the Runtime Executive +// after it has been run. +pub struct MigrateAssetRegistryToXcmV5(sp_std::marker::PhantomData); +impl OnRuntimeUpgrade for MigrateAssetRegistryToXcmV5 +where + T::AssetNativeLocation: TryFrom, +{ + fn on_runtime_upgrade() -> Weight { + log::info!( + target: "asset-registry", + "MigrateAssetRegistryToXcmV5 started..." + ); + + let mut reads = 0u64; + let mut writes = 0u64; + + // Use the old storage type to drain all entries + let old_locations: Vec<(T::AssetId, OldAssetLocation)> = old_storage::AssetLocations::::drain().collect(); + + log::info!( + target: "asset-registry", + "Found {} locations to migrate", + old_locations.len() + ); + + // Clear the old reverse map + let _ = old_storage::LocationAssets::::clear(u32::MAX, None); + + for (asset_id, old_loc) in old_locations { + reads += 1; + + // Convert v3 MultiLocation -> v5 Location via VersionedLocation + let versioned = VersionedLocation::V3(old_loc.0); + let v5_location: V5Location = match versioned.try_into() { + Ok(loc) => loc, + Err(_) => { + log::error!( + target: "asset-registry", + "Asset {:?}: Failed to convert v3->v5, skipping", + asset_id + ); + continue; + } + }; + + // Create new AssetNativeLocation from the v5 location + let new_loc: T::AssetNativeLocation = match v5_location.clone().try_into() { + Ok(loc) => loc, + Err(_) => { + log::error!( + target: "asset-registry", + "Asset {:?}: Failed to create AssetNativeLocation from V5Location, skipping", + asset_id + ); + continue; + } + }; + + // Safety check: break if we've exceeded the write limit + if writes >= 50 { + log::warn!( + target: "asset-registry", + "Migration stopped: reached safety limit of 50 writes" + ); + break; + } + + // Write back with proper v5 encoding + AssetLocations::::insert(asset_id, &new_loc); + writes += 1; + + // Update reverse map with new encoding + LocationAssets::::insert(&new_loc, asset_id); + writes += 1; + + log::info!( + target: "asset-registry", + "Asset {:?}: re-encoded location to v5", + asset_id + ); + } + + log::info!( + target: "asset-registry", + "MigrateAssetRegistryToXcmV5 finished — {} reads, {} writes", + reads, + writes + ); + + T::DbWeight::get().reads_writes(reads, writes) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::Runtime; + use frame_support::traits::OnRuntimeUpgrade; + use polkadot_xcm::v3::MultiLocation as V3MultiLocation; + use sp_io::TestExternalities; + use sp_runtime::BuildStorage; + + fn new_test_ext() -> TestExternalities { + frame_system::GenesisConfig::::default() + .build_storage() + .unwrap() + .into() + } + + fn mock_old_location_parent() -> OldAssetLocation { + OldAssetLocation(V3MultiLocation { + parents: 1, + interior: polkadot_xcm::v3::Junctions::Here, + }) + } + + fn mock_old_location_with_index(parents: u8, index: u128) -> OldAssetLocation { + OldAssetLocation(V3MultiLocation { + parents, + interior: polkadot_xcm::v3::Junctions::X1(polkadot_xcm::v3::Junction::GeneralIndex(index)), + }) + } + + fn mock_old_location_parachain(para_id: u32) -> OldAssetLocation { + OldAssetLocation(V3MultiLocation { + parents: 1, + interior: polkadot_xcm::v3::Junctions::X1(polkadot_xcm::v3::Junction::Parachain(para_id)), + }) + } + + #[test] + fn migration_converts_v3_parent_location_to_v5() { + new_test_ext().execute_with(|| { + let asset_id: u32 = 1; + let old_location = mock_old_location_parent(); + + // Insert using the old storage type (OldAssetLocation wrapping v3 MultiLocation) + old_storage::AssetLocations::::insert(asset_id, old_location.clone()); + assert!(old_storage::AssetLocations::::contains_key(asset_id)); + + // Run migration + let weight = MigrateAssetRegistryToXcmV5::::on_runtime_upgrade(); + assert!( + weight.ref_time() > 0, + "weight should be > 0, meaning migration processed entries" + ); + + // Verify the location was migrated to new storage + let migrated = AssetLocations::::get(asset_id).expect("should exist after migration"); + + // Check the migrated location has correct v5 structure + assert_eq!(migrated.0.parents, 1); + assert_eq!(migrated.0.interior, polkadot_xcm::v5::Junctions::Here); + + // Verify reverse mapping was created + let reverse = LocationAssets::::get(&migrated); + assert_eq!(reverse, Some(asset_id)); + }); + } + + #[test] + fn migration_converts_v3_location_with_general_index() { + new_test_ext().execute_with(|| { + let asset_id: u32 = 42; + let old_location = mock_old_location_with_index(0, 999); + + // Insert using the old storage type + old_storage::AssetLocations::::insert(asset_id, old_location); + + // Run migration + MigrateAssetRegistryToXcmV5::::on_runtime_upgrade(); + + // Verify migration + let migrated = AssetLocations::::get(asset_id).expect("should exist"); + assert_eq!(migrated.0.parents, 0); + + // Check interior has GeneralIndex(999) + match &migrated.0.interior { + polkadot_xcm::v5::Junctions::X1(junctions) => { + assert_eq!(junctions.len(), 1); + assert_eq!(junctions[0], polkadot_xcm::v5::Junction::GeneralIndex(999)); + } + _ => panic!("Expected X1 junction"), + } + + // Verify reverse mapping + assert_eq!(LocationAssets::::get(&migrated), Some(asset_id)); + }); + } + + #[test] + fn migration_converts_v3_parachain_location() { + new_test_ext().execute_with(|| { + let asset_id: u32 = 100; + let old_location = mock_old_location_parachain(2000); + + // Insert using the old storage type + old_storage::AssetLocations::::insert(asset_id, old_location); + + // Run migration + MigrateAssetRegistryToXcmV5::::on_runtime_upgrade(); + + // Verify migration + let migrated = AssetLocations::::get(asset_id).expect("should exist"); + assert_eq!(migrated.0.parents, 1); + + match &migrated.0.interior { + polkadot_xcm::v5::Junctions::X1(junctions) => { + assert_eq!(junctions[0], polkadot_xcm::v5::Junction::Parachain(2000)); + } + _ => panic!("Expected X1 junction with Parachain"), + } + + assert_eq!(LocationAssets::::get(&migrated), Some(asset_id)); + }); + } + + #[test] + fn migration_handles_multiple_assets() { + new_test_ext().execute_with(|| { + // Insert multiple old locations using the old storage type + let locations = vec![ + (1u32, mock_old_location_parent()), + (2u32, mock_old_location_with_index(0, 100)), + (3u32, mock_old_location_parachain(1000)), + ]; + + for (asset_id, old_loc) in &locations { + old_storage::AssetLocations::::insert(*asset_id, old_loc.clone()); + } + + // Run migration + MigrateAssetRegistryToXcmV5::::on_runtime_upgrade(); + + // Verify all assets were migrated + for (asset_id, _) in &locations { + assert!( + AssetLocations::::get(*asset_id).is_some(), + "Asset {} should be migrated", + asset_id + ); + let loc = AssetLocations::::get(*asset_id).unwrap(); + assert_eq!( + LocationAssets::::get(&loc), + Some(*asset_id), + "Reverse mapping for asset {} should exist", + asset_id + ); + } + }); + } + + #[test] + fn migration_handles_empty_storage() { + new_test_ext().execute_with(|| { + // No assets in storage + + // Run migration - should not panic + let weight = MigrateAssetRegistryToXcmV5::::on_runtime_upgrade(); + + // Weight should be zero (no reads/writes) + assert_eq!(weight.ref_time(), 0); + }); + } +} diff --git a/runtime/basilisk/src/migrations/mod.rs b/runtime/basilisk/src/migrations/mod.rs new file mode 100644 index 00000000000..2b3ae80787f --- /dev/null +++ b/runtime/basilisk/src/migrations/mod.rs @@ -0,0 +1,29 @@ +// This file is part of Basilisk-node. + +// Copyright (C) 2020-2025 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::migrations::asset_registry::MigrateAssetRegistryToXcmV5; +use crate::Runtime; + +mod asset_registry; + +// New migrations which need to be cleaned up after Runtime upgrade +pub type UnreleasedSingleBlockMigrations = MigrateAssetRegistryToXcmV5; + +// These migrations can run on every runtime upgrade +pub type PermanentSingleBlockMigrations = pallet_xcm::migration::MigrateToLatestXcmVersion; + +pub type Migrations = (PermanentSingleBlockMigrations, UnreleasedSingleBlockMigrations); diff --git a/runtime/basilisk/src/system.rs b/runtime/basilisk/src/system.rs index 20aef3b9d67..86c355ffd6f 100644 --- a/runtime/basilisk/src/system.rs +++ b/runtime/basilisk/src/system.rs @@ -26,7 +26,8 @@ use primitives::constants::{ time::{HOURS, SLOT_DURATION}, }; -use codec::{Decode, Encode, MaxEncodedLen}; +use basilisk_adapters::RelayChainBlockNumberProvider; +use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen}; use frame_support::{ dispatch::DispatchClass, pallet_prelude::Get, @@ -43,9 +44,8 @@ use frame_support::{ PalletId, }; use frame_system::EnsureRoot; -use hydradx_adapters::RelayChainBlockNumberProvider; -use hydradx_traits::evm::{EvmAddress, InspectEvmAccounts}; -use primitives::constants::time::DAYS; +use hydradx_traits::evm::InspectEvmAccounts; +use primitives::{constants::time::DAYS, EvmAddress}; use scale_info::TypeInfo; use sp_core::ConstU64; @@ -183,6 +183,7 @@ impl frame_system::Config for Runtime { type PreInherents = (); type PostInherents = (); type PostTransactions = (); + type ExtensionsWeightInfo = weights::frame_system_extensions::BasiliskWeight; } parameter_types! { @@ -245,11 +246,12 @@ parameter_types! { impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = TransferFees, TreasuryAccount>; + type OnChargeTransaction = TransferFees, TreasuryAccount>; type OperationalFeeMultiplier = (); type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type WeightInfo = weights::pallet_transaction_payment::BasiliskWeight; } pub struct WethAssetId; @@ -308,7 +310,20 @@ impl pallet_transaction_multi_payment::Config for Runtime { } /// The type used to represent the kinds of proxying allowed. -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo)] +#[derive( + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Encode, + Decode, + DecodeWithMemTracking, + RuntimeDebug, + MaxEncodedLen, + TypeInfo, +)] pub enum ProxyType { Any, CancelProxy, @@ -374,7 +389,7 @@ impl pallet_preimage::Config for Runtime { } parameter_types! { - pub MaximumSchedulerWeight: Weight = Perbill::from_percent(10) * BlockWeights::get().max_block; + pub MaximumSchedulerWeight: Weight = NORMAL_DISPATCH_RATIO * BlockWeights::get().max_block; pub const MaxScheduledPerBlock: u32 = 50; } @@ -389,6 +404,7 @@ impl pallet_scheduler::Config for Runtime { type MaxScheduledPerBlock = MaxScheduledPerBlock; type WeightInfo = weights::pallet_scheduler::BasiliskWeight; type Preimages = Preimage; + type BlockNumberProvider = System; } parameter_types! { @@ -413,6 +429,7 @@ impl pallet_proxy::Config for Runtime { type CallHasher = BlakeTwo256; type AnnouncementDepositBase = AnnouncementDepositBase; type AnnouncementDepositFactor = AnnouncementDepositFactor; + type BlockNumberProvider = System; } parameter_types! { @@ -432,6 +449,7 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type DmpQueue = frame_support::traits::EnqueueWithOrigin; type ConsensusHook = ConsensusHook; type WeightInfo = weights::cumulus_pallet_parachain_system::BasiliskWeight; + type SelectCore = cumulus_pallet_parachain_system::DefaultCoreSelector; } pub type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook< @@ -457,13 +475,13 @@ pub struct ManageExecutionTypeForUnifiedEvent; impl pallet_utility::BatchHook for ManageExecutionTypeForUnifiedEvent { fn on_batch_start() -> DispatchResult { - Broadcast::add_to_context(pallet_broadcast::types::ExecutionType::Batch); + let _ = Broadcast::add_to_context(pallet_broadcast::types::ExecutionType::Batch); Ok(()) } fn on_batch_end() -> DispatchResult { - Broadcast::remove_from_context(); + let _ = Broadcast::remove_from_context(); Ok(()) } @@ -528,6 +546,7 @@ impl pallet_session::Config for Runtime { type SessionHandler = ::KeyTypeIdProviders; type Keys = opaque::SessionKeys; type WeightInfo = (); + type DisablingStrategy = (); } impl staging_parachain_info::Config for Runtime {} @@ -564,6 +583,7 @@ impl pallet_collator_rewards::Config for Runtime { type ExcludedCollators = ExcludedCollators; type SessionManager = RotatingCollatorManager; type MaxCandidates = MaxInvulnerables; + type RewardsBag = TreasuryAccount; } pub struct RotatingCollatorManager; @@ -600,6 +620,7 @@ parameter_types! { pub const PendingUserNameExpiration: u32 = 7 * DAYS; pub const MaxSuffixLength: u32 = 7; pub const MaxUsernameLength: u32 = 32; + pub const UsernameDeposit: Balance = 5 * DOLLARS; } impl pallet_identity::Config for Runtime { @@ -621,6 +642,8 @@ impl pallet_identity::Config for Runtime { type MaxSuffixLength = MaxSuffixLength; type MaxUsernameLength = MaxUsernameLength; type WeightInfo = weights::pallet_identity::BasiliskWeight; + type UsernameDeposit = UsernameDeposit; + type UsernameGracePeriod = ConstU32<{ 30 * DAYS }>; } parameter_types! { @@ -637,6 +660,7 @@ impl pallet_multisig::Config for Runtime { type DepositFactor = DepositFactor; type MaxSignatories = MaxSignatories; type WeightInfo = weights::pallet_multisig::BasiliskWeight; + type BlockNumberProvider = System; } pub struct TechCommAccounts; diff --git a/runtime/basilisk/src/tests.rs b/runtime/basilisk/src/tests.rs index 98d5d63b591..b1c40dff9c1 100644 --- a/runtime/basilisk/src/tests.rs +++ b/runtime/basilisk/src/tests.rs @@ -64,7 +64,7 @@ fn transfer_cost() { println!( "len = {:?} // weight = {:?} // base fee = {:?} // len fee = {:?} // adjusted weight_fee = {:?} // full transfer fee = {:?}\n", len, - info.weight, + info.call_weight, fee_raw.inclusion_fee.clone().unwrap().base_fee, fee_raw.inclusion_fee.clone().unwrap().len_fee, fee_raw.inclusion_fee.unwrap().adjusted_weight_fee, @@ -133,3 +133,26 @@ fn max_multiplier() { } println!("multiplier = {multiplier:?}"); } + +#[test] +fn metadata_api_implemented() { + use codec::Decode; + use frame_metadata::{RuntimeMetadata, RuntimeMetadataPrefixed}; + use std::ops::Deref; + + sp_io::TestExternalities::new_empty().execute_with(|| { + let version = 15; + let opaque_meta = Runtime::metadata_at_version(version).expect("V15 should exist"); + let prefixed_meta_bytes = opaque_meta.deref(); + assert_eq!( + prefixed_meta_bytes, + Runtime::metadata_at_version(version).unwrap().deref() + ); + let prefixed_meta = RuntimeMetadataPrefixed::decode(&mut &prefixed_meta_bytes[..]).unwrap(); + + let RuntimeMetadata::V15(metadata) = prefixed_meta.1 else { + panic!("Expected metadata V15"); + }; + assert!(!metadata.apis.is_empty()); + }); +} diff --git a/runtime/basilisk/src/weights/cumulus_pallet_parachain_system.rs b/runtime/basilisk/src/weights/cumulus_pallet_parachain_system.rs index 740f79ebbe8..151ae912745 100644 --- a/runtime/basilisk/src/weights/cumulus_pallet_parachain_system.rs +++ b/runtime/basilisk/src/weights/cumulus_pallet_parachain_system.rs @@ -18,30 +18,25 @@ //! Autogenerated weights for `cumulus_pallet_parachain_system` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: // ./target/release/basilisk // benchmark // pallet +// --chain=dev +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// cumulus-pallet-parachain-system -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/cumulus_pallet_parachain_system.rs +// --pallet=cumulus_pallet_parachain_system +// --output=runtime/basilisk/src/weights/cumulus_pallet_parachain_system.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -72,10 +67,10 @@ impl cumulus_pallet_parachain_system::WeightInfo for Ba // Proof Size summary in bytes: // Measured: `189` // Estimated: `3517` - // Minimum execution time: 5_088_000 picoseconds. - Weight::from_parts(5_267_000, 3517) - // Standard Error: 16_199 - .saturating_add(Weight::from_parts(348_138_083, 0).saturating_mul(n.into())) + // Minimum execution time: 7_297_000 picoseconds. + Weight::from_parts(9_529_345_212, 3517) + // Standard Error: 3_419_087 + .saturating_add(Weight::from_parts(367_100_046, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) diff --git a/runtime/basilisk/src/weights/cumulus_pallet_xcmp_queue.rs b/runtime/basilisk/src/weights/cumulus_pallet_xcmp_queue.rs index 6744aaea55b..a4e047ca607 100644 --- a/runtime/basilisk/src/weights/cumulus_pallet_xcmp_queue.rs +++ b/runtime/basilisk/src/weights/cumulus_pallet_xcmp_queue.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `cumulus_pallet_xcmp_queue` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// cumulus-pallet-xcmp-queue -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/cumulus_pallet_xcmp_queue.rs +// --pallet=cumulus_pallet_xcmp_queue +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -63,8 +57,8 @@ impl cumulus_pallet_xcmp_queue::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `76` // Estimated: `1497` - // Minimum execution time: 8_835_000 picoseconds. - Weight::from_parts(9_090_000, 1497) + // Minimum execution time: 8_079_000 picoseconds. + Weight::from_parts(8_281_000, 1497) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -78,12 +72,34 @@ impl cumulus_pallet_xcmp_queue::WeightInfo for Basilisk /// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`) /// Storage: `MessageQueue::Pages` (r:0 w:1) /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(134193), added: 136668, mode: `MaxEncodedLen`) - fn enqueue_xcmp_message() -> Weight { + /// The range of component `n` is `[1, 134139]`. + fn enqueue_n_bytes_xcmp_message(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `156` // Estimated: `5487` - // Minimum execution time: 19_710_000 picoseconds. - Weight::from_parts(20_123_000, 5487) + // Minimum execution time: 19_684_000 picoseconds. + Weight::from_parts(19_153_939, 5487) + // Standard Error: 4 + .saturating_add(Weight::from_parts(921, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `XcmpQueue::QueueConfig` (r:1 w:0) + /// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) + /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::InboundXcmpSuspended` (r:1 w:0) + /// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::Pages` (r:0 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(134193), added: 136668, mode: `MaxEncodedLen`) + fn enqueue_2_empty_xcmp_messages() -> Weight { + // Proof Size summary in bytes: + // Measured: `156` + // Estimated: `5487` + // Minimum execution time: 29_904_000 picoseconds. + Weight::from_parts(30_414_000, 5487) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -93,8 +109,8 @@ impl cumulus_pallet_xcmp_queue::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `76` // Estimated: `2767` - // Minimum execution time: 5_607_000 picoseconds. - Weight::from_parts(5_794_000, 2767) + // Minimum execution time: 4_810_000 picoseconds. + Weight::from_parts(5_080_000, 2767) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -104,8 +120,8 @@ impl cumulus_pallet_xcmp_queue::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `111` // Estimated: `2767` - // Minimum execution time: 6_713_000 picoseconds. - Weight::from_parts(6_967_000, 2767) + // Minimum execution time: 6_151_000 picoseconds. + Weight::from_parts(6_438_000, 2767) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -113,8 +129,8 @@ impl cumulus_pallet_xcmp_queue::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 10_228_000 picoseconds. - Weight::from_parts(10_350_000, 0) + // Minimum execution time: 7_274_000 picoseconds. + Weight::from_parts(7_375_000, 0) } /// Storage: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6b345d8e88afa015075c945637c07e8f20` (r:1 w:1) /// Proof: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6b345d8e88afa015075c945637c07e8f20` (r:1 w:1) @@ -134,8 +150,8 @@ impl cumulus_pallet_xcmp_queue::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `134393` // Estimated: `137858` - // Minimum execution time: 222_602_000 picoseconds. - Weight::from_parts(224_504_000, 137858) + // Minimum execution time: 240_673_000 picoseconds. + Weight::from_parts(241_350_000, 137858) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -157,8 +173,8 @@ impl cumulus_pallet_xcmp_queue::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `65790` // Estimated: `69255` - // Minimum execution time: 130_794_000 picoseconds. - Weight::from_parts(131_605_000, 69255) + // Minimum execution time: 131_249_000 picoseconds. + Weight::from_parts(132_018_000, 69255) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } diff --git a/runtime/basilisk/src/weights/frame_system.rs b/runtime/basilisk/src/weights/frame_system.rs index e19a0015b35..f522eb28839 100644 --- a/runtime/basilisk/src/weights/frame_system.rs +++ b/runtime/basilisk/src/weights/frame_system.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `frame_system` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// frame-system -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/frame_system.rs +// --pallet=frame_system +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -62,20 +56,20 @@ impl frame_system::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_639_000 picoseconds. - Weight::from_parts(3_744_000, 0) - // Standard Error: 0 - .saturating_add(Weight::from_parts(414, 0).saturating_mul(b.into())) + // Minimum execution time: 3_693_000 picoseconds. + Weight::from_parts(12_860_379, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(457, 0).saturating_mul(b.into())) } /// The range of component `b` is `[0, 3932160]`. fn remark_with_event(b: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_778_000 picoseconds. - Weight::from_parts(8_893_000, 0) - // Standard Error: 0 - .saturating_add(Weight::from_parts(1_447, 0).saturating_mul(b.into())) + // Minimum execution time: 8_585_000 picoseconds. + Weight::from_parts(8_710_000, 0) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_560, 0).saturating_mul(b.into())) } /// Storage: `System::Digest` (r:1 w:1) /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -85,8 +79,8 @@ impl frame_system::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 6_291_000 picoseconds. - Weight::from_parts(6_485_000, 1485) + // Minimum execution time: 6_117_000 picoseconds. + Weight::from_parts(6_313_000, 1485) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -106,8 +100,8 @@ impl frame_system::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `231` // Estimated: `1716` - // Minimum execution time: 115_058_565_000 picoseconds. - Weight::from_parts(119_039_683_000, 1716) + // Minimum execution time: 118_912_460_000 picoseconds. + Weight::from_parts(120_959_959_000, 1716) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -118,10 +112,10 @@ impl frame_system::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_769_000 picoseconds. - Weight::from_parts(3_806_000, 0) - // Standard Error: 2_137 - .saturating_add(Weight::from_parts(769_298, 0).saturating_mul(i.into())) + // Minimum execution time: 3_486_000 picoseconds. + Weight::from_parts(3_552_000, 0) + // Standard Error: 2_391 + .saturating_add(Weight::from_parts(811_038, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -131,10 +125,10 @@ impl frame_system::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_818_000 picoseconds. - Weight::from_parts(3_896_000, 0) - // Standard Error: 938 - .saturating_add(Weight::from_parts(564_816, 0).saturating_mul(i.into())) + // Minimum execution time: 3_628_000 picoseconds. + Weight::from_parts(3_682_000, 0) + // Standard Error: 847 + .saturating_add(Weight::from_parts(601_732, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -144,10 +138,10 @@ impl frame_system::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `131 + p * (69 ±0)` // Estimated: `127 + p * (70 ±0)` - // Minimum execution time: 6_586_000 picoseconds. - Weight::from_parts(6_738_000, 127) - // Standard Error: 847 - .saturating_add(Weight::from_parts(1_155_733, 0).saturating_mul(p.into())) + // Minimum execution time: 6_936_000 picoseconds. + Weight::from_parts(7_069_000, 127) + // Standard Error: 927 + .saturating_add(Weight::from_parts(1_175_725, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) .saturating_add(Weight::from_parts(0, 70).saturating_mul(p.into())) @@ -158,8 +152,8 @@ impl frame_system::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 10_991_000 picoseconds. - Weight::from_parts(11_310_000, 0) + // Minimum execution time: 10_728_000 picoseconds. + Weight::from_parts(11_015_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `System::AuthorizedUpgrade` (r:1 w:1) @@ -180,8 +174,8 @@ impl frame_system::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `253` // Estimated: `1738` - // Minimum execution time: 117_256_984_000 picoseconds. - Weight::from_parts(119_903_032_000, 1738) + // Minimum execution time: 120_456_997_000 picoseconds. + Weight::from_parts(122_490_840_000, 1738) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } diff --git a/runtime/basilisk/src/weights/frame_system_extensions.rs b/runtime/basilisk/src/weights/frame_system_extensions.rs new file mode 100644 index 00000000000..2ca55b64cd6 --- /dev/null +++ b/runtime/basilisk/src/weights/frame_system_extensions.rs @@ -0,0 +1,136 @@ +// This file is part of Basilisk. + +// Copyright (C) 2020-2023 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +//! Autogenerated weights for `frame_system_extensions` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` + +// Executed Command: +// ./target/release/basilisk +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --wasm-execution=compiled +// --heap-pages=4096 +// --template=scripts/pallet-weight-template.hbs +// --pallet=frame_system_extensions +// --output=weights.rs +// --extrinsic=* + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; +use frame_system::ExtensionsWeightInfo; + +/// Weights for `frame_system_extensions`. +pub struct WeightInfo(PhantomData); + +/// Weights for `frame_system_extensions` using the Basilisk node and recommended hardware. +pub struct BasiliskWeight(PhantomData); +impl ExtensionsWeightInfo for BasiliskWeight { + fn check_genesis() -> Weight { + // Proof Size summary in bytes: + // Measured: `54` + // Estimated: `0` + // Minimum execution time: 11_014_000 picoseconds. + Weight::from_parts(12_060_000, 0) + } + fn check_mortality_mortal_transaction() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `0` + // Minimum execution time: 18_081_000 picoseconds. + Weight::from_parts(18_888_000, 0) + } + fn check_mortality_immortal_transaction() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `0` + // Minimum execution time: 18_076_000 picoseconds. + Weight::from_parts(19_074_000, 0) + } + fn check_non_zero_sender() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_342_000 picoseconds. + Weight::from_parts(1_489_000, 0) + } + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn check_nonce() -> Weight { + // Proof Size summary in bytes: + // Measured: `101` + // Estimated: `3593` + // Minimum execution time: 16_482_000 picoseconds. + Weight::from_parts(17_006_000, 3593) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + fn check_spec_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 988_000 picoseconds. + Weight::from_parts(1_170_000, 0) + } + fn check_tx_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_041_000 picoseconds. + Weight::from_parts(1_169_000, 0) + } + /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) + /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::BlockWeight` (r:1 w:1) + /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) + /// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1) + /// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + fn check_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `24` + // Estimated: `1533` + // Minimum execution time: 15_057_000 picoseconds. + Weight::from_parts(15_775_000, 1533) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1) + /// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `System::BlockWeight` (r:1 w:1) + /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) + fn weight_reclaim() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `1533` + // Minimum execution time: 7_329_000 picoseconds. + Weight::from_parts(7_832_000, 1533) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } +} \ No newline at end of file diff --git a/runtime/basilisk/src/weights/mod.rs b/runtime/basilisk/src/weights/mod.rs index ec969176fc5..be58e56257f 100644 --- a/runtime/basilisk/src/weights/mod.rs +++ b/runtime/basilisk/src/weights/mod.rs @@ -1,6 +1,7 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod frame_system; +pub mod frame_system_extensions; pub mod orml_tokens; pub mod orml_vesting; pub mod pallet_asset_registry; @@ -27,6 +28,7 @@ pub mod pallet_state_trie_migration; pub mod pallet_timestamp; pub mod pallet_transaction_multi_payment; pub mod pallet_transaction_pause; +pub mod pallet_transaction_payment; pub mod pallet_treasury; pub mod pallet_utility; pub mod pallet_whitelist; diff --git a/runtime/basilisk/src/weights/orml_tokens.rs b/runtime/basilisk/src/weights/orml_tokens.rs index be579f887c8..76648af3fc6 100644 --- a/runtime/basilisk/src/weights/orml_tokens.rs +++ b/runtime/basilisk/src/weights/orml_tokens.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `orml_tokens` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// orml-tokens -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/orml_tokens.rs +// --pallet=orml_tokens +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -71,8 +65,8 @@ impl orml_tokens::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `2251` // Estimated: `6156` - // Minimum execution time: 91_432_000 picoseconds. - Weight::from_parts(92_034_000, 6156) + // Minimum execution time: 90_959_000 picoseconds. + Weight::from_parts(97_525_000, 6156) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -90,8 +84,8 @@ impl orml_tokens::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `2251` // Estimated: `6156` - // Minimum execution time: 94_336_000 picoseconds. - Weight::from_parts(95_252_000, 6156) + // Minimum execution time: 90_889_000 picoseconds. + Weight::from_parts(94_244_000, 6156) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -109,8 +103,8 @@ impl orml_tokens::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `2111` // Estimated: `6156` - // Minimum execution time: 76_879_000 picoseconds. - Weight::from_parts(77_533_000, 6156) + // Minimum execution time: 73_711_000 picoseconds. + Weight::from_parts(74_056_000, 6156) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -128,8 +122,8 @@ impl orml_tokens::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `2249` // Estimated: `6196` - // Minimum execution time: 81_506_000 picoseconds. - Weight::from_parts(82_464_000, 6196) + // Minimum execution time: 79_082_000 picoseconds. + Weight::from_parts(80_489_000, 6196) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -149,8 +143,8 @@ impl orml_tokens::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `2043` // Estimated: `3593` - // Minimum execution time: 69_036_000 picoseconds. - Weight::from_parts(69_824_000, 3593) + // Minimum execution time: 67_876_000 picoseconds. + Weight::from_parts(69_786_000, 3593) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } diff --git a/runtime/basilisk/src/weights/orml_vesting.rs b/runtime/basilisk/src/weights/orml_vesting.rs index 961eb4536a5..171b7c3e62c 100644 --- a/runtime/basilisk/src/weights/orml_vesting.rs +++ b/runtime/basilisk/src/weights/orml_vesting.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `orml_vesting` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// orml-vesting -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/orml_vesting.rs +// --pallet=orml_vesting +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -69,8 +63,8 @@ impl orml_vesting::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `1664` // Estimated: `6196` - // Minimum execution time: 105_234_000 picoseconds. - Weight::from_parts(106_346_000, 6196) + // Minimum execution time: 108_069_000 picoseconds. + Weight::from_parts(109_175_000, 6196) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -85,10 +79,10 @@ impl orml_vesting::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `1784 + i * (18 ±0)` // Estimated: `4764` - // Minimum execution time: 63_291_000 picoseconds. - Weight::from_parts(64_981_802, 4764) - // Standard Error: 5_001 - .saturating_add(Weight::from_parts(136_473, 0).saturating_mul(i.into())) + // Minimum execution time: 62_852_000 picoseconds. + Weight::from_parts(65_017_563, 4764) + // Standard Error: 34_017 + .saturating_add(Weight::from_parts(75_817, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -105,10 +99,10 @@ impl orml_vesting::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `1502` // Estimated: `4764` - // Minimum execution time: 54_785_000 picoseconds. - Weight::from_parts(55_977_167, 4764) - // Standard Error: 2_239 - .saturating_add(Weight::from_parts(109_771, 0).saturating_mul(i.into())) + // Minimum execution time: 54_662_000 picoseconds. + Weight::from_parts(54_817_326, 4764) + // Standard Error: 63_699 + .saturating_add(Weight::from_parts(319_423, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } diff --git a/runtime/basilisk/src/weights/pallet_asset_registry.rs b/runtime/basilisk/src/weights/pallet_asset_registry.rs index 5ec250b2fbf..8626cde134c 100644 --- a/runtime/basilisk/src/weights/pallet_asset_registry.rs +++ b/runtime/basilisk/src/weights/pallet_asset_registry.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_asset_registry` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-asset-registry -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_asset_registry.rs +// --pallet=pallet_asset_registry +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -73,8 +67,8 @@ impl pallet_asset_registry::WeightInfo for BasiliskWeig // Proof Size summary in bytes: // Measured: `338` // Estimated: `4087` - // Minimum execution time: 42_033_000 picoseconds. - Weight::from_parts(42_375_000, 4087) + // Minimum execution time: 38_479_000 picoseconds. + Weight::from_parts(38_961_000, 4087) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -86,8 +80,8 @@ impl pallet_asset_registry::WeightInfo for BasiliskWeig // Proof Size summary in bytes: // Measured: `405` // Estimated: `3552` - // Minimum execution time: 29_416_000 picoseconds. - Weight::from_parts(29_727_000, 3552) + // Minimum execution time: 27_946_000 picoseconds. + Weight::from_parts(28_446_000, 3552) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -99,8 +93,8 @@ impl pallet_asset_registry::WeightInfo for BasiliskWeig // Proof Size summary in bytes: // Measured: `333` // Estimated: `3552` - // Minimum execution time: 21_739_000 picoseconds. - Weight::from_parts(22_133_000, 3552) + // Minimum execution time: 20_275_000 picoseconds. + Weight::from_parts(20_555_000, 3552) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -114,8 +108,8 @@ impl pallet_asset_registry::WeightInfo for BasiliskWeig // Proof Size summary in bytes: // Measured: `307` // Estimated: `4087` - // Minimum execution time: 26_543_000 picoseconds. - Weight::from_parts(26_957_000, 4087) + // Minimum execution time: 24_717_000 picoseconds. + Weight::from_parts(24_943_000, 4087) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } diff --git a/runtime/basilisk/src/weights/pallet_balances.rs b/runtime/basilisk/src/weights/pallet_balances.rs index da6ff273221..bb05f9ac1ae 100644 --- a/runtime/basilisk/src/weights/pallet_balances.rs +++ b/runtime/basilisk/src/weights/pallet_balances.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_balances` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-balances -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_balances.rs +// --pallet=pallet_balances +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -63,8 +57,8 @@ impl pallet_balances::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 72_100_000 picoseconds. - Weight::from_parts(73_239_000, 3593) + // Minimum execution time: 71_829_000 picoseconds. + Weight::from_parts(72_471_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -74,8 +68,8 @@ impl pallet_balances::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 47_915_000 picoseconds. - Weight::from_parts(48_450_000, 3593) + // Minimum execution time: 47_819_000 picoseconds. + Weight::from_parts(48_381_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -83,10 +77,10 @@ impl pallet_balances::WeightInfo for BasiliskWeight /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn force_set_balance_creating() -> Weight { // Proof Size summary in bytes: - // Measured: `174` + // Measured: `39` // Estimated: `3593` - // Minimum execution time: 21_260_000 picoseconds. - Weight::from_parts(21_683_000, 3593) + // Minimum execution time: 28_084_000 picoseconds. + Weight::from_parts(28_338_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -96,8 +90,8 @@ impl pallet_balances::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 30_250_000 picoseconds. - Weight::from_parts(30_853_000, 3593) + // Minimum execution time: 29_148_000 picoseconds. + Weight::from_parts(29_482_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -107,8 +101,8 @@ impl pallet_balances::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 76_701_000 picoseconds. - Weight::from_parts(77_143_000, 6196) + // Minimum execution time: 74_643_000 picoseconds. + Weight::from_parts(75_128_000, 6196) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -118,8 +112,8 @@ impl pallet_balances::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 59_235_000 picoseconds. - Weight::from_parts(59_846_000, 3593) + // Minimum execution time: 58_662_000 picoseconds. + Weight::from_parts(59_099_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -129,8 +123,8 @@ impl pallet_balances::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 24_625_000 picoseconds. - Weight::from_parts(25_114_000, 3593) + // Minimum execution time: 24_102_000 picoseconds. + Weight::from_parts(24_389_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -141,10 +135,10 @@ impl pallet_balances::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `0 + u * (135 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 23_758_000 picoseconds. - Weight::from_parts(23_871_000, 990) - // Standard Error: 11_161 - .saturating_add(Weight::from_parts(16_405_587, 0).saturating_mul(u.into())) + // Minimum execution time: 22_869_000 picoseconds. + Weight::from_parts(23_112_000, 990) + // Standard Error: 5_118 + .saturating_add(Weight::from_parts(15_614_784, 0).saturating_mul(u.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -155,22 +149,22 @@ impl pallet_balances::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `0` // Estimated: `1501` - // Minimum execution time: 9_846_000 picoseconds. - Weight::from_parts(10_011_000, 1501) + // Minimum execution time: 9_591_000 picoseconds. + Weight::from_parts(9_754_000, 1501) .saturating_add(T::DbWeight::get().reads(1_u64)) } fn burn_allow_death() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 51_188_000 picoseconds. - Weight::from_parts(51_733_000, 0) + // Minimum execution time: 49_921_000 picoseconds. + Weight::from_parts(50_568_000, 0) } fn burn_keep_alive() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 26_728_000 picoseconds. - Weight::from_parts(27_075_000, 0) + // Minimum execution time: 26_522_000 picoseconds. + Weight::from_parts(26_892_000, 0) } } \ No newline at end of file diff --git a/runtime/basilisk/src/weights/pallet_collator_selection.rs b/runtime/basilisk/src/weights/pallet_collator_selection.rs index c89b6244d69..5a2d97b247c 100644 --- a/runtime/basilisk/src/weights/pallet_collator_selection.rs +++ b/runtime/basilisk/src/weights/pallet_collator_selection.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_collator_selection` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-collator-selection -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_collator_selection.rs +// --pallet=pallet_collator_selection +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -66,10 +60,10 @@ impl pallet_collator_selection::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `208 + b * (79 ±0)` // Estimated: `1196 + b * (2554 ±0)` - // Minimum execution time: 19_207_000 picoseconds. - Weight::from_parts(18_050_727, 1196) - // Standard Error: 5_668 - .saturating_add(Weight::from_parts(4_188_987, 0).saturating_mul(b.into())) + // Minimum execution time: 18_224_000 picoseconds. + Weight::from_parts(17_118_001, 1196) + // Standard Error: 3_713 + .saturating_add(Weight::from_parts(3_819_395, 0).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(b.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 2554).saturating_mul(b.into())) @@ -88,12 +82,10 @@ impl pallet_collator_selection::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `863 + b * (40 ±0) + c * (48 ±0)` // Estimated: `4356 + b * (42 ±0) + c * (46 ±0)` - // Minimum execution time: 51_971_000 picoseconds. - Weight::from_parts(51_058_446, 4356) - // Standard Error: 3_580 - .saturating_add(Weight::from_parts(198_137, 0).saturating_mul(b.into())) - // Standard Error: 9_430 - .saturating_add(Weight::from_parts(34_357, 0).saturating_mul(c.into())) + // Minimum execution time: 50_628_000 picoseconds. + Weight::from_parts(50_610_161, 4356) + // Standard Error: 2_223 + .saturating_add(Weight::from_parts(143_237, 0).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 42).saturating_mul(b.into())) @@ -108,10 +100,10 @@ impl pallet_collator_selection::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `186 + b * (32 ±0)` // Estimated: `3086` - // Minimum execution time: 18_544_000 picoseconds. - Weight::from_parts(18_933_432, 3086) - // Standard Error: 487 - .saturating_add(Weight::from_parts(43_777, 0).saturating_mul(b.into())) + // Minimum execution time: 17_476_000 picoseconds. + Weight::from_parts(17_948_745, 3086) + // Standard Error: 479 + .saturating_add(Weight::from_parts(37_252, 0).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -121,8 +113,8 @@ impl pallet_collator_selection::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_803_000 picoseconds. - Weight::from_parts(8_041_000, 0) + // Minimum execution time: 8_027_000 picoseconds. + Weight::from_parts(8_196_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `CollatorSelection::CandidacyBond` (r:1 w:1) @@ -139,12 +131,12 @@ impl pallet_collator_selection::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `0 + c * (174 ±0) + k * (127 ±0)` // Estimated: `3593 + c * (848 ±30) + k * (848 ±30)` - // Minimum execution time: 16_353_000 picoseconds. - Weight::from_parts(16_557_000, 3593) - // Standard Error: 188_711 - .saturating_add(Weight::from_parts(6_388_141, 0).saturating_mul(c.into())) - // Standard Error: 188_711 - .saturating_add(Weight::from_parts(6_278_607, 0).saturating_mul(k.into())) + // Minimum execution time: 15_439_000 picoseconds. + Weight::from_parts(15_763_000, 3593) + // Standard Error: 187_308 + .saturating_add(Weight::from_parts(6_306_446, 0).saturating_mul(c.into())) + // Standard Error: 187_308 + .saturating_add(Weight::from_parts(6_289_175, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into()))) @@ -161,10 +153,10 @@ impl pallet_collator_selection::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `425 + c * (45 ±0)` // Estimated: `2446` - // Minimum execution time: 36_657_000 picoseconds. - Weight::from_parts(37_576_229, 2446) - // Standard Error: 5_286 - .saturating_add(Weight::from_parts(50_158, 0).saturating_mul(c.into())) + // Minimum execution time: 35_463_000 picoseconds. + Weight::from_parts(36_567_856, 2446) + // Standard Error: 5_263 + .saturating_add(Weight::from_parts(39_467, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -183,10 +175,10 @@ impl pallet_collator_selection::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `617 + c * (61 ±0)` // Estimated: `4082 + c * (61 ±0)` - // Minimum execution time: 47_128_000 picoseconds. - Weight::from_parts(47_094_471, 4082) - // Standard Error: 8_311 - .saturating_add(Weight::from_parts(414_346, 0).saturating_mul(c.into())) + // Minimum execution time: 46_577_000 picoseconds. + Weight::from_parts(46_932_310, 4082) + // Standard Error: 3_074 + .saturating_add(Weight::from_parts(294_386, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 61).saturating_mul(c.into())) @@ -208,10 +200,10 @@ impl pallet_collator_selection::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `717 + c * (61 ±0)` // Estimated: `4182 + c * (61 ±0)` - // Minimum execution time: 71_362_000 picoseconds. - Weight::from_parts(72_447_539, 4182) - // Standard Error: 2_684 - .saturating_add(Weight::from_parts(135_853, 0).saturating_mul(c.into())) + // Minimum execution time: 68_900_000 picoseconds. + Weight::from_parts(69_619_846, 4182) + // Standard Error: 2_434 + .saturating_add(Weight::from_parts(111_878, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 61).saturating_mul(c.into())) @@ -227,10 +219,10 @@ impl pallet_collator_selection::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `408 + c * (48 ±0)` // Estimated: `3086` - // Minimum execution time: 39_940_000 picoseconds. - Weight::from_parts(40_323_772, 3086) - // Standard Error: 1_532 - .saturating_add(Weight::from_parts(116_405, 0).saturating_mul(c.into())) + // Minimum execution time: 38_491_000 picoseconds. + Weight::from_parts(39_118_423, 3086) + // Standard Error: 1_570 + .saturating_add(Weight::from_parts(98_427, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -244,8 +236,8 @@ impl pallet_collator_selection::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `154` // Estimated: `6196` - // Minimum execution time: 54_160_000 picoseconds. - Weight::from_parts(54_710_000, 6196) + // Minimum execution time: 53_911_000 picoseconds. + Weight::from_parts(54_502_000, 6196) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -267,10 +259,10 @@ impl pallet_collator_selection::WeightInfo for Basilisk // Proof Size summary in bytes: // Measured: `407 + c * (98 ±0) + r * (127 ±0)` // Estimated: `2188621418662104 + c * (2519 ±0) + r * (2571 ±5)` - // Minimum execution time: 29_051_000 picoseconds. - Weight::from_parts(29_342_000, 2188621418662104) - // Standard Error: 319_767 - .saturating_add(Weight::from_parts(15_098_448, 0).saturating_mul(c.into())) + // Minimum execution time: 28_430_000 picoseconds. + Weight::from_parts(28_660_000, 2188621418662104) + // Standard Error: 322_087 + .saturating_add(Weight::from_parts(15_055_977, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) diff --git a/runtime/basilisk/src/weights/pallet_collective.rs b/runtime/basilisk/src/weights/pallet_collective.rs index cdf1753b792..a8f7b4748da 100644 --- a/runtime/basilisk/src/weights/pallet_collective.rs +++ b/runtime/basilisk/src/weights/pallet_collective.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_collective` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-collective -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_collective.rs +// --pallet=pallet_collective +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -71,13 +65,13 @@ impl pallet_collective::WeightInfo for BasiliskWeight Weight { // Proof Size summary in bytes: // Measured: `0 + m * (672 ±0) + p * (310 ±0)` - // Estimated: `4294 + m * (398 ±4) + p * (2602 ±2)` - // Minimum execution time: 13_094_000 picoseconds. - Weight::from_parts(13_293_000, 4294) - // Standard Error: 99_043 - .saturating_add(Weight::from_parts(3_037_915, 0).saturating_mul(m.into())) - // Standard Error: 50_085 - .saturating_add(Weight::from_parts(4_698_580, 0).saturating_mul(p.into())) + // Estimated: `4294 + m * (398 ±6) + p * (2602 ±3)` + // Minimum execution time: 12_596_000 picoseconds. + Weight::from_parts(12_810_000, 4294) + // Standard Error: 91_337 + .saturating_add(Weight::from_parts(2_951_848, 0).saturating_mul(m.into())) + // Standard Error: 46_188 + .saturating_add(Weight::from_parts(4_378_286, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -93,12 +87,12 @@ impl pallet_collective::WeightInfo for BasiliskWeight pallet_collective::WeightInfo for BasiliskWeight pallet_collective::WeightInfo for BasiliskWeight pallet_collective::WeightInfo for BasiliskWeight pallet_collective::WeightInfo for BasiliskWeight pallet_collective::WeightInfo for BasiliskWeight pallet_collective::WeightInfo for BasiliskWeight pallet_collective::WeightInfo for BasiliskWeight pallet_collective::WeightInfo for BasiliskWeight Weight { + // Proof Size summary in bytes: + // Measured: `1280 + p * (55 ±0)` + // Estimated: `4747 + d * (5 ±1) + p * (55 ±0)` + // Minimum execution time: 26_390_000 picoseconds. + Weight::from_parts(27_893_457, 4747) + // Standard Error: 2_424 + .saturating_add(Weight::from_parts(315_719, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(Weight::from_parts(0, 5).saturating_mul(d.into())) + .saturating_add(Weight::from_parts(0, 55).saturating_mul(p.into())) + } + /// Storage: `TechnicalCommittee::ProposalOf` (r:1 w:0) + /// Proof: `TechnicalCommittee::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalCommittee::CostOf` (r:1 w:0) + /// Proof: `TechnicalCommittee::CostOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn release_proposal_cost() -> Weight { + // Proof Size summary in bytes: + // Measured: `713` + // Estimated: `4178` + // Minimum execution time: 16_948_000 picoseconds. + Weight::from_parts(17_418_000, 4178) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } } \ No newline at end of file diff --git a/runtime/basilisk/src/weights/pallet_conviction_voting.rs b/runtime/basilisk/src/weights/pallet_conviction_voting.rs index 7354268c98e..fe5094d9f3a 100644 --- a/runtime/basilisk/src/weights/pallet_conviction_voting.rs +++ b/runtime/basilisk/src/weights/pallet_conviction_voting.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_conviction_voting` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-conviction-voting -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_conviction_voting.rs +// --pallet=pallet_conviction_voting +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -73,8 +67,8 @@ impl pallet_conviction_voting::WeightInfo for BasiliskW // Proof Size summary in bytes: // Measured: `13412` // Estimated: `42428` - // Minimum execution time: 143_032_000 picoseconds. - Weight::from_parts(146_476_000, 42428) + // Minimum execution time: 143_023_000 picoseconds. + Weight::from_parts(147_006_000, 42428) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -96,8 +90,8 @@ impl pallet_conviction_voting::WeightInfo for BasiliskW // Proof Size summary in bytes: // Measured: `14133` // Estimated: `83866` - // Minimum execution time: 183_525_000 picoseconds. - Weight::from_parts(188_675_000, 83866) + // Minimum execution time: 176_785_000 picoseconds. + Weight::from_parts(178_371_000, 83866) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } @@ -113,8 +107,8 @@ impl pallet_conviction_voting::WeightInfo for BasiliskW // Proof Size summary in bytes: // Measured: `13923` // Estimated: `83866` - // Minimum execution time: 152_087_000 picoseconds. - Weight::from_parts(153_037_000, 83866) + // Minimum execution time: 138_947_000 picoseconds. + Weight::from_parts(141_434_000, 83866) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -126,8 +120,8 @@ impl pallet_conviction_voting::WeightInfo for BasiliskW // Proof Size summary in bytes: // Measured: `13047` // Estimated: `30706` - // Minimum execution time: 71_444_000 picoseconds. - Weight::from_parts(73_080_000, 30706) + // Minimum execution time: 64_961_000 picoseconds. + Weight::from_parts(67_499_000, 30706) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -150,10 +144,10 @@ impl pallet_conviction_voting::WeightInfo for BasiliskW // Proof Size summary in bytes: // Measured: `1201 + r * (1000 ±0)` // Estimated: `83866 + r * (3411 ±0)` - // Minimum execution time: 76_208_000 picoseconds. - Weight::from_parts(94_757_759, 83866) - // Standard Error: 115_993 - .saturating_add(Weight::from_parts(33_988_787, 0).saturating_mul(r.into())) + // Minimum execution time: 76_417_000 picoseconds. + Weight::from_parts(96_262_493, 83866) + // Standard Error: 115_611 + .saturating_add(Weight::from_parts(31_606_544, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(5_u64)) @@ -173,10 +167,10 @@ impl pallet_conviction_voting::WeightInfo for BasiliskW // Proof Size summary in bytes: // Measured: `1162 + r * (991 ±0)` // Estimated: `83866 + r * (3411 ±0)` - // Minimum execution time: 45_016_000 picoseconds. - Weight::from_parts(59_898_896, 83866) - // Standard Error: 106_240 - .saturating_add(Weight::from_parts(33_531_102, 0).saturating_mul(r.into())) + // Minimum execution time: 43_687_000 picoseconds. + Weight::from_parts(60_647_129, 83866) + // Standard Error: 102_974 + .saturating_add(Weight::from_parts(31_640_881, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -195,8 +189,8 @@ impl pallet_conviction_voting::WeightInfo for BasiliskW // Proof Size summary in bytes: // Measured: `12065` // Estimated: `30706` - // Minimum execution time: 102_244_000 picoseconds. - Weight::from_parts(104_236_000, 30706) + // Minimum execution time: 101_148_000 picoseconds. + Weight::from_parts(102_766_000, 30706) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } diff --git a/runtime/basilisk/src/weights/pallet_currencies.rs b/runtime/basilisk/src/weights/pallet_currencies.rs index fba2671d176..1869066fbe1 100644 --- a/runtime/basilisk/src/weights/pallet_currencies.rs +++ b/runtime/basilisk/src/weights/pallet_currencies.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_currencies` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-currencies -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_currencies.rs +// --pallet=pallet_currencies +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -71,8 +65,8 @@ impl pallet_currencies::WeightInfo for BasiliskWeight pallet_currencies::WeightInfo for BasiliskWeight pallet_currencies::WeightInfo for BasiliskWeight pallet_currencies::WeightInfo for BasiliskWeight pallet_currencies::WeightInfo for BasiliskWeight(PhantomData); /// Weights for `pallet_duster` using the Basilisk node and recommended hardware. pub struct BasiliskWeight(PhantomData); impl pallet_duster::WeightInfo for BasiliskWeight { - /// Storage: `Duster::AccountBlacklist` (r:1 w:0) - /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountWhitelist` (r:1 w:0) + /// Proof: `Duster::AccountWhitelist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `AssetRegistry::Assets` (r:1 w:0) /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(87), added: 2562, mode: `MaxEncodedLen`) /// Storage: `Tokens::Accounts` (r:2 w:2) /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) - /// Storage: `Duster::DustAccount` (r:1 w:0) - /// Proof: `Duster::DustAccount` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Duster::RewardAccount` (r:1 w:0) - /// Proof: `Duster::RewardAccount` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:0 w:1) /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn dust_account() -> Weight { // Proof Size summary in bytes: - // Measured: `2487` + // Measured: `2350` // Estimated: `6156` - // Minimum execution time: 90_433_000 picoseconds. - Weight::from_parts(92_113_000, 6156) - .saturating_add(T::DbWeight::get().reads(7_u64)) + // Minimum execution time: 142_127_000 picoseconds. + Weight::from_parts(149_234_000, 6156) + .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `Duster::AccountBlacklist` (r:0 w:1) - /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - fn add_nondustable_account() -> Weight { + /// Storage: `Duster::AccountWhitelist` (r:0 w:1) + /// Proof: `Duster::AccountWhitelist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn whitelist_account() -> Weight { // Proof Size summary in bytes: // Measured: `929` // Estimated: `0` - // Minimum execution time: 22_105_000 picoseconds. - Weight::from_parts(22_376_000, 0) + // Minimum execution time: 34_491_000 picoseconds. + Weight::from_parts(36_180_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Duster::AccountBlacklist` (r:1 w:1) - /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - fn remove_nondustable_account() -> Weight { + /// Storage: `Duster::AccountWhitelist` (r:1 w:1) + /// Proof: `Duster::AccountWhitelist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn remove_from_whitelist() -> Weight { // Proof Size summary in bytes: - // Measured: `1283` + // Measured: `1216` // Estimated: `3513` - // Minimum execution time: 28_185_000 picoseconds. - Weight::from_parts(28_800_000, 3513) + // Minimum execution time: 42_047_000 picoseconds. + Weight::from_parts(46_912_000, 3513) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } diff --git a/runtime/basilisk/src/weights/pallet_ema_oracle.rs b/runtime/basilisk/src/weights/pallet_ema_oracle.rs index 0d4521afd91..dc6ceb40656 100644 --- a/runtime/basilisk/src/weights/pallet_ema_oracle.rs +++ b/runtime/basilisk/src/weights/pallet_ema_oracle.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_ema_oracle` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-ema-oracle -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_ema_oracle.rs +// --pallet=pallet_ema_oracle +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -63,8 +57,8 @@ impl pallet_ema_oracle::WeightInfo for BasiliskWeight pallet_ema_oracle::WeightInfo for BasiliskWeight pallet_ema_oracle::WeightInfo for BasiliskWeight pallet_ema_oracle::WeightInfo for BasiliskWeight pallet_ema_oracle::WeightInfo for BasiliskWeight pallet_ema_oracle::WeightInfo for BasiliskWeight pallet_ema_oracle::WeightInfo for BasiliskWeight pallet_identity::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `32 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 14_385_000 picoseconds. - Weight::from_parts(15_136_624, 2626) - // Standard Error: 1_467 - .saturating_add(Weight::from_parts(81_662, 0).saturating_mul(r.into())) + // Minimum execution time: 14_084_000 picoseconds. + Weight::from_parts(14_452_134, 2626) + // Standard Error: 826 + .saturating_add(Weight::from_parts(84_631, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. fn set_identity(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `6978 + r * (5 ±0)` - // Estimated: `11037` - // Minimum execution time: 147_135_000 picoseconds. - Weight::from_parts(148_053_222, 11037) - // Standard Error: 4_154 - .saturating_add(Weight::from_parts(137_403, 0).saturating_mul(r.into())) + // Measured: `6977 + r * (5 ±0)` + // Estimated: `11003` + // Minimum execution time: 145_445_000 picoseconds. + Weight::from_parts(146_817_363, 11003) + // Standard Error: 3_855 + .saturating_add(Weight::from_parts(66_202, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) /// Storage: `Identity::SubsOf` (r:1 w:1) /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) /// Storage: `Identity::SuperOf` (r:100 w:100) @@ -95,11 +89,11 @@ impl pallet_identity::WeightInfo for BasiliskWeight fn set_subs_new(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `101` - // Estimated: `11037 + s * (2589 ±0)` - // Minimum execution time: 14_711_000 picoseconds. - Weight::from_parts(33_104_931, 11037) - // Standard Error: 4_820 - .saturating_add(Weight::from_parts(3_943_207, 0).saturating_mul(s.into())) + // Estimated: `11003 + s * (2589 ±0)` + // Minimum execution time: 18_885_000 picoseconds. + Weight::from_parts(36_899_166, 11003) + // Standard Error: 4_649 + .saturating_add(Weight::from_parts(4_053_876, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(s.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) @@ -107,7 +101,7 @@ impl pallet_identity::WeightInfo for BasiliskWeight .saturating_add(Weight::from_parts(0, 2589).saturating_mul(s.into())) } /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) /// Storage: `Identity::SubsOf` (r:1 w:1) /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) /// Storage: `Identity::SuperOf` (r:0 w:100) @@ -116,11 +110,11 @@ impl pallet_identity::WeightInfo for BasiliskWeight fn set_subs_old(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `194 + p * (32 ±0)` - // Estimated: `11037` - // Minimum execution time: 14_639_000 picoseconds. - Weight::from_parts(32_410_379, 11037) - // Standard Error: 4_187 - .saturating_add(Weight::from_parts(1_487_510, 0).saturating_mul(p.into())) + // Estimated: `11003` + // Minimum execution time: 19_012_000 picoseconds. + Weight::from_parts(35_623_279, 11003) + // Standard Error: 3_875 + .saturating_add(Weight::from_parts(1_568_427, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) @@ -128,21 +122,21 @@ impl pallet_identity::WeightInfo for BasiliskWeight /// Storage: `Identity::SubsOf` (r:1 w:1) /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) /// Storage: `Identity::SuperOf` (r:0 w:100) /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. /// The range of component `s` is `[0, 100]`. fn clear_identity(r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `7070 + r * (5 ±0) + s * (32 ±0)` - // Estimated: `11037` - // Minimum execution time: 70_277_000 picoseconds. - Weight::from_parts(71_079_005, 11037) - // Standard Error: 7_303 - .saturating_add(Weight::from_parts(82_733, 0).saturating_mul(r.into())) - // Standard Error: 1_425 - .saturating_add(Weight::from_parts(1_512_506, 0).saturating_mul(s.into())) + // Measured: `7069 + r * (5 ±0) + s * (32 ±0)` + // Estimated: `11003` + // Minimum execution time: 69_824_000 picoseconds. + Weight::from_parts(71_656_254, 11003) + // Standard Error: 5_476 + .saturating_add(Weight::from_parts(69_975, 0).saturating_mul(r.into())) + // Standard Error: 1_068 + .saturating_add(Weight::from_parts(1_557_430, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -150,30 +144,30 @@ impl pallet_identity::WeightInfo for BasiliskWeight /// Storage: `Identity::Registrars` (r:1 w:0) /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. fn request_judgement(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `6968 + r * (57 ±0)` - // Estimated: `11037` - // Minimum execution time: 103_443_000 picoseconds. - Weight::from_parts(104_325_616, 11037) - // Standard Error: 2_698 - .saturating_add(Weight::from_parts(100_696, 0).saturating_mul(r.into())) + // Measured: `6967 + r * (57 ±0)` + // Estimated: `11003` + // Minimum execution time: 103_622_000 picoseconds. + Weight::from_parts(104_865_137, 11003) + // Standard Error: 2_298 + .saturating_add(Weight::from_parts(65_609, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. fn cancel_request(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `6999` - // Estimated: `11037` - // Minimum execution time: 100_843_000 picoseconds. - Weight::from_parts(102_197_805, 11037) - // Standard Error: 2_932 - .saturating_add(Weight::from_parts(3_915, 0).saturating_mul(r.into())) + // Measured: `6998` + // Estimated: `11003` + // Minimum execution time: 101_396_000 picoseconds. + Weight::from_parts(102_126_861, 11003) + // Standard Error: 2_559 + .saturating_add(Weight::from_parts(89_229, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -184,10 +178,10 @@ impl pallet_identity::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 10_836_000 picoseconds. - Weight::from_parts(11_391_620, 2626) - // Standard Error: 1_109 - .saturating_add(Weight::from_parts(74_708, 0).saturating_mul(r.into())) + // Minimum execution time: 10_269_000 picoseconds. + Weight::from_parts(10_654_210, 2626) + // Standard Error: 727 + .saturating_add(Weight::from_parts(66_455, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -198,10 +192,10 @@ impl pallet_identity::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 9_666_000 picoseconds. - Weight::from_parts(10_085_297, 2626) - // Standard Error: 901 - .saturating_add(Weight::from_parts(78_125, 0).saturating_mul(r.into())) + // Minimum execution time: 9_554_000 picoseconds. + Weight::from_parts(9_850_034, 2626) + // Standard Error: 797 + .saturating_add(Weight::from_parts(61_559, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -212,53 +206,53 @@ impl pallet_identity::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 9_509_000 picoseconds. - Weight::from_parts(9_947_843, 2626) - // Standard Error: 845 - .saturating_add(Weight::from_parts(77_402, 0).saturating_mul(r.into())) + // Minimum execution time: 9_185_000 picoseconds. + Weight::from_parts(9_697_346, 2626) + // Standard Error: 776 + .saturating_add(Weight::from_parts(61_390, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Identity::Registrars` (r:1 w:0) /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. - fn provide_judgement(_r: u32, ) -> Weight { + fn provide_judgement(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `7046 + r * (57 ±0)` - // Estimated: `11037` - // Minimum execution time: 127_329_000 picoseconds. - Weight::from_parts(129_567_547, 11037) + // Measured: `7045 + r * (57 ±0)` + // Estimated: `11003` + // Minimum execution time: 127_245_000 picoseconds. + Weight::from_parts(128_395_672, 11003) + // Standard Error: 3_190 + .saturating_add(Weight::from_parts(65_213, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Identity::SubsOf` (r:1 w:1) /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Identity::SuperOf` (r:0 w:100) /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. /// The range of component `s` is `[0, 100]`. - fn kill_identity(r: u32, s: u32, ) -> Weight { + fn kill_identity(_r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `7277 + r * (5 ±0) + s * (32 ±0)` - // Estimated: `11037` - // Minimum execution time: 88_445_000 picoseconds. - Weight::from_parts(90_310_160, 11037) - // Standard Error: 5_966 - .saturating_add(Weight::from_parts(49_966, 0).saturating_mul(r.into())) - // Standard Error: 1_164 - .saturating_add(Weight::from_parts(1_511_153, 0).saturating_mul(s.into())) + // Measured: `7276 + r * (5 ±0) + s * (32 ±0)` + // Estimated: `11003` + // Minimum execution time: 86_588_000 picoseconds. + Weight::from_parts(91_459_472, 11003) + // Standard Error: 1_151 + .saturating_add(Weight::from_parts(1_536_180, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) /// Storage: `Identity::SuperOf` (r:1 w:1) /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// Storage: `Identity::SubsOf` (r:1 w:1) @@ -267,32 +261,32 @@ impl pallet_identity::WeightInfo for BasiliskWeight fn add_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `475 + s * (36 ±0)` - // Estimated: `11037` - // Minimum execution time: 37_156_000 picoseconds. - Weight::from_parts(42_850_327, 11037) - // Standard Error: 1_340 - .saturating_add(Weight::from_parts(64_039, 0).saturating_mul(s.into())) + // Estimated: `11003` + // Minimum execution time: 38_042_000 picoseconds. + Weight::from_parts(43_055_974, 11003) + // Standard Error: 1_257 + .saturating_add(Weight::from_parts(63_515, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) /// Storage: `Identity::SuperOf` (r:1 w:1) /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 100]`. fn rename_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `591 + s * (3 ±0)` - // Estimated: `11037` - // Minimum execution time: 19_267_000 picoseconds. - Weight::from_parts(21_993_609, 11037) - // Standard Error: 611 - .saturating_add(Weight::from_parts(20_518, 0).saturating_mul(s.into())) + // Estimated: `11003` + // Minimum execution time: 23_136_000 picoseconds. + Weight::from_parts(25_783_381, 11003) + // Standard Error: 625 + .saturating_add(Weight::from_parts(23_943, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) /// Storage: `Identity::SuperOf` (r:1 w:1) /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// Storage: `Identity::SubsOf` (r:1 w:1) @@ -301,11 +295,11 @@ impl pallet_identity::WeightInfo for BasiliskWeight fn remove_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `638 + s * (35 ±0)` - // Estimated: `11037` - // Minimum execution time: 42_195_000 picoseconds. - Weight::from_parts(45_163_711, 11037) - // Standard Error: 796 - .saturating_add(Weight::from_parts(42_984, 0).saturating_mul(s.into())) + // Estimated: `11003` + // Minimum execution time: 41_970_000 picoseconds. + Weight::from_parts(44_810_903, 11003) + // Standard Error: 692 + .saturating_add(Weight::from_parts(50_358, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -320,101 +314,224 @@ impl pallet_identity::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `704 + s * (37 ±0)` // Estimated: `6723` - // Minimum execution time: 33_123_000 picoseconds. - Weight::from_parts(35_739_523, 6723) - // Standard Error: 925 - .saturating_add(Weight::from_parts(55_360, 0).saturating_mul(s.into())) + // Minimum execution time: 32_320_000 picoseconds. + Weight::from_parts(34_756_095, 6723) + // Standard Error: 826 + .saturating_add(Weight::from_parts(58_766, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Identity::UsernameAuthorities` (r:0 w:1) - /// Proof: `Identity::UsernameAuthorities` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Identity::AuthorityOf` (r:0 w:1) + /// Proof: `Identity::AuthorityOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn add_username_authority() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 10_373_000 picoseconds. - Weight::from_parts(10_579_000, 0) + // Minimum execution time: 10_391_000 picoseconds. + Weight::from_parts(10_774_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Identity::UsernameAuthorities` (r:1 w:1) - /// Proof: `Identity::UsernameAuthorities` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Identity::AuthorityOf` (r:1 w:1) + /// Proof: `Identity::AuthorityOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn remove_username_authority() -> Weight { // Proof Size summary in bytes: - // Measured: `80` + // Measured: `79` // Estimated: `3517` - // Minimum execution time: 15_741_000 picoseconds. - Weight::from_parts(16_142_000, 3517) + // Minimum execution time: 15_515_000 picoseconds. + Weight::from_parts(15_876_000, 3517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Identity::UsernameAuthorities` (r:1 w:1) - /// Proof: `Identity::UsernameAuthorities` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) - /// Storage: `Identity::AccountOfUsername` (r:1 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Identity::AuthorityOf` (r:1 w:1) + /// Proof: `Identity::AuthorityOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Identity::UsernameInfoOf` (r:1 w:1) + /// Proof: `Identity::UsernameInfoOf` (`max_values`: None, `max_size`: Some(98), added: 2573, mode: `MaxEncodedLen`) /// Storage: `Identity::PendingUsernames` (r:1 w:0) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - fn set_username_for() -> Weight { + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(102), added: 2577, mode: `MaxEncodedLen`) + /// Storage: `Identity::UsernameOf` (r:1 w:1) + /// Proof: `Identity::UsernameOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `p` is `[0, 1]`. + fn set_username_for(_p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `80` - // Estimated: `11037` - // Minimum execution time: 72_371_000 picoseconds. - Weight::from_parts(73_026_000, 11037) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + // Measured: `181` + // Estimated: `3593` + // Minimum execution time: 73_584_000 picoseconds. + Weight::from_parts(94_239_448, 3593) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `Identity::PendingUsernames` (r:1 w:1) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::AccountOfUsername` (r:0 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(102), added: 2577, mode: `MaxEncodedLen`) + /// Storage: `Identity::UsernameOf` (r:1 w:1) + /// Proof: `Identity::UsernameOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Identity::UsernameInfoOf` (r:0 w:1) + /// Proof: `Identity::UsernameInfoOf` (`max_values`: None, `max_size`: Some(98), added: 2573, mode: `MaxEncodedLen`) fn accept_username() -> Weight { // Proof Size summary in bytes: - // Measured: `115` - // Estimated: `11037` - // Minimum execution time: 31_184_000 picoseconds. - Weight::from_parts(31_455_000, 11037) + // Measured: `116` + // Estimated: `3567` + // Minimum execution time: 28_667_000 picoseconds. + Weight::from_parts(29_201_000, 3567) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Identity::PendingUsernames` (r:1 w:1) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) - fn remove_expired_approval() -> Weight { + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(102), added: 2577, mode: `MaxEncodedLen`) + /// Storage: `Identity::AuthorityOf` (r:1 w:0) + /// Proof: `Identity::AuthorityOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `p` is `[0, 1]`. + fn remove_expired_approval(_p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `309` + // Estimated: `3593` + // Minimum execution time: 18_448_000 picoseconds. + Weight::from_parts(43_087_920, 3593) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Identity::UsernameInfoOf` (r:1 w:0) + /// Proof: `Identity::UsernameInfoOf` (`max_values`: None, `max_size`: Some(98), added: 2573, mode: `MaxEncodedLen`) + /// Storage: `Identity::UsernameOf` (r:0 w:1) + /// Proof: `Identity::UsernameOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn set_primary_username() -> Weight { // Proof Size summary in bytes: - // Measured: `115` - // Estimated: `3550` - // Minimum execution time: 20_965_000 picoseconds. - Weight::from_parts(21_551_000, 3550) + // Measured: `172` + // Estimated: `3563` + // Minimum execution time: 19_317_000 picoseconds. + Weight::from_parts(19_638_000, 3563) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Identity::AccountOfUsername` (r:1 w:0) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - fn set_primary_username() -> Weight { + /// Storage: `Identity::UsernameInfoOf` (r:1 w:0) + /// Proof: `Identity::UsernameInfoOf` (`max_values`: None, `max_size`: Some(98), added: 2573, mode: `MaxEncodedLen`) + /// Storage: `Identity::AuthorityOf` (r:1 w:0) + /// Proof: `Identity::AuthorityOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Identity::UnbindingUsernames` (r:1 w:1) + /// Proof: `Identity::UnbindingUsernames` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + fn unbind_username() -> Weight { + // Proof Size summary in bytes: + // Measured: `236` + // Estimated: `3563` + // Minimum execution time: 24_896_000 picoseconds. + Weight::from_parts(25_289_000, 3563) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Identity::UnbindingUsernames` (r:1 w:1) + /// Proof: `Identity::UnbindingUsernames` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: `Identity::UsernameInfoOf` (r:1 w:1) + /// Proof: `Identity::UsernameInfoOf` (`max_values`: None, `max_size`: Some(98), added: 2573, mode: `MaxEncodedLen`) + /// Storage: `Identity::UsernameOf` (r:1 w:1) + /// Proof: `Identity::UsernameOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Identity::AuthorityOf` (r:1 w:0) + /// Proof: `Identity::AuthorityOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + fn remove_username() -> Weight { + // Proof Size summary in bytes: + // Measured: `297` + // Estimated: `3563` + // Minimum execution time: 30_804_000 picoseconds. + Weight::from_parts(31_192_000, 3563) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Identity::UsernameInfoOf` (r:1 w:1) + /// Proof: `Identity::UsernameInfoOf` (`max_values`: None, `max_size`: Some(98), added: 2573, mode: `MaxEncodedLen`) + /// Storage: `Identity::UsernameOf` (r:1 w:1) + /// Proof: `Identity::UsernameOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Identity::UnbindingUsernames` (r:1 w:1) + /// Proof: `Identity::UnbindingUsernames` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: `Identity::AuthorityOf` (r:1 w:0) + /// Proof: `Identity::AuthorityOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `p` is `[0, 1]`. + fn kill_username(_p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `257` - // Estimated: `11037` - // Minimum execution time: 26_140_000 picoseconds. - Weight::from_parts(26_702_000, 11037) + // Measured: `470` + // Estimated: `3593` + // Minimum execution time: 27_357_000 picoseconds. + Weight::from_parts(63_345_281, 3593) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: UNKNOWN KEY `0x2aeddc77fe58c98d50bd37f1b90840f99622d1423cdd16f5c33e2b531c34a53d` (r:2 w:0) + /// Proof: UNKNOWN KEY `0x2aeddc77fe58c98d50bd37f1b90840f99622d1423cdd16f5c33e2b531c34a53d` (r:2 w:0) + /// Storage: `Identity::AuthorityOf` (r:0 w:1) + /// Proof: `Identity::AuthorityOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + fn migration_v2_authority_step() -> Weight { + // Proof Size summary in bytes: + // Measured: `147` + // Estimated: `6087` + // Minimum execution time: 12_519_000 picoseconds. + Weight::from_parts(12_643_000, 6087) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Identity::AccountOfUsername` (r:1 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - fn remove_dangling_username() -> Weight { + /// Storage: UNKNOWN KEY `0x2aeddc77fe58c98d50bd37f1b90840f97c182fead9255863460affdd63116be3` (r:2 w:0) + /// Proof: UNKNOWN KEY `0x2aeddc77fe58c98d50bd37f1b90840f97c182fead9255863460affdd63116be3` (r:2 w:0) + /// Storage: `Identity::UsernameInfoOf` (r:0 w:1) + /// Proof: `Identity::UsernameInfoOf` (`max_values`: None, `max_size`: Some(98), added: 2573, mode: `MaxEncodedLen`) + fn migration_v2_username_step() -> Weight { + // Proof Size summary in bytes: + // Measured: `159` + // Estimated: `6099` + // Minimum execution time: 12_425_000 picoseconds. + Weight::from_parts(12_686_000, 6099) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Identity::IdentityOf` (r:2 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) + /// Storage: `Identity::UsernameOf` (r:0 w:1) + /// Proof: `Identity::UsernameOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn migration_v2_identity_step() -> Weight { + // Proof Size summary in bytes: + // Measured: `7062` + // Estimated: `21016` + // Minimum execution time: 84_412_000 picoseconds. + Weight::from_parts(85_085_000, 21016) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Identity::PendingUsernames` (r:2 w:1) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(102), added: 2577, mode: `MaxEncodedLen`) + fn migration_v2_pending_username_step() -> Weight { // Proof Size summary in bytes: - // Measured: `98` - // Estimated: `11037` - // Minimum execution time: 19_108_000 picoseconds. - Weight::from_parts(19_292_000, 11037) + // Measured: `201` + // Estimated: `6144` + // Minimum execution time: 11_219_000 picoseconds. + Weight::from_parts(11_371_000, 6144) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } + /// Storage: `Identity::AuthorityOf` (r:2 w:0) + /// Proof: `Identity::AuthorityOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x2aeddc77fe58c98d50bd37f1b90840f99622d1423cdd16f5c33e2b531c34a53d` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x2aeddc77fe58c98d50bd37f1b90840f99622d1423cdd16f5c33e2b531c34a53d` (r:1 w:1) + fn migration_v2_cleanup_authority_step() -> Weight { + // Proof Size summary in bytes: + // Measured: `288` + // Estimated: `6044` + // Minimum execution time: 16_142_000 picoseconds. + Weight::from_parts(16_456_000, 6044) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Identity::UsernameInfoOf` (r:2 w:0) + /// Proof: `Identity::UsernameInfoOf` (`max_values`: None, `max_size`: Some(98), added: 2573, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x2aeddc77fe58c98d50bd37f1b90840f97c182fead9255863460affdd63116be3` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x2aeddc77fe58c98d50bd37f1b90840f97c182fead9255863460affdd63116be3` (r:1 w:1) + fn migration_v2_cleanup_username_step() -> Weight { + // Proof Size summary in bytes: + // Measured: `290` + // Estimated: `6136` + // Minimum execution time: 14_602_000 picoseconds. + Weight::from_parts(14_917_000, 6136) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } } \ No newline at end of file diff --git a/runtime/basilisk/src/weights/pallet_lbp.rs b/runtime/basilisk/src/weights/pallet_lbp.rs index 04746fceb95..5e9c8176d24 100644 --- a/runtime/basilisk/src/weights/pallet_lbp.rs +++ b/runtime/basilisk/src/weights/pallet_lbp.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_lbp` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-lbp -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_lbp.rs +// --pallet=pallet_lbp +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -75,8 +69,8 @@ impl pallet_lbp::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `950` // Estimated: `11322` - // Minimum execution time: 131_108_000 picoseconds. - Weight::from_parts(132_020_000, 11322) + // Minimum execution time: 126_072_000 picoseconds. + Weight::from_parts(127_200_000, 11322) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } @@ -88,8 +82,8 @@ impl pallet_lbp::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `384` // Estimated: `3628` - // Minimum execution time: 29_218_000 picoseconds. - Weight::from_parts(29_736_000, 3628) + // Minimum execution time: 27_799_000 picoseconds. + Weight::from_parts(28_442_000, 3628) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -105,8 +99,8 @@ impl pallet_lbp::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `1105` // Estimated: `11322` - // Minimum execution time: 96_363_000 picoseconds. - Weight::from_parts(97_464_000, 11322) + // Minimum execution time: 92_320_000 picoseconds. + Weight::from_parts(93_740_000, 11322) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -128,8 +122,8 @@ impl pallet_lbp::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `1364` // Estimated: `11322` - // Minimum execution time: 126_752_000 picoseconds. - Weight::from_parts(128_055_000, 11322) + // Minimum execution time: 123_532_000 picoseconds. + Weight::from_parts(124_705_000, 11322) .saturating_add(T::DbWeight::get().reads(10_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } @@ -143,15 +137,17 @@ impl pallet_lbp::WeightInfo for BasiliskWeight { /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(87), added: 2562, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:3 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Broadcast::Swapper` (r:1 w:0) + /// Proof: `Broadcast::Swapper` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `Broadcast::ExecutionContext` (r:1 w:0) /// Proof: `Broadcast::ExecutionContext` (`max_values`: Some(1), `max_size`: Some(593), added: 1088, mode: `MaxEncodedLen`) fn sell() -> Weight { // Proof Size summary in bytes: // Measured: `1586` // Estimated: `13905` - // Minimum execution time: 237_445_000 picoseconds. - Weight::from_parts(239_352_000, 13905) - .saturating_add(T::DbWeight::get().reads(13_u64)) + // Minimum execution time: 222_522_000 picoseconds. + Weight::from_parts(224_596_000, 13905) + .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } /// Storage: `LBP::PoolData` (r:1 w:0) @@ -164,15 +160,17 @@ impl pallet_lbp::WeightInfo for BasiliskWeight { /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(87), added: 2562, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:3 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Broadcast::Swapper` (r:1 w:0) + /// Proof: `Broadcast::Swapper` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `Broadcast::ExecutionContext` (r:1 w:0) /// Proof: `Broadcast::ExecutionContext` (`max_values`: Some(1), `max_size`: Some(593), added: 1088, mode: `MaxEncodedLen`) fn buy() -> Weight { // Proof Size summary in bytes: // Measured: `1586` // Estimated: `13905` - // Minimum execution time: 234_871_000 picoseconds. - Weight::from_parts(236_479_000, 13905) - .saturating_add(T::DbWeight::get().reads(13_u64)) + // Minimum execution time: 227_639_000 picoseconds. + Weight::from_parts(229_369_000, 13905) + .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } /// Storage: `LBP::PoolData` (r:1 w:0) @@ -185,6 +183,8 @@ impl pallet_lbp::WeightInfo for BasiliskWeight { /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(87), added: 2562, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:3 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Broadcast::Swapper` (r:1 w:0) + /// Proof: `Broadcast::Swapper` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `Broadcast::ExecutionContext` (r:1 w:0) /// Proof: `Broadcast::ExecutionContext` (`max_values`: Some(1), `max_size`: Some(593), added: 1088, mode: `MaxEncodedLen`) /// The range of component `c` is `[1, 2]`. @@ -193,14 +193,14 @@ impl pallet_lbp::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `718 + e * (868 ±0)` // Estimated: `6156 + e * (7749 ±6_801_226_166_572_765)` - // Minimum execution time: 90_780_000 picoseconds. - Weight::from_parts(91_674_000, 6156) - // Standard Error: 226_536 - .saturating_add(Weight::from_parts(877_607, 0).saturating_mul(c.into())) - // Standard Error: 504_561 - .saturating_add(Weight::from_parts(147_205_098, 0).saturating_mul(e.into())) + // Minimum execution time: 79_646_000 picoseconds. + Weight::from_parts(80_347_000, 6156) + // Standard Error: 200_186 + .saturating_add(Weight::from_parts(815_854, 0).saturating_mul(c.into())) + // Standard Error: 445_871 + .saturating_add(Weight::from_parts(145_598_392, 0).saturating_mul(e.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().reads((10_u64).saturating_mul(e.into()))) + .saturating_add(T::DbWeight::get().reads((11_u64).saturating_mul(e.into()))) .saturating_add(T::DbWeight::get().writes((7_u64).saturating_mul(e.into()))) .saturating_add(Weight::from_parts(0, 7749).saturating_mul(e.into())) } @@ -214,6 +214,8 @@ impl pallet_lbp::WeightInfo for BasiliskWeight { /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(87), added: 2562, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:3 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Broadcast::Swapper` (r:1 w:0) + /// Proof: `Broadcast::Swapper` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `Broadcast::ExecutionContext` (r:1 w:0) /// Proof: `Broadcast::ExecutionContext` (`max_values`: Some(1), `max_size`: Some(593), added: 1088, mode: `MaxEncodedLen`) /// The range of component `c` is `[1, 3]`. @@ -221,15 +223,15 @@ impl pallet_lbp::WeightInfo for BasiliskWeight { fn router_execution_buy(c: u32, e: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `718 + e * (868 ±0)` - // Estimated: `6156 + e * (7749 ±851_806_049_420_682)` - // Minimum execution time: 162_634_000 picoseconds. - Weight::from_parts(163_572_000, 6156) - // Standard Error: 425_970 - .saturating_add(Weight::from_parts(2_737_882, 0).saturating_mul(c.into())) - // Standard Error: 1_436_510 - .saturating_add(Weight::from_parts(108_685_914, 0).saturating_mul(e.into())) + // Estimated: `6156 + e * (7749 ±1_922_716_303_367_818)` + // Minimum execution time: 141_024_000 picoseconds. + Weight::from_parts(142_220_000, 6156) + // Standard Error: 368_030 + .saturating_add(Weight::from_parts(2_412_599, 0).saturating_mul(c.into())) + // Standard Error: 1_241_118 + .saturating_add(Weight::from_parts(111_841_287, 0).saturating_mul(e.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().reads((10_u64).saturating_mul(e.into()))) + .saturating_add(T::DbWeight::get().reads((11_u64).saturating_mul(e.into()))) .saturating_add(T::DbWeight::get().writes((7_u64).saturating_mul(e.into()))) .saturating_add(Weight::from_parts(0, 7749).saturating_mul(e.into())) } @@ -241,8 +243,8 @@ impl pallet_lbp::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `718` // Estimated: `6156` - // Minimum execution time: 93_499_000 picoseconds. - Weight::from_parts(93_976_000, 6156) + // Minimum execution time: 86_349_000 picoseconds. + Weight::from_parts(86_882_000, 6156) .saturating_add(T::DbWeight::get().reads(3_u64)) } /// Storage: `LBP::PoolData` (r:1 w:0) @@ -255,8 +257,8 @@ impl pallet_lbp::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `718` // Estimated: `6156` - // Minimum execution time: 30_271_000 picoseconds. - Weight::from_parts(30_562_000, 6156) + // Minimum execution time: 28_184_000 picoseconds. + Weight::from_parts(28_773_000, 6156) .saturating_add(T::DbWeight::get().reads(4_u64)) } } \ No newline at end of file diff --git a/runtime/basilisk/src/weights/pallet_marketplace.rs b/runtime/basilisk/src/weights/pallet_marketplace.rs index 0e19c4618cf..fae2a33520f 100644 --- a/runtime/basilisk/src/weights/pallet_marketplace.rs +++ b/runtime/basilisk/src/weights/pallet_marketplace.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_marketplace` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-marketplace -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_marketplace.rs +// --pallet=pallet_marketplace +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -83,8 +77,8 @@ impl pallet_marketplace::WeightInfo for BasiliskWeight< // Proof Size summary in bytes: // Measured: `2792` // Estimated: `6156` - // Minimum execution time: 133_358_000 picoseconds. - Weight::from_parts(134_664_000, 6156) + // Minimum execution time: 249_477_000 picoseconds. + Weight::from_parts(264_777_000, 6156) .saturating_add(T::DbWeight::get().reads(10_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } @@ -96,8 +90,8 @@ impl pallet_marketplace::WeightInfo for BasiliskWeight< // Proof Size summary in bytes: // Measured: `1360` // Estimated: `3611` - // Minimum execution time: 39_494_000 picoseconds. - Weight::from_parts(39_928_000, 3611) + // Minimum execution time: 78_928_000 picoseconds. + Weight::from_parts(82_788_000, 3611) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -115,8 +109,8 @@ impl pallet_marketplace::WeightInfo for BasiliskWeight< // Proof Size summary in bytes: // Measured: `1731` // Estimated: `4087` - // Minimum execution time: 68_389_000 picoseconds. - Weight::from_parts(69_155_000, 4087) + // Minimum execution time: 124_546_000 picoseconds. + Weight::from_parts(137_721_000, 4087) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -136,8 +130,8 @@ impl pallet_marketplace::WeightInfo for BasiliskWeight< // Proof Size summary in bytes: // Measured: `2222` // Estimated: `4087` - // Minimum execution time: 71_555_000 picoseconds. - Weight::from_parts(71_998_000, 4087) + // Minimum execution time: 135_596_000 picoseconds. + Weight::from_parts(140_816_000, 4087) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -169,8 +163,8 @@ impl pallet_marketplace::WeightInfo for BasiliskWeight< // Proof Size summary in bytes: // Measured: `2862` // Estimated: `6156` - // Minimum execution time: 155_222_000 picoseconds. - Weight::from_parts(156_370_000, 6156) + // Minimum execution time: 294_659_000 picoseconds. + Weight::from_parts(303_201_000, 6156) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } @@ -186,8 +180,8 @@ impl pallet_marketplace::WeightInfo for BasiliskWeight< // Proof Size summary in bytes: // Measured: `1643` // Estimated: `4087` - // Minimum execution time: 52_363_000 picoseconds. - Weight::from_parts(53_037_000, 4087) + // Minimum execution time: 99_926_000 picoseconds. + Weight::from_parts(104_580_000, 4087) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } diff --git a/runtime/basilisk/src/weights/pallet_message_queue.rs b/runtime/basilisk/src/weights/pallet_message_queue.rs index 59f3512d4fa..b8e461ebbab 100644 --- a/runtime/basilisk/src/weights/pallet_message_queue.rs +++ b/runtime/basilisk/src/weights/pallet_message_queue.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_message_queue` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-message-queue -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_message_queue.rs +// --pallet=pallet_message_queue +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -65,8 +59,8 @@ impl pallet_message_queue::WeightInfo for BasiliskWeigh // Proof Size summary in bytes: // Measured: `298` // Estimated: `6044` - // Minimum execution time: 19_850_000 picoseconds. - Weight::from_parts(20_272_000, 6044) + // Minimum execution time: 18_752_000 picoseconds. + Weight::from_parts(19_223_000, 6044) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -78,8 +72,8 @@ impl pallet_message_queue::WeightInfo for BasiliskWeigh // Proof Size summary in bytes: // Measured: `293` // Estimated: `6044` - // Minimum execution time: 18_258_000 picoseconds. - Weight::from_parts(18_680_000, 6044) + // Minimum execution time: 17_421_000 picoseconds. + Weight::from_parts(17_733_000, 6044) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -89,8 +83,8 @@ impl pallet_message_queue::WeightInfo for BasiliskWeigh // Proof Size summary in bytes: // Measured: `80` // Estimated: `3517` - // Minimum execution time: 8_931_000 picoseconds. - Weight::from_parts(9_173_000, 3517) + // Minimum execution time: 8_371_000 picoseconds. + Weight::from_parts(8_561_000, 3517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -100,8 +94,8 @@ impl pallet_message_queue::WeightInfo for BasiliskWeigh // Proof Size summary in bytes: // Measured: `147` // Estimated: `137658` - // Minimum execution time: 11_330_000 picoseconds. - Weight::from_parts(11_596_000, 137658) + // Minimum execution time: 10_788_000 picoseconds. + Weight::from_parts(11_052_000, 137658) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -111,8 +105,8 @@ impl pallet_message_queue::WeightInfo for BasiliskWeigh // Proof Size summary in bytes: // Measured: `147` // Estimated: `137658` - // Minimum execution time: 11_617_000 picoseconds. - Weight::from_parts(11_803_000, 137658) + // Minimum execution time: 10_860_000 picoseconds. + Weight::from_parts(11_165_000, 137658) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -124,8 +118,8 @@ impl pallet_message_queue::WeightInfo for BasiliskWeigh // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 285_385_000 picoseconds. - Weight::from_parts(286_897_000, 0) + // Minimum execution time: 317_625_000 picoseconds. + Weight::from_parts(319_851_000, 0) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) @@ -136,11 +130,24 @@ impl pallet_message_queue::WeightInfo for BasiliskWeigh // Proof Size summary in bytes: // Measured: `246` // Estimated: `3517` - // Minimum execution time: 12_371_000 picoseconds. - Weight::from_parts(12_776_000, 3517) + // Minimum execution time: 11_511_000 picoseconds. + Weight::from_parts(12_063_000, 3517) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } + /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::ServiceHead` (r:0 w:1) + /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`) + fn set_service_head() -> Weight { + // Proof Size summary in bytes: + // Measured: `236` + // Estimated: `3517` + // Minimum execution time: 9_974_000 picoseconds. + Weight::from_parts(10_201_000, 3517) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `MessageQueue::Pages` (r:1 w:1) @@ -149,8 +156,8 @@ impl pallet_message_queue::WeightInfo for BasiliskWeigh // Proof Size summary in bytes: // Measured: `134349` // Estimated: `137658` - // Minimum execution time: 108_835_000 picoseconds. - Weight::from_parts(109_651_000, 137658) + // Minimum execution time: 122_056_000 picoseconds. + Weight::from_parts(122_657_000, 137658) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -162,8 +169,8 @@ impl pallet_message_queue::WeightInfo for BasiliskWeigh // Proof Size summary in bytes: // Measured: `134349` // Estimated: `137658` - // Minimum execution time: 141_908_000 picoseconds. - Weight::from_parts(142_292_000, 137658) + // Minimum execution time: 156_166_000 picoseconds. + Weight::from_parts(157_040_000, 137658) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -175,8 +182,8 @@ impl pallet_message_queue::WeightInfo for BasiliskWeigh // Proof Size summary in bytes: // Measured: `134349` // Estimated: `137658` - // Minimum execution time: 213_896_000 picoseconds. - Weight::from_parts(215_100_000, 137658) + // Minimum execution time: 231_842_000 picoseconds. + Weight::from_parts(233_185_000, 137658) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } diff --git a/runtime/basilisk/src/weights/pallet_multisig.rs b/runtime/basilisk/src/weights/pallet_multisig.rs index 09bef739a45..daca7671183 100644 --- a/runtime/basilisk/src/weights/pallet_multisig.rs +++ b/runtime/basilisk/src/weights/pallet_multisig.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_multisig` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-multisig -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_multisig.rs +// --pallet=pallet_multisig +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -62,10 +56,10 @@ impl pallet_multisig::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 13_781_000 picoseconds. - Weight::from_parts(14_139_559, 0) + // Minimum execution time: 15_138_000 picoseconds. + Weight::from_parts(15_501_220, 0) // Standard Error: 1 - .saturating_add(Weight::from_parts(609, 0).saturating_mul(z.into())) + .saturating_add(Weight::from_parts(435, 0).saturating_mul(z.into())) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) @@ -75,12 +69,12 @@ impl pallet_multisig::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `263 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 48_222_000 picoseconds. - Weight::from_parts(43_222_174, 6811) - // Standard Error: 352 - .saturating_add(Weight::from_parts(58_876, 0).saturating_mul(s.into())) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_291, 0).saturating_mul(z.into())) + // Minimum execution time: 50_026_000 picoseconds. + Weight::from_parts(44_078_027, 6811) + // Standard Error: 5_592 + .saturating_add(Weight::from_parts(66_025, 0).saturating_mul(s.into())) + // Standard Error: 54 + .saturating_add(Weight::from_parts(1_554, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -92,12 +86,12 @@ impl pallet_multisig::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `282` // Estimated: `6811` - // Minimum execution time: 30_822_000 picoseconds. - Weight::from_parts(26_361_063, 6811) - // Standard Error: 347 - .saturating_add(Weight::from_parts(51_769, 0).saturating_mul(s.into())) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_296, 0).saturating_mul(z.into())) + // Minimum execution time: 31_459_000 picoseconds. + Weight::from_parts(24_870_077, 6811) + // Standard Error: 250 + .saturating_add(Weight::from_parts(70_950, 0).saturating_mul(s.into())) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_632, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -111,12 +105,12 @@ impl pallet_multisig::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `388 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 53_669_000 picoseconds. - Weight::from_parts(47_224_703, 6811) - // Standard Error: 520 - .saturating_add(Weight::from_parts(73_444, 0).saturating_mul(s.into())) - // Standard Error: 5 - .saturating_add(Weight::from_parts(1_325, 0).saturating_mul(z.into())) + // Minimum execution time: 53_763_000 picoseconds. + Weight::from_parts(45_270_973, 6811) + // Standard Error: 376 + .saturating_add(Weight::from_parts(93_926, 0).saturating_mul(s.into())) + // Standard Error: 3 + .saturating_add(Weight::from_parts(1_615, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -127,10 +121,10 @@ impl pallet_multisig::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `263 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 40_790_000 picoseconds. - Weight::from_parts(41_213_557, 6811) - // Standard Error: 592 - .saturating_add(Weight::from_parts(53_670, 0).saturating_mul(s.into())) + // Minimum execution time: 39_548_000 picoseconds. + Weight::from_parts(40_129_374, 6811) + // Standard Error: 339 + .saturating_add(Weight::from_parts(73_638, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -141,10 +135,10 @@ impl pallet_multisig::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `282` // Estimated: `6811` - // Minimum execution time: 24_093_000 picoseconds. - Weight::from_parts(24_294_916, 6811) - // Standard Error: 641 - .saturating_add(Weight::from_parts(50_504, 0).saturating_mul(s.into())) + // Minimum execution time: 22_879_000 picoseconds. + Weight::from_parts(23_416_900, 6811) + // Standard Error: 431 + .saturating_add(Weight::from_parts(70_141, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -155,10 +149,24 @@ impl pallet_multisig::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `454 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 40_677_000 picoseconds. - Weight::from_parts(41_138_895, 6811) - // Standard Error: 565 - .saturating_add(Weight::from_parts(57_750, 0).saturating_mul(s.into())) + // Minimum execution time: 39_918_000 picoseconds. + Weight::from_parts(40_462_111, 6811) + // Standard Error: 347 + .saturating_add(Weight::from_parts(72_855, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// The range of component `s` is `[2, 100]`. + fn poke_deposit(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `454 + s * (1 ±0)` + // Estimated: `6811` + // Minimum execution time: 37_754_000 picoseconds. + Weight::from_parts(38_219_222, 6811) + // Standard Error: 355 + .saturating_add(Weight::from_parts(72_570, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } diff --git a/runtime/basilisk/src/weights/pallet_nft.rs b/runtime/basilisk/src/weights/pallet_nft.rs index 06aae4a2964..c11a9395535 100644 --- a/runtime/basilisk/src/weights/pallet_nft.rs +++ b/runtime/basilisk/src/weights/pallet_nft.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_nft` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-nft -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_nft.rs +// --pallet=pallet_nft +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -74,8 +68,8 @@ impl pallet_nft::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `500` // Estimated: `4087` - // Minimum execution time: 33_975_000 picoseconds. - Weight::from_parts(34_427_000, 4087) + // Minimum execution time: 33_909_000 picoseconds. + Weight::from_parts(34_237_000, 4087) .saturating_mul(CREATE_COLLECTION_OFFSET) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -100,8 +94,8 @@ impl pallet_nft::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `936` // Estimated: `4087` - // Minimum execution time: 57_734_000 picoseconds. - Weight::from_parts(58_201_000, 4087) + // Minimum execution time: 56_711_000 picoseconds. + Weight::from_parts(57_237_000, 4087) .saturating_mul(MINT_OFFSET) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) @@ -120,8 +114,8 @@ impl pallet_nft::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `873` // Estimated: `3655` - // Minimum execution time: 50_979_000 picoseconds. - Weight::from_parts(51_782_000, 3655) + // Minimum execution time: 51_229_000 picoseconds. + Weight::from_parts(51_418_000, 3655) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -145,8 +139,8 @@ impl pallet_nft::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `940` // Estimated: `4087` - // Minimum execution time: 63_629_000 picoseconds. - Weight::from_parts(64_708_000, 4087) + // Minimum execution time: 64_288_000 picoseconds. + Weight::from_parts(64_856_000, 4087) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -170,8 +164,8 @@ impl pallet_nft::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `1141` // Estimated: `4087` - // Minimum execution time: 57_366_000 picoseconds. - Weight::from_parts(57_943_000, 4087) + // Minimum execution time: 57_118_000 picoseconds. + Weight::from_parts(57_750_000, 4087) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } diff --git a/runtime/basilisk/src/weights/pallet_preimage.rs b/runtime/basilisk/src/weights/pallet_preimage.rs index d4a68e5aa69..67d53b21787 100644 --- a/runtime/basilisk/src/weights/pallet_preimage.rs +++ b/runtime/basilisk/src/weights/pallet_preimage.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_preimage` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-preimage -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_preimage.rs +// --pallet=pallet_preimage +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -62,18 +56,18 @@ impl pallet_preimage::WeightInfo for BasiliskWeight /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(139), added: 2614, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `109` - // Estimated: `3556` - // Minimum execution time: 58_621_000 picoseconds. - Weight::from_parts(58_833_000, 3556) - // Standard Error: 5 - .saturating_add(Weight::from_parts(2_116, 0).saturating_mul(s.into())) + // Estimated: `3604` + // Minimum execution time: 60_277_000 picoseconds. + Weight::from_parts(25_503_592, 3604) + // Standard Error: 2 + .saturating_add(Weight::from_parts(2_191, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -88,10 +82,10 @@ impl pallet_preimage::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `173` // Estimated: `3556` - // Minimum execution time: 22_182_000 picoseconds. - Weight::from_parts(22_459_000, 3556) - // Standard Error: 2 - .saturating_add(Weight::from_parts(2_075, 0).saturating_mul(s.into())) + // Minimum execution time: 21_546_000 picoseconds. + Weight::from_parts(21_746_000, 3556) + // Standard Error: 1 + .saturating_add(Weight::from_parts(2_176, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -106,10 +100,10 @@ impl pallet_preimage::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `173` // Estimated: `3556` - // Minimum execution time: 22_941_000 picoseconds. - Weight::from_parts(23_198_000, 3556) - // Standard Error: 2 - .saturating_add(Weight::from_parts(2_076, 0).saturating_mul(s.into())) + // Minimum execution time: 21_733_000 picoseconds. + Weight::from_parts(21_897_000, 3556) + // Standard Error: 5 + .saturating_add(Weight::from_parts(2_223, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -118,15 +112,15 @@ impl pallet_preimage::WeightInfo for BasiliskWeight /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(139), added: 2614, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unnote_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `310` - // Estimated: `3556` - // Minimum execution time: 64_720_000 picoseconds. - Weight::from_parts(65_969_000, 3556) + // Estimated: `3604` + // Minimum execution time: 62_606_000 picoseconds. + Weight::from_parts(63_728_000, 3604) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -140,8 +134,8 @@ impl pallet_preimage::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `211` // Estimated: `3556` - // Minimum execution time: 33_555_000 picoseconds. - Weight::from_parts(34_276_000, 3556) + // Minimum execution time: 29_971_000 picoseconds. + Weight::from_parts(31_500_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -153,8 +147,8 @@ impl pallet_preimage::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `255` // Estimated: `3556` - // Minimum execution time: 27_074_000 picoseconds. - Weight::from_parts(28_163_000, 3556) + // Minimum execution time: 24_837_000 picoseconds. + Weight::from_parts(25_479_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -166,8 +160,8 @@ impl pallet_preimage::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `211` // Estimated: `3556` - // Minimum execution time: 20_754_000 picoseconds. - Weight::from_parts(21_454_000, 3556) + // Minimum execution time: 17_963_000 picoseconds. + Weight::from_parts(18_942_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -179,8 +173,8 @@ impl pallet_preimage::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `109` // Estimated: `3556` - // Minimum execution time: 20_179_000 picoseconds. - Weight::from_parts(20_728_000, 3556) + // Minimum execution time: 18_780_000 picoseconds. + Weight::from_parts(19_206_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -192,8 +186,8 @@ impl pallet_preimage::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `173` // Estimated: `3556` - // Minimum execution time: 15_750_000 picoseconds. - Weight::from_parts(16_212_000, 3556) + // Minimum execution time: 14_710_000 picoseconds. + Weight::from_parts(15_009_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -207,8 +201,8 @@ impl pallet_preimage::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `211` // Estimated: `3556` - // Minimum execution time: 29_698_000 picoseconds. - Weight::from_parts(30_772_000, 3556) + // Minimum execution time: 26_858_000 picoseconds. + Weight::from_parts(27_754_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -220,8 +214,8 @@ impl pallet_preimage::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `173` // Estimated: `3556` - // Minimum execution time: 15_560_000 picoseconds. - Weight::from_parts(15_910_000, 3556) + // Minimum execution time: 14_275_000 picoseconds. + Weight::from_parts(14_698_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -233,8 +227,8 @@ impl pallet_preimage::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `173` // Estimated: `3556` - // Minimum execution time: 15_770_000 picoseconds. - Weight::from_parts(16_268_000, 3556) + // Minimum execution time: 14_488_000 picoseconds. + Weight::from_parts(14_835_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -243,20 +237,20 @@ impl pallet_preimage::WeightInfo for BasiliskWeight /// Storage: `System::Account` (r:1023 w:1023) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1023 w:1023) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(139), added: 2614, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:0 w:1023) /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 1024]`. fn ensure_updated(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + n * (227 ±0)` - // Estimated: `990 + n * (2603 ±0)` - // Minimum execution time: 65_318_000 picoseconds. - Weight::from_parts(65_440_000, 990) - // Standard Error: 34_964 - .saturating_add(Weight::from_parts(60_442_104, 0).saturating_mul(n.into())) + // Estimated: `990 + n * (2614 ±0)` + // Minimum execution time: 65_939_000 picoseconds. + Weight::from_parts(66_750_000, 990) + // Standard Error: 37_522 + .saturating_add(Weight::from_parts(60_109_763, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2603).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(0, 2614).saturating_mul(n.into())) } } \ No newline at end of file diff --git a/runtime/basilisk/src/weights/pallet_proxy.rs b/runtime/basilisk/src/weights/pallet_proxy.rs index 7b592239507..236a79ba385 100644 --- a/runtime/basilisk/src/weights/pallet_proxy.rs +++ b/runtime/basilisk/src/weights/pallet_proxy.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_proxy` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-proxy -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_proxy.rs +// --pallet=pallet_proxy +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -64,10 +58,10 @@ impl pallet_proxy::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `194 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 19_657_000 picoseconds. - Weight::from_parts(20_362_758, 4706) - // Standard Error: 704 - .saturating_add(Weight::from_parts(33_870, 0).saturating_mul(p.into())) + // Minimum execution time: 19_209_000 picoseconds. + Weight::from_parts(19_591_203, 4706) + // Standard Error: 597 + .saturating_add(Weight::from_parts(21_547, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Proxy::Proxies` (r:1 w:0) @@ -82,12 +76,12 @@ impl pallet_proxy::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `521 + a * (68 ±0) + p * (37 ±0)` // Estimated: `5698` - // Minimum execution time: 46_479_000 picoseconds. - Weight::from_parts(46_817_772, 5698) - // Standard Error: 1_555 - .saturating_add(Weight::from_parts(169_751, 0).saturating_mul(a.into())) - // Standard Error: 1_607 - .saturating_add(Weight::from_parts(34_906, 0).saturating_mul(p.into())) + // Minimum execution time: 45_489_000 picoseconds. + Weight::from_parts(45_438_556, 5698) + // Standard Error: 1_534 + .saturating_add(Weight::from_parts(174_381, 0).saturating_mul(a.into())) + // Standard Error: 1_585 + .saturating_add(Weight::from_parts(25_310, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -97,14 +91,16 @@ impl pallet_proxy::WeightInfo for BasiliskWeight { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. - fn remove_announcement(a: u32, _p: u32, ) -> Weight { + fn remove_announcement(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `436 + a * (68 ±0)` // Estimated: `5698` - // Minimum execution time: 32_174_000 picoseconds. - Weight::from_parts(32_948_861, 5698) - // Standard Error: 1_381 - .saturating_add(Weight::from_parts(169_631, 0).saturating_mul(a.into())) + // Minimum execution time: 31_723_000 picoseconds. + Weight::from_parts(32_336_003, 5698) + // Standard Error: 1_365 + .saturating_add(Weight::from_parts(165_488, 0).saturating_mul(a.into())) + // Standard Error: 1_410 + .saturating_add(Weight::from_parts(1_081, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -118,12 +114,12 @@ impl pallet_proxy::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `436 + a * (68 ±0)` // Estimated: `5698` - // Minimum execution time: 31_950_000 picoseconds. - Weight::from_parts(32_916_821, 5698) - // Standard Error: 1_457 - .saturating_add(Weight::from_parts(168_688, 0).saturating_mul(a.into())) - // Standard Error: 1_505 - .saturating_add(Weight::from_parts(2_452, 0).saturating_mul(p.into())) + // Minimum execution time: 31_462_000 picoseconds. + Weight::from_parts(32_133_463, 5698) + // Standard Error: 1_440 + .saturating_add(Weight::from_parts(169_911, 0).saturating_mul(a.into())) + // Standard Error: 1_488 + .saturating_add(Weight::from_parts(6_774, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -139,12 +135,12 @@ impl pallet_proxy::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `453 + a * (68 ±0) + p * (37 ±0)` // Estimated: `5698` - // Minimum execution time: 42_268_000 picoseconds. - Weight::from_parts(42_273_786, 5698) - // Standard Error: 1_454 - .saturating_add(Weight::from_parts(162_581, 0).saturating_mul(a.into())) - // Standard Error: 1_502 - .saturating_add(Weight::from_parts(38_771, 0).saturating_mul(p.into())) + // Minimum execution time: 41_032_000 picoseconds. + Weight::from_parts(41_151_619, 5698) + // Standard Error: 1_556 + .saturating_add(Weight::from_parts(158_990, 0).saturating_mul(a.into())) + // Standard Error: 1_607 + .saturating_add(Weight::from_parts(27_081, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -155,10 +151,10 @@ impl pallet_proxy::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `194 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 31_466_000 picoseconds. - Weight::from_parts(31_906_947, 4706) - // Standard Error: 698 - .saturating_add(Weight::from_parts(34_648, 0).saturating_mul(p.into())) + // Minimum execution time: 30_712_000 picoseconds. + Weight::from_parts(31_167_291, 4706) + // Standard Error: 712 + .saturating_add(Weight::from_parts(38_298, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -169,10 +165,10 @@ impl pallet_proxy::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `194 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 30_927_000 picoseconds. - Weight::from_parts(31_710_071, 4706) - // Standard Error: 992 - .saturating_add(Weight::from_parts(55_022, 0).saturating_mul(p.into())) + // Minimum execution time: 30_637_000 picoseconds. + Weight::from_parts(31_295_594, 4706) + // Standard Error: 742 + .saturating_add(Weight::from_parts(35_349, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -183,10 +179,10 @@ impl pallet_proxy::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `194 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 28_055_000 picoseconds. - Weight::from_parts(28_867_565, 4706) - // Standard Error: 864 - .saturating_add(Weight::from_parts(31_816, 0).saturating_mul(p.into())) + // Minimum execution time: 28_003_000 picoseconds. + Weight::from_parts(28_552_497, 4706) + // Standard Error: 781 + .saturating_add(Weight::from_parts(25_230, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -197,10 +193,10 @@ impl pallet_proxy::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `206` // Estimated: `4706` - // Minimum execution time: 33_130_000 picoseconds. - Weight::from_parts(33_839_330, 4706) - // Standard Error: 767 - .saturating_add(Weight::from_parts(7_998, 0).saturating_mul(p.into())) + // Minimum execution time: 32_858_000 picoseconds. + Weight::from_parts(33_821_066, 4706) + // Standard Error: 1_010 + .saturating_add(Weight::from_parts(8_817, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -211,11 +207,26 @@ impl pallet_proxy::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `231 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 28_873_000 picoseconds. - Weight::from_parts(29_682_447, 4706) - // Standard Error: 878 - .saturating_add(Weight::from_parts(39_698, 0).saturating_mul(p.into())) + // Minimum execution time: 28_598_000 picoseconds. + Weight::from_parts(29_373_259, 4706) + // Standard Error: 760 + .saturating_add(Weight::from_parts(23_161, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Proxy::Announcements` (r:1 w:1) + /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) + fn poke_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `519` + // Estimated: `5698` + // Minimum execution time: 54_326_000 picoseconds. + Weight::from_parts(54_840_000, 5698) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } } \ No newline at end of file diff --git a/runtime/basilisk/src/weights/pallet_referenda.rs b/runtime/basilisk/src/weights/pallet_referenda.rs index b982a69d216..12f47e19a3b 100644 --- a/runtime/basilisk/src/weights/pallet_referenda.rs +++ b/runtime/basilisk/src/weights/pallet_referenda.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_referenda` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-referenda -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_referenda.rs +// --pallet=pallet_referenda +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -67,8 +61,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `220` // Estimated: `42428` - // Minimum execution time: 46_785_000 picoseconds. - Weight::from_parts(47_113_000, 42428) + // Minimum execution time: 46_152_000 picoseconds. + Weight::from_parts(46_705_000, 42428) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -82,8 +76,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `473` // Estimated: `83866` - // Minimum execution time: 62_125_000 picoseconds. - Weight::from_parts(62_579_000, 83866) + // Minimum execution time: 60_970_000 picoseconds. + Weight::from_parts(61_637_000, 83866) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -99,10 +93,10 @@ impl pallet_referenda::WeightInfo for BasiliskWeight /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3260` + // Measured: `3271` // Estimated: `42428` - // Minimum execution time: 76_588_000 picoseconds. - Weight::from_parts(77_848_000, 42428) + // Minimum execution time: 74_366_000 picoseconds. + Weight::from_parts(75_343_000, 42428) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -118,10 +112,10 @@ impl pallet_referenda::WeightInfo for BasiliskWeight /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3280` + // Measured: `3291` // Estimated: `42428` - // Minimum execution time: 76_610_000 picoseconds. - Weight::from_parts(77_569_000, 42428) + // Minimum execution time: 72_912_000 picoseconds. + Weight::from_parts(74_619_000, 42428) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -139,8 +133,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `473` // Estimated: `83866` - // Minimum execution time: 73_014_000 picoseconds. - Weight::from_parts(73_622_000, 83866) + // Minimum execution time: 72_185_000 picoseconds. + Weight::from_parts(72_855_000, 83866) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -158,8 +152,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `473` // Estimated: `83866` - // Minimum execution time: 71_930_000 picoseconds. - Weight::from_parts(72_798_000, 83866) + // Minimum execution time: 71_992_000 picoseconds. + Weight::from_parts(72_509_000, 83866) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -169,8 +163,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `351` // Estimated: `4401` - // Minimum execution time: 36_480_000 picoseconds. - Weight::from_parts(37_040_000, 4401) + // Minimum execution time: 36_056_000 picoseconds. + Weight::from_parts(36_637_000, 4401) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -180,8 +174,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `341` // Estimated: `4401` - // Minimum execution time: 37_296_000 picoseconds. - Weight::from_parts(37_657_000, 4401) + // Minimum execution time: 36_379_000 picoseconds. + Weight::from_parts(36_702_000, 4401) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -195,8 +189,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `381` // Estimated: `83866` - // Minimum execution time: 44_416_000 picoseconds. - Weight::from_parts(45_627_000, 83866) + // Minimum execution time: 43_465_000 picoseconds. + Weight::from_parts(43_976_000, 83866) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -212,8 +206,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `622` // Estimated: `83866` - // Minimum execution time: 108_293_000 picoseconds. - Weight::from_parts(111_331_000, 83866) + // Minimum execution time: 108_183_000 picoseconds. + Weight::from_parts(108_932_000, 83866) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -225,8 +219,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `174` // Estimated: `5477` - // Minimum execution time: 15_269_000 picoseconds. - Weight::from_parts(15_615_000, 5477) + // Minimum execution time: 14_589_000 picoseconds. + Weight::from_parts(14_731_000, 5477) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -240,10 +234,10 @@ impl pallet_referenda::WeightInfo for BasiliskWeight /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn one_fewer_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `3150` + // Measured: `3170` // Estimated: `42428` - // Minimum execution time: 49_932_000 picoseconds. - Weight::from_parts(51_056_000, 42428) + // Minimum execution time: 48_901_000 picoseconds. + Weight::from_parts(49_869_000, 42428) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -257,10 +251,10 @@ impl pallet_referenda::WeightInfo for BasiliskWeight /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn one_fewer_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `3150` + // Measured: `3156` // Estimated: `42428` - // Minimum execution time: 52_669_000 picoseconds. - Weight::from_parts(53_715_000, 42428) + // Minimum execution time: 51_095_000 picoseconds. + Weight::from_parts(51_859_000, 42428) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -272,8 +266,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `3011` // Estimated: `5477` - // Minimum execution time: 25_627_000 picoseconds. - Weight::from_parts(26_104_000, 5477) + // Minimum execution time: 24_444_000 picoseconds. + Weight::from_parts(24_938_000, 5477) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -285,8 +279,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `3011` // Estimated: `5477` - // Minimum execution time: 25_057_000 picoseconds. - Weight::from_parts(26_167_000, 5477) + // Minimum execution time: 24_402_000 picoseconds. + Weight::from_parts(24_926_000, 5477) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -300,8 +294,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `3015` // Estimated: `5477` - // Minimum execution time: 31_168_000 picoseconds. - Weight::from_parts(31_923_000, 5477) + // Minimum execution time: 30_887_000 picoseconds. + Weight::from_parts(31_676_000, 5477) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -315,8 +309,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `3035` // Estimated: `5477` - // Minimum execution time: 31_014_000 picoseconds. - Weight::from_parts(31_645_000, 5477) + // Minimum execution time: 30_107_000 picoseconds. + Weight::from_parts(31_025_000, 5477) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -328,8 +322,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `333` // Estimated: `42428` - // Minimum execution time: 30_590_000 picoseconds. - Weight::from_parts(31_250_000, 42428) + // Minimum execution time: 29_514_000 picoseconds. + Weight::from_parts(29_941_000, 42428) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -341,8 +335,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `381` // Estimated: `42428` - // Minimum execution time: 30_630_000 picoseconds. - Weight::from_parts(31_225_000, 42428) + // Minimum execution time: 29_982_000 picoseconds. + Weight::from_parts(30_383_000, 42428) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -352,8 +346,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `278` // Estimated: `4401` - // Minimum execution time: 20_914_000 picoseconds. - Weight::from_parts(21_246_000, 4401) + // Minimum execution time: 20_169_000 picoseconds. + Weight::from_parts(20_565_000, 4401) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -369,8 +363,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `381` // Estimated: `42428` - // Minimum execution time: 40_181_000 picoseconds. - Weight::from_parts(40_610_000, 42428) + // Minimum execution time: 39_345_000 picoseconds. + Weight::from_parts(39_652_000, 42428) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -386,8 +380,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `381` // Estimated: `42428` - // Minimum execution time: 42_057_000 picoseconds. - Weight::from_parts(42_868_000, 42428) + // Minimum execution time: 40_793_000 picoseconds. + Weight::from_parts(41_417_000, 42428) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -401,8 +395,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `434` // Estimated: `42428` - // Minimum execution time: 35_157_000 picoseconds. - Weight::from_parts(35_773_000, 42428) + // Minimum execution time: 34_251_000 picoseconds. + Weight::from_parts(34_731_000, 42428) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -416,8 +410,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `417` // Estimated: `42428` - // Minimum execution time: 35_349_000 picoseconds. - Weight::from_parts(36_006_000, 42428) + // Minimum execution time: 34_621_000 picoseconds. + Weight::from_parts(35_137_000, 42428) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -431,8 +425,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `434` // Estimated: `42428` - // Minimum execution time: 33_930_000 picoseconds. - Weight::from_parts(34_277_000, 42428) + // Minimum execution time: 32_999_000 picoseconds. + Weight::from_parts(33_606_000, 42428) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -446,8 +440,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `438` // Estimated: `42428` - // Minimum execution time: 33_081_000 picoseconds. - Weight::from_parts(33_526_000, 42428) + // Minimum execution time: 32_237_000 picoseconds. + Weight::from_parts(32_708_000, 42428) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -463,8 +457,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `438` // Estimated: `83866` - // Minimum execution time: 48_789_000 picoseconds. - Weight::from_parts(49_256_000, 83866) + // Minimum execution time: 48_296_000 picoseconds. + Weight::from_parts(48_753_000, 83866) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -478,8 +472,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `434` // Estimated: `42428` - // Minimum execution time: 34_343_000 picoseconds. - Weight::from_parts(35_226_000, 42428) + // Minimum execution time: 33_668_000 picoseconds. + Weight::from_parts(34_157_000, 42428) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -495,8 +489,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `489` // Estimated: `4401` - // Minimum execution time: 29_261_000 picoseconds. - Weight::from_parts(29_671_000, 4401) + // Minimum execution time: 28_164_000 picoseconds. + Weight::from_parts(28_387_000, 4401) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -508,8 +502,8 @@ impl pallet_referenda::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `355` // Estimated: `4401` - // Minimum execution time: 23_610_000 picoseconds. - Weight::from_parts(24_062_000, 4401) + // Minimum execution time: 22_709_000 picoseconds. + Weight::from_parts(22_901_000, 4401) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } diff --git a/runtime/basilisk/src/weights/pallet_route_executor.rs b/runtime/basilisk/src/weights/pallet_route_executor.rs index 796819bf6a9..e355be45775 100644 --- a/runtime/basilisk/src/weights/pallet_route_executor.rs +++ b/runtime/basilisk/src/weights/pallet_route_executor.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_route_executor` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-route-executor -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_route_executor.rs +// --pallet=pallet_route_executor +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -61,8 +55,8 @@ impl pallet_route_executor::WeightInfo for BasiliskWeig // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 222_000 picoseconds. - Weight::from_parts(244_000, 0) + // Minimum execution time: 368_000 picoseconds. + Weight::from_parts(448_000, 0) } /// Storage: `LBP::PoolData` (r:1 w:0) /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) @@ -78,8 +72,8 @@ impl pallet_route_executor::WeightInfo for BasiliskWeig /// Proof: `Broadcast::ExecutionContext` (`max_values`: Some(1), `max_size`: Some(593), added: 1088, mode: `MaxEncodedLen`) /// Storage: `Tokens::Locks` (r:1 w:1) /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) - /// Storage: `Broadcast::OverflowCount` (r:1 w:0) - /// Proof: `Broadcast::OverflowCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Broadcast::Swapper` (r:1 w:0) + /// Proof: `Broadcast::Swapper` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `Router::SkipEd` (r:0 w:1) /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1]`. @@ -87,10 +81,10 @@ impl pallet_route_executor::WeightInfo for BasiliskWeig // Proof Size summary in bytes: // Measured: `3066` // Estimated: `13905` - // Minimum execution time: 367_925_000 picoseconds. - Weight::from_parts(371_354_146, 13905) - // Standard Error: 306_800 - .saturating_add(Weight::from_parts(74_898_853, 0).saturating_mul(c.into())) + // Minimum execution time: 556_023_000 picoseconds. + Weight::from_parts(663_675_644, 13905) + // Standard Error: 4_915_050 + .saturating_add(Weight::from_parts(79_545_055, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(15_u64)) .saturating_add(T::DbWeight::get().writes(10_u64)) } @@ -108,8 +102,8 @@ impl pallet_route_executor::WeightInfo for BasiliskWeig /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(87), added: 2562, mode: `MaxEncodedLen`) /// Storage: `Tokens::Locks` (r:1 w:1) /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) - /// Storage: `Broadcast::OverflowCount` (r:1 w:0) - /// Proof: `Broadcast::OverflowCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Broadcast::Swapper` (r:1 w:0) + /// Proof: `Broadcast::Swapper` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `Router::SkipEd` (r:0 w:1) /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// The range of component `c` is `[1, 2]`. @@ -117,13 +111,13 @@ impl pallet_route_executor::WeightInfo for BasiliskWeig fn calculate_and_execute_buy_in_lbp(c: u32, b: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1463 + b * (1608 ±0)` - // Estimated: `6156 + b * (7749 ±7_072_116_491_613_192)` - // Minimum execution time: 101_140_000 picoseconds. - Weight::from_parts(102_000_000, 6156) - // Standard Error: 234_028 - .saturating_add(Weight::from_parts(942_788, 0).saturating_mul(c.into())) - // Standard Error: 521_247 - .saturating_add(Weight::from_parts(271_903_319, 0).saturating_mul(b.into())) + // Estimated: `6156 + b * (7749 ±1_992_139_977_073_960)` + // Minimum execution time: 132_298_000 picoseconds. + Weight::from_parts(170_600_000, 6156) + // Standard Error: 433_249 + .saturating_add(Weight::from_parts(2_759_110, 0).saturating_mul(c.into())) + // Standard Error: 964_968 + .saturating_add(Weight::from_parts(511_019_748, 0).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().reads((12_u64).saturating_mul(b.into()))) .saturating_add(T::DbWeight::get().writes((10_u64).saturating_mul(b.into()))) @@ -151,16 +145,16 @@ impl pallet_route_executor::WeightInfo for BasiliskWeig /// Proof: `MultiTransactionPayment::AcceptedCurrencies` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) /// Storage: `EmaOracle::Accumulator` (r:1 w:0) /// Proof: `EmaOracle::Accumulator` (`max_values`: Some(1), `max_size`: Some(4441), added: 4936, mode: `MaxEncodedLen`) - /// Storage: `Broadcast::OverflowCount` (r:1 w:0) - /// Proof: `Broadcast::OverflowCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Broadcast::Swapper` (r:1 w:0) + /// Proof: `Broadcast::Swapper` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `Tokens::TotalIssuance` (r:1 w:0) /// Proof: `Tokens::TotalIssuance` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) fn set_route_for_xyk() -> Weight { // Proof Size summary in bytes: // Measured: `8255` // Estimated: `39735` - // Minimum execution time: 1_794_259_000 picoseconds. - Weight::from_parts(1_799_766_000, 39735) + // Minimum execution time: 3_617_866_000 picoseconds. + Weight::from_parts(3_666_347_000, 39735) .saturating_add(T::DbWeight::get().reads(47_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -170,8 +164,8 @@ impl pallet_route_executor::WeightInfo for BasiliskWeig // Proof Size summary in bytes: // Measured: `929` // Estimated: `0` - // Minimum execution time: 30_957_000 picoseconds. - Weight::from_parts(31_456_000, 0) + // Minimum execution time: 42_849_000 picoseconds. + Weight::from_parts(72_733_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Router::Routes` (r:1 w:0) @@ -180,8 +174,8 @@ impl pallet_route_executor::WeightInfo for BasiliskWeig // Proof Size summary in bytes: // Measured: `701` // Estimated: `3555` - // Minimum execution time: 9_304_000 picoseconds. - Weight::from_parts(9_530_000, 3555) + // Minimum execution time: 15_465_000 picoseconds. + Weight::from_parts(18_128_000, 3555) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `EmaOracle::Oracles` (r:2 w:0) @@ -190,8 +184,8 @@ impl pallet_route_executor::WeightInfo for BasiliskWeig // Proof Size summary in bytes: // Measured: `1353` // Estimated: `6294` - // Minimum execution time: 33_059_000 picoseconds. - Weight::from_parts(33_926_000, 6294) + // Minimum execution time: 63_220_000 picoseconds. + Weight::from_parts(66_059_000, 6294) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: `Benchmark::Override` (r:0 w:0) @@ -213,8 +207,8 @@ impl pallet_route_executor::WeightInfo for BasiliskWeig // Proof Size summary in bytes: // Measured: `1500` // Estimated: `6156` - // Minimum execution time: 42_229_000 picoseconds. - Weight::from_parts(42_681_000, 6156) + // Minimum execution time: 74_122_000 picoseconds. + Weight::from_parts(78_158_000, 6156) .saturating_add(T::DbWeight::get().reads(4_u64)) } } \ No newline at end of file diff --git a/runtime/basilisk/src/weights/pallet_scheduler.rs b/runtime/basilisk/src/weights/pallet_scheduler.rs index de70b130226..c5791868fde 100644 --- a/runtime/basilisk/src/weights/pallet_scheduler.rs +++ b/runtime/basilisk/src/weights/pallet_scheduler.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_scheduler` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-scheduler -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_scheduler.rs +// --pallet=pallet_scheduler +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -63,8 +57,8 @@ impl pallet_scheduler::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `31` // Estimated: `1489` - // Minimum execution time: 4_471_000 picoseconds. - Weight::from_parts(4_634_000, 1489) + // Minimum execution time: 7_796_000 picoseconds. + Weight::from_parts(7_933_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -75,10 +69,10 @@ impl pallet_scheduler::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `78 + s * (177 ±0)` // Estimated: `42428` - // Minimum execution time: 5_128_000 picoseconds. - Weight::from_parts(10_376_715, 42428) - // Standard Error: 2_387 - .saturating_add(Weight::from_parts(462_037, 0).saturating_mul(s.into())) + // Minimum execution time: 5_221_000 picoseconds. + Weight::from_parts(9_864_401, 42428) + // Standard Error: 2_144 + .saturating_add(Weight::from_parts(435_223, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -86,11 +80,11 @@ impl pallet_scheduler::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_485_000 picoseconds. - Weight::from_parts(5_612_000, 0) + // Minimum execution time: 5_025_000 picoseconds. + Weight::from_parts(5_157_000, 0) } /// Storage: `Preimage::PreimageFor` (r:1 w:1) - /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) + /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `Measured`) /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) @@ -99,13 +93,14 @@ impl pallet_scheduler::WeightInfo for BasiliskWeight fn service_task_fetched(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `246 + s * (1 ±0)` - // Estimated: `4197809` - // Minimum execution time: 26_368_000 picoseconds. - Weight::from_parts(26_774_000, 3711) + // Estimated: `3711 + s * (1 ±0)` + // Minimum execution time: 24_980_000 picoseconds. + Weight::from_parts(25_263_000, 3711) // Standard Error: 15 - .saturating_add(Weight::from_parts(1_618, 0).saturating_mul(s.into())) + .saturating_add(Weight::from_parts(1_601, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 1).saturating_mul(s.into())) } /// Storage: `Scheduler::Lookup` (r:0 w:1) /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) @@ -113,30 +108,30 @@ impl pallet_scheduler::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_111_000 picoseconds. - Weight::from_parts(8_240_000, 0) + // Minimum execution time: 7_479_000 picoseconds. + Weight::from_parts(7_698_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } fn service_task_periodic() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_567_000 picoseconds. - Weight::from_parts(5_714_000, 0) + // Minimum execution time: 4_957_000 picoseconds. + Weight::from_parts(5_091_000, 0) } fn execute_dispatch_signed() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_213_000 picoseconds. - Weight::from_parts(4_306_000, 0) + // Minimum execution time: 3_837_000 picoseconds. + Weight::from_parts(3_972_000, 0) } fn execute_dispatch_unsigned() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_078_000 picoseconds. - Weight::from_parts(4_196_000, 0) + // Minimum execution time: 3_786_000 picoseconds. + Weight::from_parts(3_930_000, 0) } /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) @@ -145,10 +140,10 @@ impl pallet_scheduler::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `78 + s * (177 ±0)` // Estimated: `42428` - // Minimum execution time: 15_769_000 picoseconds. - Weight::from_parts(20_717_211, 42428) - // Standard Error: 2_213 - .saturating_add(Weight::from_parts(479_682, 0).saturating_mul(s.into())) + // Minimum execution time: 15_031_000 picoseconds. + Weight::from_parts(19_750_434, 42428) + // Standard Error: 2_080 + .saturating_add(Weight::from_parts(439_078, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -163,10 +158,10 @@ impl pallet_scheduler::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `78 + s * (177 ±0)` // Estimated: `42428` - // Minimum execution time: 24_143_000 picoseconds. - Weight::from_parts(23_652_179, 42428) - // Standard Error: 706 - .saturating_add(Weight::from_parts(726_325, 0).saturating_mul(s.into())) + // Minimum execution time: 23_456_000 picoseconds. + Weight::from_parts(23_056_631, 42428) + // Standard Error: 767 + .saturating_add(Weight::from_parts(688_086, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -179,10 +174,10 @@ impl pallet_scheduler::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `255 + s * (185 ±0)` // Estimated: `42428` - // Minimum execution time: 20_236_000 picoseconds. - Weight::from_parts(27_227_794, 42428) - // Standard Error: 3_704 - .saturating_add(Weight::from_parts(522_250, 0).saturating_mul(s.into())) + // Minimum execution time: 19_889_000 picoseconds. + Weight::from_parts(25_947_134, 42428) + // Standard Error: 3_265 + .saturating_add(Weight::from_parts(475_038, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -197,10 +192,10 @@ impl pallet_scheduler::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `281 + s * (185 ±0)` // Estimated: `42428` - // Minimum execution time: 27_183_000 picoseconds. - Weight::from_parts(27_789_032, 42428) - // Standard Error: 1_406 - .saturating_add(Weight::from_parts(759_850, 0).saturating_mul(s.into())) + // Minimum execution time: 26_357_000 picoseconds. + Weight::from_parts(26_921_064, 42428) + // Standard Error: 1_181 + .saturating_add(Weight::from_parts(720_537, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -213,10 +208,10 @@ impl pallet_scheduler::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `118` // Estimated: `42428` - // Minimum execution time: 15_207_000 picoseconds. - Weight::from_parts(15_834_098, 42428) - // Standard Error: 411 - .saturating_add(Weight::from_parts(25_858, 0).saturating_mul(s.into())) + // Minimum execution time: 14_549_000 picoseconds. + Weight::from_parts(15_049_739, 42428) + // Standard Error: 384 + .saturating_add(Weight::from_parts(22_047, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -228,8 +223,8 @@ impl pallet_scheduler::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `8928` // Estimated: `42428` - // Minimum execution time: 34_859_000 picoseconds. - Weight::from_parts(35_997_000, 42428) + // Minimum execution time: 33_684_000 picoseconds. + Weight::from_parts(34_157_000, 42428) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -243,8 +238,8 @@ impl pallet_scheduler::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `9606` // Estimated: `42428` - // Minimum execution time: 42_918_000 picoseconds. - Weight::from_parts(43_745_000, 42428) + // Minimum execution time: 41_133_000 picoseconds. + Weight::from_parts(41_514_000, 42428) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -256,8 +251,8 @@ impl pallet_scheduler::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `8940` // Estimated: `42428` - // Minimum execution time: 34_348_000 picoseconds. - Weight::from_parts(34_961_000, 42428) + // Minimum execution time: 32_985_000 picoseconds. + Weight::from_parts(33_521_000, 42428) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -271,8 +266,8 @@ impl pallet_scheduler::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `9618` // Estimated: `42428` - // Minimum execution time: 41_856_000 picoseconds. - Weight::from_parts(43_286_000, 42428) + // Minimum execution time: 39_963_000 picoseconds. + Weight::from_parts(40_605_000, 42428) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } diff --git a/runtime/basilisk/src/weights/pallet_state_trie_migration.rs b/runtime/basilisk/src/weights/pallet_state_trie_migration.rs index 416c9a15068..f2a32a6e5f7 100644 --- a/runtime/basilisk/src/weights/pallet_state_trie_migration.rs +++ b/runtime/basilisk/src/weights/pallet_state_trie_migration.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_state_trie_migration` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-state-trie-migration -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_state_trie_migration.rs +// --pallet=pallet_state_trie_migration +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -60,15 +54,15 @@ impl pallet_state_trie_migration::WeightInfo for Basili /// Storage: `StateTrieMigration::SignedMigrationMaxLimits` (r:1 w:0) /// Proof: `StateTrieMigration::SignedMigrationMaxLimits` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(139), added: 2614, mode: `MaxEncodedLen`) /// Storage: `StateTrieMigration::MigrationProcess` (r:1 w:1) /// Proof: `StateTrieMigration::MigrationProcess` (`max_values`: Some(1), `max_size`: Some(1042), added: 1537, mode: `MaxEncodedLen`) fn continue_migrate() -> Weight { // Proof Size summary in bytes: // Measured: `141` - // Estimated: `3550` - // Minimum execution time: 27_524_000 picoseconds. - Weight::from_parts(27_862_000, 3550) + // Estimated: `3604` + // Minimum execution time: 25_980_000 picoseconds. + Weight::from_parts(26_582_000, 3604) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -78,53 +72,53 @@ impl pallet_state_trie_migration::WeightInfo for Basili // Proof Size summary in bytes: // Measured: `109` // Estimated: `1493` - // Minimum execution time: 8_320_000 picoseconds. - Weight::from_parts(8_514_000, 1493) + // Minimum execution time: 7_524_000 picoseconds. + Weight::from_parts(7_720_000, 1493) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(139), added: 2614, mode: `MaxEncodedLen`) fn migrate_custom_top_success() -> Weight { // Proof Size summary in bytes: // Measured: `0` - // Estimated: `3550` - // Minimum execution time: 16_464_000 picoseconds. - Weight::from_parts(16_754_000, 3550) + // Estimated: `3604` + // Minimum execution time: 16_287_000 picoseconds. + Weight::from_parts(16_589_000, 3604) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(139), added: 2614, mode: `MaxEncodedLen`) /// Storage: UNKNOWN KEY `0x666f6f` (r:1 w:1) /// Proof: UNKNOWN KEY `0x666f6f` (r:1 w:1) fn migrate_custom_top_fail() -> Weight { // Proof Size summary in bytes: // Measured: `146` // Estimated: `3611` - // Minimum execution time: 79_915_000 picoseconds. - Weight::from_parts(80_761_000, 3611) + // Minimum execution time: 82_124_000 picoseconds. + Weight::from_parts(82_763_000, 3611) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(139), added: 2614, mode: `MaxEncodedLen`) fn migrate_custom_child_success() -> Weight { // Proof Size summary in bytes: // Measured: `0` - // Estimated: `3550` - // Minimum execution time: 16_771_000 picoseconds. - Weight::from_parts(17_063_000, 3550) + // Estimated: `3604` + // Minimum execution time: 16_688_000 picoseconds. + Weight::from_parts(17_072_000, 3604) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(139), added: 2614, mode: `MaxEncodedLen`) /// Storage: UNKNOWN KEY `0x666f6f` (r:1 w:1) /// Proof: UNKNOWN KEY `0x666f6f` (r:1 w:1) fn migrate_custom_child_fail() -> Weight { // Proof Size summary in bytes: // Measured: `106` - // Estimated: `3571` - // Minimum execution time: 81_964_000 picoseconds. - Weight::from_parts(82_489_000, 3571) + // Estimated: `3604` + // Minimum execution time: 82_038_000 picoseconds. + Weight::from_parts(82_782_000, 3604) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -135,10 +129,10 @@ impl pallet_state_trie_migration::WeightInfo for Basili // Proof Size summary in bytes: // Measured: `262 + v * (1 ±0)` // Estimated: `3727 + v * (1 ±0)` - // Minimum execution time: 8_293_000 picoseconds. - Weight::from_parts(8_525_000, 3727) - // Standard Error: 6 - .saturating_add(Weight::from_parts(1_454, 0).saturating_mul(v.into())) + // Minimum execution time: 7_800_000 picoseconds. + Weight::from_parts(8_015_000, 3727) + // Standard Error: 7 + .saturating_add(Weight::from_parts(1_517, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(v.into())) diff --git a/runtime/basilisk/src/weights/pallet_timestamp.rs b/runtime/basilisk/src/weights/pallet_timestamp.rs index acce2bec8da..4ff89ca0acc 100644 --- a/runtime/basilisk/src/weights/pallet_timestamp.rs +++ b/runtime/basilisk/src/weights/pallet_timestamp.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_timestamp` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-timestamp -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_timestamp.rs +// --pallet=pallet_timestamp +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -63,8 +57,8 @@ impl pallet_timestamp::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `76` // Estimated: `1493` - // Minimum execution time: 9_851_000 picoseconds. - Weight::from_parts(10_270_000, 1493) + // Minimum execution time: 9_486_000 picoseconds. + Weight::from_parts(9_673_000, 1493) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -72,7 +66,7 @@ impl pallet_timestamp::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `128` // Estimated: `0` - // Minimum execution time: 6_563_000 picoseconds. - Weight::from_parts(6_795_000, 0) + // Minimum execution time: 6_100_000 picoseconds. + Weight::from_parts(6_328_000, 0) } } \ No newline at end of file diff --git a/runtime/basilisk/src/weights/pallet_transaction_multi_payment.rs b/runtime/basilisk/src/weights/pallet_transaction_multi_payment.rs index b791ee13314..c94f3ae3753 100644 --- a/runtime/basilisk/src/weights/pallet_transaction_multi_payment.rs +++ b/runtime/basilisk/src/weights/pallet_transaction_multi_payment.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_transaction_multi_payment` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-transaction-multi-payment -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_transaction_multi_payment.rs +// --pallet=pallet_transaction_multi_payment +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -63,8 +57,8 @@ impl pallet_transaction_multi_payment::WeightInfo for B // Proof Size summary in bytes: // Measured: `1126` // Estimated: `3493` - // Minimum execution time: 27_334_000 picoseconds. - Weight::from_parts(27_716_000, 3493) + // Minimum execution time: 46_214_000 picoseconds. + Weight::from_parts(51_311_000, 3493) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -74,8 +68,8 @@ impl pallet_transaction_multi_payment::WeightInfo for B // Proof Size summary in bytes: // Measured: `1157` // Estimated: `3493` - // Minimum execution time: 27_175_000 picoseconds. - Weight::from_parts(27_577_000, 3493) + // Minimum execution time: 47_419_000 picoseconds. + Weight::from_parts(51_867_000, 3493) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -87,8 +81,8 @@ impl pallet_transaction_multi_payment::WeightInfo for B // Proof Size summary in bytes: // Measured: `1191` // Estimated: `3493` - // Minimum execution time: 34_833_000 picoseconds. - Weight::from_parts(35_397_000, 3493) + // Minimum execution time: 59_378_000 picoseconds. + Weight::from_parts(64_406_000, 3493) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -100,8 +94,8 @@ impl pallet_transaction_multi_payment::WeightInfo for B // Proof Size summary in bytes: // Measured: `3308` // Estimated: `27510` - // Minimum execution time: 102_307_000 picoseconds. - Weight::from_parts(104_033_000, 27510) + // Minimum execution time: 202_057_000 picoseconds. + Weight::from_parts(210_505_000, 27510) .saturating_add(T::DbWeight::get().reads(11_u64)) } /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:0 w:1) @@ -110,8 +104,8 @@ impl pallet_transaction_multi_payment::WeightInfo for B // Proof Size summary in bytes: // Measured: `929` // Estimated: `0` - // Minimum execution time: 21_850_000 picoseconds. - Weight::from_parts(22_175_000, 0) + // Minimum execution time: 39_907_000 picoseconds. + Weight::from_parts(41_459_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:1 w:0) @@ -138,6 +132,8 @@ impl pallet_transaction_multi_payment::WeightInfo for B /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `EmaOracle::Accumulator` (r:1 w:1) /// Proof: `EmaOracle::Accumulator` (`max_values`: Some(1), `max_size`: Some(4441), added: 4936, mode: `MaxEncodedLen`) + /// Storage: `Broadcast::Swapper` (r:1 w:0) + /// Proof: `Broadcast::Swapper` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `Broadcast::ExecutionContext` (r:1 w:0) /// Proof: `Broadcast::ExecutionContext` (`max_values`: Some(1), `max_size`: Some(593), added: 1088, mode: `MaxEncodedLen`) /// Storage: `Tokens::TotalIssuance` (r:1 w:1) @@ -146,9 +142,9 @@ impl pallet_transaction_multi_payment::WeightInfo for B // Proof Size summary in bytes: // Measured: `3587` // Estimated: `11322` - // Minimum execution time: 232_769_000 picoseconds. - Weight::from_parts(233_723_000, 11322) - .saturating_add(T::DbWeight::get().reads(20_u64)) + // Minimum execution time: 431_476_000 picoseconds. + Weight::from_parts(440_856_000, 11322) + .saturating_add(T::DbWeight::get().reads(21_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } } \ No newline at end of file diff --git a/runtime/basilisk/src/weights/pallet_transaction_pause.rs b/runtime/basilisk/src/weights/pallet_transaction_pause.rs index 973aa650c2a..fb7cbc7c03b 100644 --- a/runtime/basilisk/src/weights/pallet_transaction_pause.rs +++ b/runtime/basilisk/src/weights/pallet_transaction_pause.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_transaction_pause` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-transaction-pause -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_transaction_pause.rs +// --pallet=pallet_transaction_pause +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -63,8 +57,8 @@ impl pallet_transaction_pause::WeightInfo for BasiliskW // Proof Size summary in bytes: // Measured: `109` // Estimated: `3555` - // Minimum execution time: 14_882_000 picoseconds. - Weight::from_parts(15_211_000, 3555) + // Minimum execution time: 14_314_000 picoseconds. + Weight::from_parts(14_435_000, 3555) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -74,8 +68,8 @@ impl pallet_transaction_pause::WeightInfo for BasiliskW // Proof Size summary in bytes: // Measured: `160` // Estimated: `3555` - // Minimum execution time: 16_486_000 picoseconds. - Weight::from_parts(16_876_000, 3555) + // Minimum execution time: 15_758_000 picoseconds. + Weight::from_parts(16_133_000, 3555) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } diff --git a/runtime/basilisk/src/weights/pallet_transaction_payment.rs b/runtime/basilisk/src/weights/pallet_transaction_payment.rs new file mode 100644 index 00000000000..f300350b813 --- /dev/null +++ b/runtime/basilisk/src/weights/pallet_transaction_payment.rs @@ -0,0 +1,69 @@ +// This file is part of Basilisk. + +// Copyright (C) 2020-2023 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +//! Autogenerated weights for `pallet_transaction_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` + +// Executed Command: +// ./target/release/basilisk +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --wasm-execution=compiled +// --heap-pages=4096 +// --template=scripts/pallet-weight-template.hbs +// --pallet=pallet_transaction_payment +// --output=weights.rs +// --extrinsic=* + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weights for `pallet_transaction_payment`. +pub struct WeightInfo(PhantomData); + +/// Weights for `pallet_transaction_payment` using the Basilisk node and recommended hardware. +pub struct BasiliskWeight(PhantomData); +impl pallet_transaction_payment::WeightInfo for BasiliskWeight { + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn charge_transaction_payment() -> Weight { + // Proof Size summary in bytes: + // Measured: `252` + // Estimated: `3593` + // Minimum execution time: 123_366_000 picoseconds. + Weight::from_parts(126_114_000, 3593) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +} \ No newline at end of file diff --git a/runtime/basilisk/src/weights/pallet_treasury.rs b/runtime/basilisk/src/weights/pallet_treasury.rs index 573366847bc..ec4dda7ec08 100644 --- a/runtime/basilisk/src/weights/pallet_treasury.rs +++ b/runtime/basilisk/src/weights/pallet_treasury.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_treasury` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-treasury -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_treasury.rs +// --pallet=pallet_treasury +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -67,8 +61,8 @@ impl pallet_treasury::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `109` // Estimated: `1887` - // Minimum execution time: 18_081_000 picoseconds. - Weight::from_parts(18_554_000, 1887) + // Minimum execution time: 17_615_000 picoseconds. + Weight::from_parts(17_908_000, 1887) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -78,8 +72,8 @@ impl pallet_treasury::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `194` // Estimated: `1887` - // Minimum execution time: 10_851_000 picoseconds. - Weight::from_parts(11_159_000, 1887) + // Minimum execution time: 9_946_000 picoseconds. + Weight::from_parts(10_228_000, 1887) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -87,26 +81,19 @@ impl pallet_treasury::WeightInfo for BasiliskWeight /// Proof: `Treasury::Deactivated` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Balances::InactiveIssuance` (r:1 w:1) /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Approvals` (r:1 w:1) - /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Proposals` (r:99 w:99) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:99 w:99) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Treasury::LastSpendPeriod` (r:1 w:1) + /// Proof: `Treasury::LastSpendPeriod` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// The range of component `p` is `[0, 99]`. fn on_initialize_proposals(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `168 + p * (156 ±0)` - // Estimated: `1887 + p * (2603 ±0)` - // Minimum execution time: 24_306_000 picoseconds. - Weight::from_parts(33_432_365, 1887) - // Standard Error: 12_190 - .saturating_add(Weight::from_parts(25_123_666, 0).saturating_mul(p.into())) + // Measured: `203` + // Estimated: `1501` + // Minimum execution time: 15_323_000 picoseconds. + Weight::from_parts(17_876_636, 1501) + // Standard Error: 746 + .saturating_add(Weight::from_parts(10_257, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(p.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) - .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(p.into()))) - .saturating_add(Weight::from_parts(0, 2603).saturating_mul(p.into())) } /// Storage: `Treasury::SpendCount` (r:1 w:1) /// Proof: `Treasury::SpendCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -116,8 +103,8 @@ impl pallet_treasury::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `109` // Estimated: `1489` - // Minimum execution time: 16_668_000 picoseconds. - Weight::from_parts(16_909_000, 1489) + // Minimum execution time: 15_677_000 picoseconds. + Weight::from_parts(15_906_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -129,8 +116,8 @@ impl pallet_treasury::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `279` // Estimated: `3593` - // Minimum execution time: 65_431_000 picoseconds. - Weight::from_parts(65_771_000, 3593) + // Minimum execution time: 63_204_000 picoseconds. + Weight::from_parts(63_683_000, 3593) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -140,8 +127,8 @@ impl pallet_treasury::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `227` // Estimated: `3534` - // Minimum execution time: 19_020_000 picoseconds. - Weight::from_parts(19_325_000, 3534) + // Minimum execution time: 17_595_000 picoseconds. + Weight::from_parts(17_980_000, 3534) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -151,8 +138,8 @@ impl pallet_treasury::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `227` // Estimated: `3534` - // Minimum execution time: 17_440_000 picoseconds. - Weight::from_parts(17_683_000, 3534) + // Minimum execution time: 15_978_000 picoseconds. + Weight::from_parts(16_379_000, 3534) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } diff --git a/runtime/basilisk/src/weights/pallet_utility.rs b/runtime/basilisk/src/weights/pallet_utility.rs index 6852a05bfbe..3c9a5d41cc6 100644 --- a/runtime/basilisk/src/weights/pallet_utility.rs +++ b/runtime/basilisk/src/weights/pallet_utility.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_utility` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-utility -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_utility.rs +// --pallet=pallet_utility +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -61,68 +55,76 @@ impl pallet_utility::WeightInfo for BasiliskWeight { /// Proof: `Broadcast::IncrementalId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Broadcast::ExecutionContext` (r:1 w:1) /// Proof: `Broadcast::ExecutionContext` (`max_values`: Some(1), `max_size`: Some(593), added: 1088, mode: `MaxEncodedLen`) - /// Storage: `Broadcast::OverflowCount` (r:1 w:0) - /// Proof: `Broadcast::OverflowCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn batch(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `2078` - // Minimum execution time: 16_617_000 picoseconds. - Weight::from_parts(12_155_245, 2078) - // Standard Error: 3_738 - .saturating_add(Weight::from_parts(4_229_511, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(3_u64)) + // Minimum execution time: 15_536_000 picoseconds. + Weight::from_parts(18_131_709, 2078) + // Standard Error: 1_683 + .saturating_add(Weight::from_parts(3_390_243, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } fn as_derivative() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_268_000 picoseconds. - Weight::from_parts(7_422_000, 0) + // Minimum execution time: 6_884_000 picoseconds. + Weight::from_parts(7_053_000, 0) } /// Storage: `Broadcast::IncrementalId` (r:1 w:1) /// Proof: `Broadcast::IncrementalId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Broadcast::ExecutionContext` (r:1 w:1) /// Proof: `Broadcast::ExecutionContext` (`max_values`: Some(1), `max_size`: Some(593), added: 1088, mode: `MaxEncodedLen`) - /// Storage: `Broadcast::OverflowCount` (r:1 w:0) - /// Proof: `Broadcast::OverflowCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn batch_all(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `2078` - // Minimum execution time: 16_750_000 picoseconds. - Weight::from_parts(13_675_402, 2078) - // Standard Error: 3_471 - .saturating_add(Weight::from_parts(4_532_441, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(3_u64)) + // Minimum execution time: 15_370_000 picoseconds. + Weight::from_parts(15_545_628, 2078) + // Standard Error: 1_474 + .saturating_add(Weight::from_parts(3_685_913, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } fn dispatch_as() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 10_403_000 picoseconds. - Weight::from_parts(10_850_000, 0) + // Minimum execution time: 10_194_000 picoseconds. + Weight::from_parts(10_430_000, 0) } /// Storage: `Broadcast::IncrementalId` (r:1 w:1) /// Proof: `Broadcast::IncrementalId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Broadcast::ExecutionContext` (r:1 w:1) /// Proof: `Broadcast::ExecutionContext` (`max_values`: Some(1), `max_size`: Some(593), added: 1088, mode: `MaxEncodedLen`) - /// Storage: `Broadcast::OverflowCount` (r:1 w:0) - /// Proof: `Broadcast::OverflowCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn force_batch(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `2078` - // Minimum execution time: 16_575_000 picoseconds. - Weight::from_parts(12_368_786, 2078) - // Standard Error: 3_992 - .saturating_add(Weight::from_parts(4_238_614, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(3_u64)) + // Minimum execution time: 15_434_000 picoseconds. + Weight::from_parts(13_046_194, 2078) + // Standard Error: 1_753 + .saturating_add(Weight::from_parts(3_400_481, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } + fn dispatch_as_fallible() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 10_097_000 picoseconds. + Weight::from_parts(10_422_000, 0) + } + fn if_else() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 12_069_000 picoseconds. + Weight::from_parts(12_427_000, 0) + } } \ No newline at end of file diff --git a/runtime/basilisk/src/weights/pallet_whitelist.rs b/runtime/basilisk/src/weights/pallet_whitelist.rs index d23c4e1e32d..a1e9fb36b14 100644 --- a/runtime/basilisk/src/weights/pallet_whitelist.rs +++ b/runtime/basilisk/src/weights/pallet_whitelist.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_whitelist` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-whitelist -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_whitelist.rs +// --pallet=pallet_whitelist +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -67,8 +61,8 @@ impl pallet_whitelist::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `185` // Estimated: `3556` - // Minimum execution time: 27_441_000 picoseconds. - Weight::from_parts(28_067_000, 3556) + // Minimum execution time: 26_813_000 picoseconds. + Weight::from_parts(27_224_000, 3556) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -82,8 +76,8 @@ impl pallet_whitelist::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `314` // Estimated: `3556` - // Minimum execution time: 26_571_000 picoseconds. - Weight::from_parts(27_300_000, 3556) + // Minimum execution time: 25_695_000 picoseconds. + Weight::from_parts(26_183_000, 3556) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -100,10 +94,10 @@ impl pallet_whitelist::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `390 + n * (1 ±0)` // Estimated: `3854 + n * (1 ±0)` - // Minimum execution time: 42_073_000 picoseconds. - Weight::from_parts(42_359_000, 3854) - // Standard Error: 15 - .saturating_add(Weight::from_parts(1_668, 0).saturating_mul(n.into())) + // Minimum execution time: 40_210_000 picoseconds. + Weight::from_parts(40_680_000, 3854) + // Standard Error: 19 + .saturating_add(Weight::from_parts(1_681, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -119,10 +113,10 @@ impl pallet_whitelist::WeightInfo for BasiliskWeight // Proof Size summary in bytes: // Measured: `314` // Estimated: `3556` - // Minimum execution time: 33_082_000 picoseconds. - Weight::from_parts(33_363_979, 3556) + // Minimum execution time: 30_964_000 picoseconds. + Weight::from_parts(31_550_068, 3556) // Standard Error: 2 - .saturating_add(Weight::from_parts(1_304, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_138, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } diff --git a/runtime/basilisk/src/weights/pallet_xcm.rs b/runtime/basilisk/src/weights/pallet_xcm.rs index 3892bbae7fa..c0fc81ae529 100644 --- a/runtime/basilisk/src/weights/pallet_xcm.rs +++ b/runtime/basilisk/src/weights/pallet_xcm.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_xcm` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-xcm -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_xcm.rs +// --pallet=pallet_xcm +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -71,8 +65,8 @@ impl pallet_xcm::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `178` // Estimated: `3643` - // Minimum execution time: 32_621_000 picoseconds. - Weight::from_parts(33_266_000, 3643) + // Minimum execution time: 35_280_000 picoseconds. + Weight::from_parts(35_866_000, 3643) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -107,8 +101,8 @@ impl pallet_xcm::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `503` // Estimated: `3968` - // Minimum execution time: 129_849_000 picoseconds. - Weight::from_parts(130_557_000, 3968) + // Minimum execution time: 129_106_000 picoseconds. + Weight::from_parts(130_328_000, 3968) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -134,8 +128,8 @@ impl pallet_xcm::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `503` // Estimated: `3968` - // Minimum execution time: 121_493_000 picoseconds. - Weight::from_parts(122_490_000, 3968) + // Minimum execution time: 122_766_000 picoseconds. + Weight::from_parts(123_826_000, 3968) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -145,8 +139,8 @@ impl pallet_xcm::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `69` // Estimated: `1554` - // Minimum execution time: 17_712_000 picoseconds. - Weight::from_parts(17_991_000, 1554) + // Minimum execution time: 16_613_000 picoseconds. + Weight::from_parts(16_976_000, 1554) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) @@ -155,8 +149,8 @@ impl pallet_xcm::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 11_428_000 picoseconds. - Weight::from_parts(11_668_000, 0) + // Minimum execution time: 11_226_000 picoseconds. + Weight::from_parts(11_641_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `PolkadotXcm::SafeXcmVersion` (r:0 w:1) @@ -165,8 +159,8 @@ impl pallet_xcm::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_134_000 picoseconds. - Weight::from_parts(4_259_000, 0) + // Minimum execution time: 4_100_000 picoseconds. + Weight::from_parts(4_262_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `PolkadotXcm::VersionNotifiers` (r:1 w:1) @@ -189,8 +183,8 @@ impl pallet_xcm::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `178` // Estimated: `3643` - // Minimum execution time: 40_601_000 picoseconds. - Weight::from_parts(41_123_000, 3643) + // Minimum execution time: 39_984_000 picoseconds. + Weight::from_parts(40_716_000, 3643) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -212,8 +206,8 @@ impl pallet_xcm::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `361` // Estimated: `3826` - // Minimum execution time: 42_471_000 picoseconds. - Weight::from_parts(43_152_000, 3826) + // Minimum execution time: 41_206_000 picoseconds. + Weight::from_parts(41_866_000, 3826) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -223,41 +217,41 @@ impl pallet_xcm::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_998_000 picoseconds. - Weight::from_parts(4_214_000, 0) + // Minimum execution time: 4_018_000 picoseconds. + Weight::from_parts(4_210_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `PolkadotXcm::SupportedVersion` (r:5 w:2) + /// Storage: `PolkadotXcm::SupportedVersion` (r:6 w:2) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_supported_version() -> Weight { // Proof Size summary in bytes: // Measured: `125` - // Estimated: `13490` - // Minimum execution time: 26_686_000 picoseconds. - Weight::from_parts(27_057_000, 13490) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Estimated: `15965` + // Minimum execution time: 28_838_000 picoseconds. + Weight::from_parts(29_164_000, 15965) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `PolkadotXcm::VersionNotifiers` (r:5 w:2) + /// Storage: `PolkadotXcm::VersionNotifiers` (r:6 w:2) /// Proof: `PolkadotXcm::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notifiers() -> Weight { // Proof Size summary in bytes: // Measured: `129` - // Estimated: `13494` - // Minimum execution time: 26_686_000 picoseconds. - Weight::from_parts(27_179_000, 13494) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Estimated: `15969` + // Minimum execution time: 28_796_000 picoseconds. + Weight::from_parts(29_507_000, 15969) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:6 w:0) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:7 w:0) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn already_notified_target() -> Weight { // Proof Size summary in bytes: // Measured: `178` - // Estimated: `16018` - // Minimum execution time: 28_207_000 picoseconds. - Weight::from_parts(28_543_000, 16018) - .saturating_add(T::DbWeight::get().reads(6_u64)) + // Estimated: `18493` + // Minimum execution time: 33_341_000 picoseconds. + Weight::from_parts(33_746_000, 18493) + .saturating_add(T::DbWeight::get().reads(7_u64)) } /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:2 w:1) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -275,33 +269,33 @@ impl pallet_xcm::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `245` // Estimated: `6185` - // Minimum execution time: 37_670_000 picoseconds. - Weight::from_parts(38_386_000, 6185) + // Minimum execution time: 36_481_000 picoseconds. + Weight::from_parts(37_143_000, 6185) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:0) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:0) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn notify_target_migration_fail() -> Weight { // Proof Size summary in bytes: - // Measured: `139` - // Estimated: `11029` - // Minimum execution time: 16_671_000 picoseconds. - Weight::from_parts(16_898_000, 11029) - .saturating_add(T::DbWeight::get().reads(4_u64)) + // Measured: `181` + // Estimated: `13546` + // Minimum execution time: 22_987_000 picoseconds. + Weight::from_parts(23_279_000, 13546) + .saturating_add(T::DbWeight::get().reads(5_u64)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:2) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:6 w:2) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notify_targets() -> Weight { // Proof Size summary in bytes: // Measured: `136` - // Estimated: `13501` - // Minimum execution time: 26_940_000 picoseconds. - Weight::from_parts(27_254_000, 13501) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Estimated: `15976` + // Minimum execution time: 29_719_000 picoseconds. + Weight::from_parts(30_088_000, 15976) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:2) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:6 w:2) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -316,10 +310,10 @@ impl pallet_xcm::WeightInfo for BasiliskWeight { fn migrate_and_notify_old_targets() -> Weight { // Proof Size summary in bytes: // Measured: `245` - // Estimated: `13610` - // Minimum execution time: 49_328_000 picoseconds. - Weight::from_parts(49_989_000, 13610) - .saturating_add(T::DbWeight::get().reads(10_u64)) + // Estimated: `16085` + // Minimum execution time: 51_184_000 picoseconds. + Weight::from_parts(51_980_000, 16085) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1) @@ -330,8 +324,8 @@ impl pallet_xcm::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `69` // Estimated: `1554` - // Minimum execution time: 8_401_000 picoseconds. - Weight::from_parts(8_669_000, 1554) + // Minimum execution time: 7_535_000 picoseconds. + Weight::from_parts(7_821_000, 1554) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -341,8 +335,8 @@ impl pallet_xcm::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `7706` // Estimated: `11171` - // Minimum execution time: 37_715_000 picoseconds. - Weight::from_parts(38_288_000, 11171) + // Minimum execution time: 37_817_000 picoseconds. + Weight::from_parts(38_063_000, 11171) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -358,9 +352,27 @@ impl pallet_xcm::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `415` // Estimated: `4087` - // Minimum execution time: 50_830_000 picoseconds. - Weight::from_parts(51_492_000, 4087) + // Minimum execution time: 47_548_000 picoseconds. + Weight::from_parts(48_151_000, 4087) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn add_authorized_alias() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn remove_authorized_alias() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + } } \ No newline at end of file diff --git a/runtime/basilisk/src/weights/pallet_xyk.rs b/runtime/basilisk/src/weights/pallet_xyk.rs index 6d6a7cda77d..e6be54d55f8 100644 --- a/runtime/basilisk/src/weights/pallet_xyk.rs +++ b/runtime/basilisk/src/weights/pallet_xyk.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_xyk` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-xyk -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_xyk.rs +// --pallet=pallet_xyk +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -77,8 +71,8 @@ impl pallet_xyk::WeightInfo for BasiliskWeight { /// Proof: `MultiTransactionPayment::AcceptedCurrencies` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) /// Storage: `Tokens::TotalIssuance` (r:1 w:1) /// Proof: `Tokens::TotalIssuance` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) - /// Storage: `Duster::AccountBlacklist` (r:0 w:1) - /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountWhitelist` (r:0 w:1) + /// Proof: `Duster::AccountWhitelist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `XYK::TotalLiquidity` (r:0 w:1) /// Proof: `XYK::TotalLiquidity` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `XYK::PoolAssets` (r:0 w:1) @@ -87,8 +81,8 @@ impl pallet_xyk::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `2865` // Estimated: `16488` - // Minimum execution time: 215_652_000 picoseconds. - Weight::from_parts(217_581_000, 16488) + // Minimum execution time: 372_811_000 picoseconds. + Weight::from_parts(381_854_000, 16488) .saturating_add(T::DbWeight::get().reads(19_u64)) .saturating_add(T::DbWeight::get().writes(15_u64)) } @@ -112,8 +106,8 @@ impl pallet_xyk::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `3273` // Estimated: `16488` - // Minimum execution time: 195_553_000 picoseconds. - Weight::from_parts(196_895_000, 16488) + // Minimum execution time: 325_825_000 picoseconds. + Weight::from_parts(339_133_000, 16488) .saturating_add(T::DbWeight::get().reads(15_u64)) .saturating_add(T::DbWeight::get().writes(9_u64)) } @@ -133,16 +127,16 @@ impl pallet_xyk::WeightInfo for BasiliskWeight { /// Proof: `Tokens::TotalIssuance` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) /// Storage: `EmaOracle::Accumulator` (r:1 w:1) /// Proof: `EmaOracle::Accumulator` (`max_values`: Some(1), `max_size`: Some(4441), added: 4936, mode: `MaxEncodedLen`) - /// Storage: `Duster::AccountBlacklist` (r:1 w:1) - /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountWhitelist` (r:1 w:1) + /// Proof: `Duster::AccountWhitelist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `XYK::PoolAssets` (r:0 w:1) /// Proof: `XYK::PoolAssets` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) fn remove_liquidity() -> Weight { // Proof Size summary in bytes: - // Measured: `3520` + // Measured: `3453` // Estimated: `16488` - // Minimum execution time: 234_182_000 picoseconds. - Weight::from_parts(235_624_000, 16488) + // Minimum execution time: 383_552_000 picoseconds. + Weight::from_parts(408_755_000, 16488) .saturating_add(T::DbWeight::get().reads(18_u64)) .saturating_add(T::DbWeight::get().writes(14_u64)) } @@ -158,15 +152,17 @@ impl pallet_xyk::WeightInfo for BasiliskWeight { /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `EmaOracle::Accumulator` (r:1 w:1) /// Proof: `EmaOracle::Accumulator` (`max_values`: Some(1), `max_size`: Some(4441), added: 4936, mode: `MaxEncodedLen`) + /// Storage: `Broadcast::Swapper` (r:1 w:0) + /// Proof: `Broadcast::Swapper` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `Broadcast::ExecutionContext` (r:1 w:0) /// Proof: `Broadcast::ExecutionContext` (`max_values`: Some(1), `max_size`: Some(593), added: 1088, mode: `MaxEncodedLen`) fn sell() -> Weight { // Proof Size summary in bytes: // Measured: `3169` // Estimated: `13905` - // Minimum execution time: 168_316_000 picoseconds. - Weight::from_parts(169_467_000, 13905) - .saturating_add(T::DbWeight::get().reads(13_u64)) + // Minimum execution time: 271_123_000 picoseconds. + Weight::from_parts(292_190_000, 13905) + .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } /// Storage: `XYK::ShareToken` (r:1 w:0) @@ -181,15 +177,17 @@ impl pallet_xyk::WeightInfo for BasiliskWeight { /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `EmaOracle::Accumulator` (r:1 w:1) /// Proof: `EmaOracle::Accumulator` (`max_values`: Some(1), `max_size`: Some(4441), added: 4936, mode: `MaxEncodedLen`) + /// Storage: `Broadcast::Swapper` (r:1 w:0) + /// Proof: `Broadcast::Swapper` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `Broadcast::ExecutionContext` (r:1 w:0) /// Proof: `Broadcast::ExecutionContext` (`max_values`: Some(1), `max_size`: Some(593), added: 1088, mode: `MaxEncodedLen`) fn buy() -> Weight { // Proof Size summary in bytes: // Measured: `3169` // Estimated: `13905` - // Minimum execution time: 167_211_000 picoseconds. - Weight::from_parts(169_114_000, 13905) - .saturating_add(T::DbWeight::get().reads(13_u64)) + // Minimum execution time: 281_441_000 picoseconds. + Weight::from_parts(288_409_000, 13905) + .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } /// Storage: `XYK::ShareToken` (r:1 w:0) @@ -204,22 +202,22 @@ impl pallet_xyk::WeightInfo for BasiliskWeight { /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `EmaOracle::Accumulator` (r:1 w:1) /// Proof: `EmaOracle::Accumulator` (`max_values`: Some(1), `max_size`: Some(4441), added: 4936, mode: `MaxEncodedLen`) + /// Storage: `Broadcast::Swapper` (r:1 w:0) + /// Proof: `Broadcast::Swapper` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `Broadcast::ExecutionContext` (r:1 w:0) /// Proof: `Broadcast::ExecutionContext` (`max_values`: Some(1), `max_size`: Some(593), added: 1088, mode: `MaxEncodedLen`) /// The range of component `c` is `[1, 2]`. /// The range of component `e` is `[0, 1]`. - fn router_execution_sell(c: u32, e: u32, ) -> Weight { + fn router_execution_sell(_c: u32, e: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1083 + e * (2086 ±0)` - // Estimated: `6156 + e * (7749 ±7_072_116_491_613_192)` - // Minimum execution time: 28_299_000 picoseconds. - Weight::from_parts(13_581_097, 6156) - // Standard Error: 69_491 - .saturating_add(Weight::from_parts(7_726_502, 0).saturating_mul(c.into())) - // Standard Error: 69_491 - .saturating_add(Weight::from_parts(147_392_297, 0).saturating_mul(e.into())) + // Estimated: `6156 + e * (7749 ±2_594_596_928_286_404)` + // Minimum execution time: 27_708_000 picoseconds. + Weight::from_parts(146_657_442, 6156) + // Standard Error: 2_214_449 + .saturating_add(Weight::from_parts(191_900_017, 0).saturating_mul(e.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().reads((10_u64).saturating_mul(e.into()))) + .saturating_add(T::DbWeight::get().reads((11_u64).saturating_mul(e.into()))) .saturating_add(T::DbWeight::get().writes((6_u64).saturating_mul(e.into()))) .saturating_add(Weight::from_parts(0, 7749).saturating_mul(e.into())) } @@ -235,22 +233,22 @@ impl pallet_xyk::WeightInfo for BasiliskWeight { /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `EmaOracle::Accumulator` (r:1 w:1) /// Proof: `EmaOracle::Accumulator` (`max_values`: Some(1), `max_size`: Some(4441), added: 4936, mode: `MaxEncodedLen`) + /// Storage: `Broadcast::Swapper` (r:1 w:0) + /// Proof: `Broadcast::Swapper` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `Broadcast::ExecutionContext` (r:1 w:0) /// Proof: `Broadcast::ExecutionContext` (`max_values`: Some(1), `max_size`: Some(593), added: 1088, mode: `MaxEncodedLen`) /// The range of component `c` is `[1, 3]`. /// The range of component `e` is `[0, 1]`. - fn router_execution_buy(c: u32, e: u32, ) -> Weight { + fn router_execution_buy(_c: u32, e: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1083 + e * (2086 ±0)` - // Estimated: `6156 + e * (7749 ±5_855_995_681_653_278)` - // Minimum execution time: 35_967_000 picoseconds. - Weight::from_parts(13_341_718, 6156) - // Standard Error: 22_151 - .saturating_add(Weight::from_parts(7_820_591, 0).saturating_mul(c.into())) - // Standard Error: 36_872 - .saturating_add(Weight::from_parts(147_132_254, 0).saturating_mul(e.into())) + // Estimated: `6156 + e * (7749 ±1_563_467_443_840_561)` + // Minimum execution time: 35_242_000 picoseconds. + Weight::from_parts(232_904_921, 6156) + // Standard Error: 3_469_775 + .saturating_add(Weight::from_parts(83_792_209, 0).saturating_mul(e.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().reads((10_u64).saturating_mul(e.into()))) + .saturating_add(T::DbWeight::get().reads((11_u64).saturating_mul(e.into()))) .saturating_add(T::DbWeight::get().writes((6_u64).saturating_mul(e.into()))) .saturating_add(Weight::from_parts(0, 7749).saturating_mul(e.into())) } @@ -260,8 +258,8 @@ impl pallet_xyk::WeightInfo for BasiliskWeight { // Proof Size summary in bytes: // Measured: `917` // Estimated: `6156` - // Minimum execution time: 20_904_000 picoseconds. - Weight::from_parts(21_338_000, 6156) + // Minimum execution time: 20_086_000 picoseconds. + Weight::from_parts(20_461_000, 6156) .saturating_add(T::DbWeight::get().reads(2_u64)) } } \ No newline at end of file diff --git a/runtime/basilisk/src/weights/pallet_xyk_liquidity_mining.rs b/runtime/basilisk/src/weights/pallet_xyk_liquidity_mining.rs index b994f956dbd..ce564364ea9 100644 --- a/runtime/basilisk/src/weights/pallet_xyk_liquidity_mining.rs +++ b/runtime/basilisk/src/weights/pallet_xyk_liquidity_mining.rs @@ -18,8 +18,8 @@ //! Autogenerated weights for `pallet_xyk_liquidity_mining` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 43.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 48.0.0 +//! DATE: 2025-12-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -28,20 +28,14 @@ // ./target/release/basilisk // benchmark // pallet +// --steps=50 +// --repeat=20 // --wasm-execution=compiled -// --pallet -// pallet-xyk-liquidity-mining -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// runtime/basilisk/src/weights/pallet_xyk_liquidity_mining.rs +// --pallet=pallet_xyk_liquidity_mining +// --output=weights.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -63,16 +57,16 @@ impl pallet_xyk_liquidity_mining::WeightInfo for Basili /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `XYKWarehouseLM::FarmSequencer` (r:1 w:1) /// Proof: `XYKWarehouseLM::FarmSequencer` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Duster::AccountBlacklist` (r:0 w:1) - /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountWhitelist` (r:0 w:1) + /// Proof: `Duster::AccountWhitelist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `XYKWarehouseLM::GlobalFarm` (r:0 w:1) /// Proof: `XYKWarehouseLM::GlobalFarm` (`max_values`: None, `max_size`: Some(205), added: 2680, mode: `MaxEncodedLen`) fn create_global_farm() -> Weight { // Proof Size summary in bytes: // Measured: `502` // Estimated: `6196` - // Minimum execution time: 80_519_000 picoseconds. - Weight::from_parts(81_125_000, 6196) + // Minimum execution time: 81_012_000 picoseconds. + Weight::from_parts(81_760_000, 6196) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -86,8 +80,8 @@ impl pallet_xyk_liquidity_mining::WeightInfo for Basili // Proof Size summary in bytes: // Measured: `947` // Estimated: `6196` - // Minimum execution time: 86_472_000 picoseconds. - Weight::from_parts(87_556_000, 6196) + // Minimum execution time: 86_442_000 picoseconds. + Weight::from_parts(86_902_000, 6196) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -95,14 +89,14 @@ impl pallet_xyk_liquidity_mining::WeightInfo for Basili /// Proof: `XYKWarehouseLM::GlobalFarm` (`max_values`: None, `max_size`: Some(205), added: 2680, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:2 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Duster::AccountBlacklist` (r:1 w:1) - /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountWhitelist` (r:1 w:1) + /// Proof: `Duster::AccountWhitelist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn terminate_global_farm() -> Weight { // Proof Size summary in bytes: - // Measured: `1031` + // Measured: `964` // Estimated: `6196` - // Minimum execution time: 87_201_000 picoseconds. - Weight::from_parts(87_728_000, 6196) + // Minimum execution time: 85_181_000 picoseconds. + Weight::from_parts(86_296_000, 6196) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -124,8 +118,8 @@ impl pallet_xyk_liquidity_mining::WeightInfo for Basili // Proof Size summary in bytes: // Measured: `1281` // Estimated: `6196` - // Minimum execution time: 113_907_000 picoseconds. - Weight::from_parts(114_991_000, 6196) + // Minimum execution time: 111_385_000 picoseconds. + Weight::from_parts(112_504_000, 6196) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -145,8 +139,8 @@ impl pallet_xyk_liquidity_mining::WeightInfo for Basili // Proof Size summary in bytes: // Measured: `1429` // Estimated: `6196` - // Minimum execution time: 118_534_000 picoseconds. - Weight::from_parts(119_082_000, 6196) + // Minimum execution time: 115_789_000 picoseconds. + Weight::from_parts(116_400_000, 6196) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -164,8 +158,8 @@ impl pallet_xyk_liquidity_mining::WeightInfo for Basili // Proof Size summary in bytes: // Measured: `1263` // Estimated: `6196` - // Minimum execution time: 112_313_000 picoseconds. - Weight::from_parts(113_243_000, 6196) + // Minimum execution time: 109_135_000 picoseconds. + Weight::from_parts(109_885_000, 6196) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -181,8 +175,8 @@ impl pallet_xyk_liquidity_mining::WeightInfo for Basili // Proof Size summary in bytes: // Measured: `971` // Estimated: `6196` - // Minimum execution time: 91_388_000 picoseconds. - Weight::from_parts(92_616_000, 6196) + // Minimum execution time: 90_340_000 picoseconds. + Weight::from_parts(91_408_000, 6196) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -228,8 +222,8 @@ impl pallet_xyk_liquidity_mining::WeightInfo for Basili // Proof Size summary in bytes: // Measured: `3187` // Estimated: `11402` - // Minimum execution time: 245_115_000 picoseconds. - Weight::from_parts(246_776_000, 11402) + // Minimum execution time: 239_981_000 picoseconds. + Weight::from_parts(241_107_000, 11402) .saturating_add(T::DbWeight::get().reads(22_u64)) .saturating_add(T::DbWeight::get().writes(13_u64)) } @@ -255,8 +249,8 @@ impl pallet_xyk_liquidity_mining::WeightInfo for Basili // Proof Size summary in bytes: // Measured: `2223` // Estimated: `3878` - // Minimum execution time: 88_482_000 picoseconds. - Weight::from_parts(89_903_000, 3878) + // Minimum execution time: 84_542_000 picoseconds. + Weight::from_parts(85_314_000, 3878) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -276,8 +270,8 @@ impl pallet_xyk_liquidity_mining::WeightInfo for Basili // Proof Size summary in bytes: // Measured: `2202` // Estimated: `8799` - // Minimum execution time: 162_066_000 picoseconds. - Weight::from_parts(163_841_000, 8799) + // Minimum execution time: 159_861_000 picoseconds. + Weight::from_parts(160_728_000, 8799) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -319,8 +313,8 @@ impl pallet_xyk_liquidity_mining::WeightInfo for Basili // Proof Size summary in bytes: // Measured: `2990` // Estimated: `11402` - // Minimum execution time: 340_765_000 picoseconds. - Weight::from_parts(342_256_000, 11402) + // Minimum execution time: 338_984_000 picoseconds. + Weight::from_parts(341_220_000, 11402) .saturating_add(T::DbWeight::get().reads(19_u64)) .saturating_add(T::DbWeight::get().writes(15_u64)) } @@ -340,8 +334,8 @@ impl pallet_xyk_liquidity_mining::WeightInfo for Basili // Proof Size summary in bytes: // Measured: `1537` // Estimated: `6196` - // Minimum execution time: 116_005_000 picoseconds. - Weight::from_parts(116_626_000, 6196) + // Minimum execution time: 114_674_000 picoseconds. + Weight::from_parts(115_413_000, 6196) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } diff --git a/runtime/basilisk/src/xcm.rs b/runtime/basilisk/src/xcm.rs index 5d8da2df9e3..4950f73f69a 100644 --- a/runtime/basilisk/src/xcm.rs +++ b/runtime/basilisk/src/xcm.rs @@ -20,32 +20,26 @@ use crate::governance::TreasuryAccount; use crate::origins::GeneralAdmin; use crate::system::WeightToFee; -use codec::{Decode, Encode, MaxEncodedLen}; +use basilisk_adapters::xcm_exchange::XcmAssetExchanger; +use basilisk_adapters::{MultiCurrencyTrader, ToFeeReceiver}; +use basilisk_traits::router::PoolType; +use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen}; use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; use frame_support::traits::TransformOrigin; use frame_support::{ parameter_types, sp_runtime::traits::Convert, - traits::{Contains, ContainsPair, EitherOf, Everything, Get, Nothing}, + traits::{Contains, ContainsPair, Disabled, EitherOf, Everything, Get, Nothing}, PalletId, }; use frame_system::EnsureRoot; -use hydradx_adapters::xcm_exchange::XcmAssetExchanger; -use hydradx_adapters::xcm_execute_filter::AllowTransferAndSwap; -use hydradx_adapters::{MultiCurrencyTrader, ToFeeReceiver}; -use hydradx_traits::router::PoolType; use orml_traits::{location::AbsoluteReserveProvider, parameter_type_with_key}; pub use orml_xcm_support::{DepositToAlternative, IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset}; use pallet_transaction_multi_payment::DepositAll; use pallet_xcm::XcmPassthrough; use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling}; use polkadot_parachain::primitives::{RelayChainBlockNumber, Sibling}; -use polkadot_xcm::latest::{Asset, Junctions, Location}; -use polkadot_xcm::prelude::{Fungible, InteriorLocation}; -use polkadot_xcm::v3::{ - prelude::{Here, NetworkId, Parachain}, - MultiLocation, Weight as XcmWeight, -}; +use polkadot_xcm::v5::{prelude::*, Location, Weight as XcmWeight}; use primitives::AssetId; use scale_info::TypeInfo; use sp_runtime::traits::MaybeEquivalence; @@ -59,8 +53,8 @@ use xcm_builder::{ }; use xcm_executor::{Config, XcmExecutor}; -#[derive(Debug, Default, Encode, Decode, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)] -pub struct AssetLocation(pub MultiLocation); +#[derive(Debug, Default, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +pub struct AssetLocation(pub Location); impl Into> for AssetLocation { fn into(self) -> Option { @@ -72,12 +66,11 @@ impl TryFrom for AssetLocation { type Error = (); fn try_from(value: Location) -> Result { - let loc: MultiLocation = value.try_into()?; - Ok(AssetLocation(loc)) + Ok(AssetLocation(value)) } } -pub const RELAY_CHAIN_ASSET_LOCATION: AssetLocation = AssetLocation(MultiLocation { +pub const RELAY_CHAIN_ASSET_LOCATION: AssetLocation = AssetLocation(Location { parents: 1, interior: Here, }); @@ -115,7 +108,7 @@ parameter_types! { pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); - pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); + pub Ancestry: Location = Parachain(ParachainInfo::parachain_id().into()).into(); } pub struct IsKsmFrom(PhantomData); @@ -167,7 +160,7 @@ parameter_types! { pub const BaseXcmWeight: XcmWeight = XcmWeight::from_parts(100_000_000, 0); pub const MaxInstructions: u32 = 100; pub const MaxAssetsForTransfer: usize = 2; - pub UniversalLocation: InteriorLocation = [polkadot_xcm::v4::prelude::GlobalConsensus(RelayNetwork::get().into()), polkadot_xcm::v4::prelude::Parachain(ParachainInfo::parachain_id().into())].into(); + pub UniversalLocation: InteriorLocation = [polkadot_xcm::v5::prelude::GlobalConsensus(RelayNetwork::get()), polkadot_xcm::v5::prelude::Parachain(ParachainInfo::parachain_id().into())].into(); } pub struct XcmConfig; @@ -216,6 +209,7 @@ impl Config for XcmConfig { type HrmpChannelClosingHandler = (); type HrmpChannelAcceptedHandler = (); type XcmRecorder = PolkadotXcm; + type XcmEventEmitter = (); } impl cumulus_pallet_xcm::Config for Runtime { @@ -298,7 +292,7 @@ impl pallet_xcm::Config for Runtime { type SendXcmOrigin = EnsureXcmOrigin; type XcmRouter = XcmRouter; type ExecuteXcmOrigin = EnsureXcmOrigin; - type XcmExecuteFilter = AllowTransferAndSwap; + type XcmExecuteFilter = Everything; type XcmExecutor = XcmExecutor; type XcmTeleportFilter = Nothing; type XcmReserveTransferFilter = Everything; @@ -315,6 +309,7 @@ impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); + type AuthorizedAliasConsideration = Disabled; } #[test] @@ -397,18 +392,34 @@ impl Convert> for CurrencyIdConvert { && a.contains(&polkadot_xcm::prelude::GeneralIndex(CORE_ASSET_ID.into())) && a.contains(&polkadot_xcm::prelude::Parachain(ParachainInfo::get().into())) => { + log::trace!( + target: "xcm", + "dgd match 1" + ); Some(CORE_ASSET_ID) } Junctions::X1(a) if parents == 0 && a.contains(&polkadot_xcm::prelude::GeneralIndex(CORE_ASSET_ID.into())) => { + log::trace!( + target: "xcm", + "dgd match 2" + ); Some(CORE_ASSET_ID) } _ => { let location: Option = location.try_into().ok(); if let Some(location) = location { + log::trace!( + target: "xcm", + "dgd match 3" + ); AssetRegistry::location_to_asset(location) } else { + log::trace!( + target: "xcm", + "dgd match 4" + ); None } } @@ -418,6 +429,10 @@ impl Convert> for CurrencyIdConvert { impl Convert> for CurrencyIdConvert { fn convert(asset: Asset) -> Option { + log::trace!( + target: "xcm", + "dgd5" + ); Self::convert(asset.id.0) } } diff --git a/rust-toolchain b/rust-toolchain index d129d221c27..1a13e5851de 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,5 +1,5 @@ [toolchain] -channel = "1.81.0" +channel = "1.84.1" components = [ "rustfmt", "clippy", "rust-src" ] targets = [ "wasm32-unknown-unknown" ] profile = "minimal" diff --git a/traits/Cargo.toml b/traits/Cargo.toml new file mode 100644 index 00000000000..e2368ef2986 --- /dev/null +++ b/traits/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "basilisk-traits" +version = "1.0.0" +description = "Shared traits" +authors = ["GalacticCouncil"] +edition = "2021" +license = "Apache 2.0" +repository = "https://github.com/galacticcouncil/basilisk-node" + +[dependencies] +codec = { workspace = true } +scale-info = { workspace = true } +serde = { workspace = true } +impl-trait-for-tuples = { workspace = true } +sp-arithmetic = { workspace = true } + +# Substrate dependencies +frame-support = { workspace = true } +sp-std = { workspace = true } + +hydradx-traits = { workspace = true } + +[features] +default = ["std"] +std = [ + "serde/std", + "codec/std", + "frame-support/std", + "sp-std/std", +] diff --git a/traits/src/lib.rs b/traits/src/lib.rs new file mode 100644 index 00000000000..1f81b174d6e --- /dev/null +++ b/traits/src/lib.rs @@ -0,0 +1,104 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +pub mod oracle; +pub mod router; + +use codec::{Decode, Encode}; +use frame_support::dispatch::{self}; +use frame_support::sp_runtime::{traits::Zero, DispatchError, RuntimeDebug}; +use frame_support::weights::Weight; +use serde::{Deserialize, Serialize}; + +/// Identifier for oracle data sources. +pub type Source = [u8; 8]; + +/// Handler used by AMM pools to perform some tasks when a new pool is created. +pub trait OnCreatePoolHandler { + /// Register an asset to be handled by price-oracle pallet. + /// If an asset is not registered, calling `on_trade` results in populating the price buffer in the price oracle pallet, + /// but the entries are ignored and the average price for the asset is not calculated. + fn on_create_pool(asset_a: AssetId, asset_b: AssetId) -> dispatch::DispatchResult; +} + +impl OnCreatePoolHandler for () { + fn on_create_pool(_asset_a: AssetId, _asset_b: AssetId) -> dispatch::DispatchResult { + Ok(()) + } +} + +/// Handler used by AMM pools to perform some tasks when a trade is executed. +pub trait OnTradeHandler { + /// Include a trade in the average price calculation of the price-oracle pallet. + #[allow(clippy::too_many_arguments)] + fn on_trade( + source: Source, + asset_a: AssetId, + asset_b: AssetId, + amount_a: Balance, + amount_b: Balance, + liquidity_a: Balance, + liquidity_b: Balance, + price: Price, + ) -> Result; + /// Known overhead for a trade in `on_initialize/on_finalize`. + /// Needs to be specified here if we don't want to make AMM pools tightly coupled with the price oracle pallet, otherwise we can't access the weight. + /// Add this weight to an extrinsic from which you call `on_trade`. + fn on_trade_weight() -> Weight; +} + +impl OnTradeHandler for () { + fn on_trade( + _source: Source, + _asset_a: AssetId, + _asset_b: AssetId, + _amount_a: Balance, + _amount_b: Balance, + _liquidity_a: Balance, + _liquidity_b: Balance, + _price: Price, + ) -> Result { + Ok(Weight::zero()) + } + fn on_trade_weight() -> Weight { + Weight::zero() + } +} + +/// Handler used by AMM pools to perform some tasks when liquidity changes outside of trades. +pub trait OnLiquidityChangedHandler { + /// Notify that the liquidity for a pair of assets has changed. + #[allow(clippy::too_many_arguments)] + fn on_liquidity_changed( + source: Source, + asset_a: AssetId, + asset_b: AssetId, + amount_a: Balance, + amount_b: Balance, + liquidity_a: Balance, + liquidity_b: Balance, + price: Price, + ) -> Result; + /// Known overhead for a liquidity change in `on_initialize/on_finalize`. + /// Needs to be specified here if we don't want to make AMM pools tightly coupled with the price oracle pallet, otherwise we can't access the weight. + /// Add this weight to an extrinsic from which you call `on_liquidity_changed`. + fn on_liquidity_changed_weight() -> Weight; +} + +impl OnLiquidityChangedHandler for () { + fn on_liquidity_changed( + _source: Source, + _a: AssetId, + _b: AssetId, + _amount_a: Balance, + _amount_b: Balance, + _liq_a: Balance, + _liq_b: Balance, + _price: Price, + ) -> Result { + Ok(Weight::zero()) + } + + fn on_liquidity_changed_weight() -> Weight { + Weight::zero() + } +} diff --git a/traits/src/oracle.rs b/traits/src/oracle.rs new file mode 100644 index 00000000000..a0acc6f78c6 --- /dev/null +++ b/traits/src/oracle.rs @@ -0,0 +1,325 @@ +use super::*; + +use crate::router::Trade; +use codec::MaxEncodedLen; +use frame_support::sp_runtime::traits::{AtLeast32BitUnsigned, One}; +use scale_info::TypeInfo; + +/// Implementers of this trait provide the price of a given asset compared to the native currency. +/// +/// So if `100` native tokens correspond to `200` ABC tokens, the price returned would be `2.0`. +/// +/// Should return `None` if no price is available. +pub trait NativePriceOracle { + fn price(currency: AssetId) -> Option; +} + +impl NativePriceOracle for () { + fn price(_currency: AssetId) -> Option { + None + } +} + +/// Implementers of this trait provide the price for an arbitrary asset pair. +/// +/// Should return `None` if no price is available. +pub trait PriceOracle { + type Price; + + fn price(route: &[Trade], period: OraclePeriod) -> Option; +} + +pub struct AlwaysPriceOfOne; +impl NativePriceOracle for AlwaysPriceOfOne +where + Price: One, +{ + fn price(_currency: AssetId) -> Option { + Some(Price::one()) + } +} + +/// Defines the different kinds of aggregation periods for oracles. +/// +/// Note: Some of the oracles are named after certain periods of time. +/// This description relies on the mapping of the enum to the internal implementation and can thus not be guaranteed. +#[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub enum OraclePeriod { + /// The oracle data is from the last block, thus unaggregated. + LastBlock, + /// The oracle data was aggregated over the last few blocks. + Short, + /// The oracle data was aggregated over the blocks of the last ten minutes. + TenMinutes, + /// The oracle data was aggregated over the blocks of the last hour. + Hour, + /// The oracle data was aggregated over the blocks of the last day. + Day, + /// The oracle data was aggregated over the blocks of the last week. + Week, +} + +impl OraclePeriod { + pub const fn all_periods() -> &'static [OraclePeriod] { + use OraclePeriod::*; + &[LastBlock, Short, TenMinutes, Hour, Day, Week] + } + + pub const fn non_immediate_periods() -> &'static [OraclePeriod] { + use OraclePeriod::*; + &[Short, TenMinutes, Hour, Day, Week] + } +} + +/// Struct to represent oracle data aggregated over a time period. Includes the age of the oracle +/// as metadata. Age is the blocks between first data and the timestamp of the most recent value. +#[derive(Encode, Decode, Eq, PartialEq, Clone, Default, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct AggregatedEntry { + pub price: Price, + pub volume: Volume, + pub liquidity: Liquidity, + pub oracle_age: BlockNumber, +} + +impl From<(Price, Volume, Liquidity, BlockNumber)> + for AggregatedEntry +{ + fn from((price, volume, liquidity, oracle_age): (Price, Volume, Liquidity, BlockNumber)) -> Self { + Self { + price, + volume, + liquidity, + oracle_age, + } + } +} + +/// Struct to represent trade volume for an asset pair. +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq, Default, TypeInfo, MaxEncodedLen)] +pub struct Volume { + pub a_in: Balance, + pub b_out: Balance, + pub a_out: Balance, + pub b_in: Balance, +} + +impl Volume +where + Balance: Copy + AtLeast32BitUnsigned, +{ + /// Constructor for volume flowing based on trades from asset a to asset b. + pub fn from_a_in_b_out(a_in: Balance, b_out: Balance) -> Self { + Self { + a_in, + b_out, + a_out: Zero::zero(), + b_in: Zero::zero(), + } + } + + /// Constructor for volume flowing based on trades from asset b to asset a. + pub fn from_a_out_b_in(a_out: Balance, b_in: Balance) -> Self { + Self { + a_in: Zero::zero(), + b_out: Zero::zero(), + a_out, + b_in, + } + } + + /// Utility function that sums the underlying values of the volumes. + pub fn saturating_add(&self, rhs: &Self) -> Self { + let Self { + a_in: r_a_in, + b_out: r_b_out, + a_out: r_a_out, + b_in: r_b_in, + } = rhs; + let Self { + a_in, + b_out, + a_out, + b_in, + } = self; + Self { + a_in: a_in.saturating_add(*r_a_in), + b_out: b_out.saturating_add(*r_b_out), + a_out: a_out.saturating_add(*r_a_out), + b_in: b_in.saturating_add(*r_b_in), + } + } + + /// Returns the cumulative volume as `(cumulative_a, cumulative_b)`. + pub fn cumulative_volume(&self) -> (Balance, Balance) { + ( + self.a_in.saturating_add(self.a_out), + (self.b_out).saturating_add(self.b_in), + ) + } + + /// Switch assets a and b, so the new `a_in` refers to old `b_in` etc. + pub fn inverted(self) -> Self { + let Self { + a_in, + b_out, + a_out, + b_in, + } = self; + Self { + a_in: b_in, + b_out: a_out, + a_out: b_out, + b_in: a_in, + } + } +} + +impl From<(Balance, Balance, Balance, Balance)> for Volume { + fn from((a_in, b_out, a_out, b_in): (Balance, Balance, Balance, Balance)) -> Self { + Self { + a_in, + b_out, + a_out, + b_in, + } + } +} + +impl From> for (Balance, Balance, Balance, Balance) { + fn from( + Volume { + a_in, + b_out, + a_out, + b_in, + }: Volume, + ) -> Self { + (a_in, b_out, a_out, b_in) + } +} + +/// Struct to represent pool liquidity for an asset pair. +#[derive( + RuntimeDebug, Encode, Decode, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Default, TypeInfo, MaxEncodedLen, +)] +pub struct Liquidity { + pub a: Balance, + pub b: Balance, +} + +impl Liquidity +where + Balance: Copy + AtLeast32BitUnsigned, +{ + /// Constructor for pool liquidity of assets a and b + pub const fn new(a: Balance, b: Balance) -> Self { + Self { a, b } + } + + /// Switch assets a and b, so the new `a_in` refers to old `b_in` etc. + pub fn inverted(self) -> Self { + Self { a: self.b, b: self.a } + } +} + +impl From<(Balance, Balance)> for Liquidity { + fn from((a, b): (Balance, Balance)) -> Self { + Self { a, b } + } +} + +impl From> for (Balance, Balance) { + fn from(Liquidity { a, b }: Liquidity) -> Self { + (a, b) + } +} + +/// Identifier for oracle data sources. +pub type Source = [u8; 8]; + +/// An oracle returning an entry of oracle data aggregated over `period`. +pub trait AggregatedOracle { + type Error; + fn get_entry( + asset_a: AssetId, + asset_b: AssetId, + period: OraclePeriod, + source: Source, + ) -> Result, Self::Error>; + + fn get_entry_weight() -> Weight; +} + +/// Default implementation of the oracle trait that always returns `Err`. +impl AggregatedOracle for () { + type Error = (); + + fn get_entry( + _asset_a: AssetId, + _asset_b: AssetId, + _period: OraclePeriod, + _source: Source, + ) -> Result, Self::Error> { + Err(()) + } + + fn get_entry_weight() -> Weight { + Weight::zero() + } +} + +/// An oracle returning a price aggregated over `period` with the associated oracle age (to allow +/// judging whether the oracle had a chance to settle yet). +pub trait AggregatedPriceOracle { + type Error; + fn get_price( + asset_a: AssetId, + asset_b: AssetId, + period: OraclePeriod, + source: Source, + ) -> Result<(Price, BlockNumber), Self::Error>; + + fn get_price_weight() -> Weight; +} + +/// Default implementation of the oracle trait that always returns `Err`. +impl AggregatedPriceOracle for () { + type Error = (); + + fn get_price( + _asset_a: AssetId, + _asset_b: AssetId, + _period: OraclePeriod, + _source: Source, + ) -> Result<(Price, BlockNumber), Self::Error> { + Err(()) + } + + fn get_price_weight() -> Weight { + Weight::zero() + } +} + +/// Mock implementation of the oracle trait that always returns `Price::one()` and oracle age of +/// `BlockNumber::one()`. +impl AggregatedPriceOracle for AlwaysPriceOfOne +where + Price: One, + BlockNumber: One, +{ + type Error = (); + + fn get_price( + _asset_a: AssetId, + _asset_b: AssetId, + _period: OraclePeriod, + _source: Source, + ) -> Result<(Price, BlockNumber), Self::Error> { + Ok((Price::one(), BlockNumber::one())) + } + + fn get_price_weight() -> Weight { + Weight::zero() + } +} diff --git a/traits/src/router.rs b/traits/src/router.rs new file mode 100644 index 00000000000..036e0eb3593 --- /dev/null +++ b/traits/src/router.rs @@ -0,0 +1,371 @@ +use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen}; +use frame_support::dispatch::DispatchResultWithPostInfo; +use frame_support::sp_runtime::{DispatchError, DispatchResult}; +use frame_support::weights::Weight; +use scale_info::TypeInfo; +use sp_arithmetic::FixedU128; +use sp_std::vec; +use sp_std::vec::Vec; + +pub trait RouteSpotPriceProvider { + fn spot_price_with_fee(route: &[Trade]) -> Option; +} + +#[derive( + Debug, + Encode, + Decode, + DecodeWithMemTracking, + Copy, + Clone, + PartialOrd, + PartialEq, + Eq, + Default, + TypeInfo, + MaxEncodedLen, +)] +pub struct AssetPair { + pub asset_in: AssetId, + pub asset_out: AssetId, +} + +impl AssetPair { + pub fn new(asset_in: AssetId, asset_out: AssetId) -> Self { + Self { asset_in, asset_out } + } + + /// Return ordered asset tuple (A,B) where A < B + /// Used in storage + pub fn ordered_pair(&self) -> AssetPair + where + AssetId: PartialOrd + Copy, + { + match self.is_ordered() { + true => AssetPair::new(self.asset_in, self.asset_out), + false => AssetPair::new(self.asset_out, self.asset_in), + } + } + + pub fn is_ordered(&self) -> bool + where + AssetId: PartialOrd, + { + self.asset_in <= self.asset_out + } + + pub fn to_ordered_vec(&self) -> Vec + where + AssetId: PartialOrd + Copy, + { + let pair = self.ordered_pair(); + vec![pair.asset_in, pair.asset_out] + } +} + +pub trait RouteProvider { + fn get_route(asset_pair: AssetPair) -> Vec> { + vec![Trade { + pool: PoolType::Omnipool, + asset_in: asset_pair.asset_in, + asset_out: asset_pair.asset_out, + }] + } +} + +#[derive(Encode, Decode, DecodeWithMemTracking, Clone, Copy, Debug, Eq, PartialEq, TypeInfo, MaxEncodedLen)] +pub enum PoolType { + XYK, + LBP, + Stableswap(AssetId), + Omnipool, +} + +#[derive(Debug, PartialEq, Eq)] +pub enum ExecutorError { + NotSupported, + Error(E), +} + +///A single trade for buy/sell, describing the asset pair and the pool type in which the trade is executed +#[derive(Encode, Decode, DecodeWithMemTracking, Debug, Eq, PartialEq, Copy, Clone, TypeInfo, MaxEncodedLen)] +pub struct Trade { + pub pool: PoolType, + pub asset_in: AssetId, + pub asset_out: AssetId, +} + +#[derive(Debug, PartialEq)] +pub struct AmountInAndOut { + pub amount_in: Balance, + pub amount_out: Balance, +} + +pub fn inverse_route(trades: Vec>) -> Vec> { + trades + .into_iter() + .map(|trade| Trade { + pool: trade.pool, + asset_in: trade.asset_out, + asset_out: trade.asset_in, + }) + .collect::>>() + .into_iter() + .rev() + .collect() +} + +pub trait RouterT { + fn sell( + origin: Origin, + asset_in: AssetId, + asset_out: AssetId, + amount_in: Balance, + min_amount_out: Balance, + route: Vec, + ) -> DispatchResult; + + fn sell_all( + origin: Origin, + asset_in: AssetId, + asset_out: AssetId, + min_amount_out: Balance, + route: Vec, + ) -> DispatchResult; + + fn buy( + origin: Origin, + asset_in: AssetId, + asset_out: AssetId, + amount_out: Balance, + max_amount_in: Balance, + route: Vec, + ) -> DispatchResult; + + fn calculate_sell_trade_amounts(route: &[Trade], amount_in: Balance) -> Result, DispatchError>; + + fn calculate_buy_trade_amounts(route: &[Trade], amount_out: Balance) -> Result, DispatchError>; + + fn set_route(origin: Origin, asset_pair: AssetPair, route: Vec) -> DispatchResultWithPostInfo; + + fn force_insert_route( + origin: Origin, + asset_pair: AssetPair, + route: Vec, + ) -> DispatchResultWithPostInfo; +} + +/// All AMMs used in the router are required to implement this trait. +pub trait TradeExecution { + type Error; + + fn calculate_sell( + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_in: Balance, + ) -> Result>; + + fn calculate_buy( + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_out: Balance, + ) -> Result>; + + fn execute_sell( + who: Origin, + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_in: Balance, + min_limit: Balance, + ) -> Result<(), ExecutorError>; + + fn execute_buy( + who: Origin, + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_out: Balance, + max_limit: Balance, + ) -> Result<(), ExecutorError>; + + fn get_liquidity_depth( + pool_type: PoolType, + asset_a: AssetId, + asset_b: AssetId, + ) -> Result>; + + fn calculate_spot_price_with_fee( + pool_type: PoolType, + asset_a: AssetId, + asset_b: AssetId, + ) -> Result>; +} + +#[allow(clippy::redundant_clone)] //Needed as it complains about redundant clone, but clone is needed as Origin is moved and it is not copy type. +#[impl_trait_for_tuples::impl_for_tuples(1, 5)] +impl + TradeExecution for Tuple +{ + for_tuples!( where #(Tuple: TradeExecution)*); + type Error = E; + + fn calculate_sell( + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_in: Balance, + ) -> Result> { + for_tuples!( + #( + let value = match Tuple::calculate_sell(pool_type, asset_in,asset_out,amount_in) { + Ok(result) => return Ok(result), + Err(v) if v == ExecutorError::NotSupported => v, + Err(v) => return Err(v), + }; + )* + ); + Err(value) + } + + fn calculate_buy( + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_out: Balance, + ) -> Result> { + for_tuples!( + #( + let value = match Tuple::calculate_buy(pool_type, asset_in,asset_out,amount_out) { + Ok(result) => return Ok(result), + Err(v) if v == ExecutorError::NotSupported => v, + Err(v) => return Err(v), + }; + )* + ); + Err(value) + } + + fn execute_sell( + who: Origin, + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_in: Balance, + min_limit: Balance, + ) -> Result<(), ExecutorError> { + for_tuples!( + #( + let value = match Tuple::execute_sell(who.clone(),pool_type, asset_in, asset_out, amount_in, min_limit) { + Ok(result) => return Ok(result), + Err(v) if v == ExecutorError::NotSupported => v, + Err(v) => return Err(v), + }; + )* + ); + Err(value) + } + + fn execute_buy( + who: Origin, + pool_type: PoolType, + asset_in: AssetId, + asset_out: AssetId, + amount_out: Balance, + max_limit: Balance, + ) -> Result<(), ExecutorError> { + for_tuples!( + #( + let value = match Tuple::execute_buy(who.clone(), pool_type,asset_in, asset_out, amount_out, max_limit) { + Ok(result) => return Ok(result), + Err(v) if v == ExecutorError::NotSupported => v, + Err(v) => return Err(v), + }; + )* + ); + Err(value) + } + + fn get_liquidity_depth( + pool_type: PoolType, + asset_a: AssetId, + asset_b: AssetId, + ) -> Result> { + for_tuples!( + #( + let value = match Tuple::get_liquidity_depth(pool_type,asset_a, asset_b){ + Ok(result) => return Ok(result), + Err(v) if v == ExecutorError::NotSupported => v, + Err(v) => return Err(v), + }; + )* + ); + Err(value) + } + + fn calculate_spot_price_with_fee( + pool_type: PoolType, + asset_a: AssetId, + asset_b: AssetId, + ) -> Result> { + for_tuples!( + #( + let value = match Tuple::calculate_spot_price_with_fee(pool_type, asset_a, asset_b){ + Ok(result) => return Ok(result), + Err(v) if v == ExecutorError::NotSupported => v, + Err(v) => return Err(v), + }; + )* + ); + Err(value) + } +} + +/// Provides weight info for the router. Calculates the weight of a route based on the AMMs. +pub trait AmmTradeWeights { + fn sell_weight(route: &[Trade]) -> Weight; + fn buy_weight(route: &[Trade]) -> Weight; + fn calculate_buy_trade_amounts_weight(route: &[Trade]) -> Weight; + fn sell_and_calculate_sell_trade_amounts_weight(route: &[Trade]) -> Weight; + fn buy_and_calculate_buy_trade_amounts_weight(route: &[Trade]) -> Weight; + fn set_route_weight(route: &[Trade]) -> Weight; + fn force_insert_route_weight() -> Weight; + fn get_route_weight() -> Weight; + fn calculate_spot_price_with_fee_weight(route: &[Trade]) -> Weight; +} + +impl AmmTradeWeights for () { + fn sell_weight(_route: &[Trade]) -> Weight { + Weight::zero() + } + fn buy_weight(_route: &[Trade]) -> Weight { + Weight::zero() + } + fn calculate_buy_trade_amounts_weight(_route: &[Trade]) -> Weight { + Weight::zero() + } + fn sell_and_calculate_sell_trade_amounts_weight(_route: &[Trade]) -> Weight { + Weight::zero() + } + fn buy_and_calculate_buy_trade_amounts_weight(_route: &[Trade]) -> Weight { + Weight::zero() + } + fn set_route_weight(_route: &[Trade]) -> Weight { + Weight::zero() + } + fn force_insert_route_weight() -> Weight { + Weight::zero() + } + fn get_route_weight() -> Weight { + Weight::zero() + } + fn calculate_spot_price_with_fee_weight(_route: &[Trade]) -> Weight { + Weight::zero() + } +} + +pub trait RefundEdCalculator { + fn calculate() -> Balance; +}