diff --git a/Cargo.lock b/Cargo.lock index 9382504e4..4797a89f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -967,7 +967,7 @@ dependencies = [ [[package]] name = "avail-core" version = "0.6.2" -source = "git+https://github.com/availproject/avail-core?tag=core-node-7#70458d5430a5209f14369c42ded3243fce8fa1cb" +source = "git+https://github.com/availproject/avail-core?branch=fusion-mvp#bca764109b40c7c494185689aedc689805354c0e" dependencies = [ "binary-merkle-tree", "blake2b_simd", @@ -1217,7 +1217,7 @@ dependencies = [ [[package]] name = "binary-merkle-tree" version = "13.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "hash-db 0.16.0", "log", @@ -2463,6 +2463,7 @@ dependencies = [ "pallet-balances", "pallet-collective", "pallet-election-provider-multi-phase", + "pallet-fusion", "pallet-grandpa", "pallet-identity", "pallet-im-online", @@ -3554,7 +3555,7 @@ checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" [[package]] name = "fork-tree" version = "12.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "parity-scale-codec", ] @@ -3577,7 +3578,7 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" [[package]] name = "frame-benchmarking" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-support", "frame-support-procedural", @@ -3602,7 +3603,7 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" version = "32.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "Inflector", "array-bytes 6.2.3", @@ -3650,7 +3651,7 @@ dependencies = [ [[package]] name = "frame-election-provider-solution-type" version = "13.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", @@ -3661,7 +3662,7 @@ dependencies = [ [[package]] name = "frame-election-provider-support" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-election-provider-solution-type", "frame-support", @@ -3678,7 +3679,7 @@ dependencies = [ [[package]] name = "frame-executive" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-support", "frame-system", @@ -3708,7 +3709,7 @@ dependencies = [ [[package]] name = "frame-remote-externalities" version = "0.35.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "futures", "indicatif", @@ -3730,7 +3731,7 @@ dependencies = [ [[package]] name = "frame-support" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "aquamarine", "array-bytes 6.2.3", @@ -3771,7 +3772,7 @@ dependencies = [ [[package]] name = "frame-support-procedural" version = "23.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "Inflector", "cfg-expr", @@ -3790,7 +3791,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools" version = "10.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate 3.2.0", @@ -3802,7 +3803,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" version = "11.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "proc-macro2", "quote", @@ -3871,7 +3872,7 @@ dependencies = [ [[package]] name = "frame-try-runtime" version = "0.34.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-support", "parity-scale-codec", @@ -5406,7 +5407,7 @@ dependencies = [ [[package]] name = "kate" version = "0.9.2" -source = "git+https://github.com/availproject/avail-core?tag=core-node-7#70458d5430a5209f14369c42ded3243fce8fa1cb" +source = "git+https://github.com/availproject/avail-core?branch=fusion-mvp#bca764109b40c7c494185689aedc689805354c0e" dependencies = [ "avail-core", "derive_more 0.99.18", @@ -5433,7 +5434,7 @@ dependencies = [ [[package]] name = "kate-recovery" version = "0.10.0" -source = "git+https://github.com/availproject/avail-core?tag=core-node-7#70458d5430a5209f14369c42ded3243fce8fa1cb" +source = "git+https://github.com/availproject/avail-core?branch=fusion-mvp#bca764109b40c7c494185689aedc689805354c0e" dependencies = [ "avail-core", "derive_more 0.99.18", @@ -6431,7 +6432,7 @@ dependencies = [ [[package]] name = "mmr-rpc" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -7310,7 +7311,7 @@ dependencies = [ [[package]] name = "pallet-authority-discovery" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-support", "frame-system", @@ -7326,7 +7327,7 @@ dependencies = [ [[package]] name = "pallet-authorship" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-support", "frame-system", @@ -7340,7 +7341,7 @@ dependencies = [ [[package]] name = "pallet-babe" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-benchmarking", "frame-support", @@ -7364,7 +7365,7 @@ dependencies = [ [[package]] name = "pallet-bags-list" version = "27.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "aquamarine", "docify", @@ -7386,7 +7387,7 @@ dependencies = [ [[package]] name = "pallet-balances" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "docify", "frame-benchmarking", @@ -7402,7 +7403,7 @@ dependencies = [ [[package]] name = "pallet-collective" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-benchmarking", "frame-support", @@ -7419,7 +7420,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-multi-phase" version = "27.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -7442,7 +7443,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-support-benchmarking" version = "27.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -7453,10 +7454,37 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-fusion" +version = "1.0.0" +dependencies = [ + "avail-core", + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "hex", + "hex-literal", + "log", + "pallet-authorship", + "pallet-balances", + "pallet-session", + "pallet-staking", + "pallet-staking-reward-curve", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-std", +] + [[package]] name = "pallet-grandpa" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-benchmarking", "frame-support", @@ -7479,7 +7507,7 @@ dependencies = [ [[package]] name = "pallet-identity" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "enumflags2", "frame-benchmarking", @@ -7496,7 +7524,7 @@ dependencies = [ [[package]] name = "pallet-im-online" version = "27.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-benchmarking", "frame-support", @@ -7516,7 +7544,7 @@ dependencies = [ [[package]] name = "pallet-indices" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-benchmarking", "frame-support", @@ -7550,7 +7578,7 @@ dependencies = [ [[package]] name = "pallet-mmr" version = "27.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-benchmarking", "frame-support", @@ -7568,7 +7596,7 @@ dependencies = [ [[package]] name = "pallet-multisig" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-benchmarking", "frame-support", @@ -7584,7 +7612,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools" version = "25.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-support", "frame-system", @@ -7603,7 +7631,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-runtime-api" version = "23.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "pallet-nomination-pools", "parity-scale-codec", @@ -7614,7 +7642,7 @@ dependencies = [ [[package]] name = "pallet-offences" version = "27.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-support", "frame-system", @@ -7631,7 +7659,7 @@ dependencies = [ [[package]] name = "pallet-preimage" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-benchmarking", "frame-support", @@ -7648,7 +7676,7 @@ dependencies = [ [[package]] name = "pallet-proxy" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-benchmarking", "frame-support", @@ -7663,7 +7691,7 @@ dependencies = [ [[package]] name = "pallet-scheduler" version = "29.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "docify", "frame-benchmarking", @@ -7681,7 +7709,7 @@ dependencies = [ [[package]] name = "pallet-session" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-support", "frame-system", @@ -7703,7 +7731,7 @@ dependencies = [ [[package]] name = "pallet-staking" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -7726,7 +7754,7 @@ dependencies = [ [[package]] name = "pallet-staking-reward-curve" version = "11.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", @@ -7737,7 +7765,7 @@ dependencies = [ [[package]] name = "pallet-staking-reward-fn" version = "19.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "log", "sp-arithmetic", @@ -7746,7 +7774,7 @@ dependencies = [ [[package]] name = "pallet-staking-runtime-api" version = "14.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "parity-scale-codec", "sp-api", @@ -7756,7 +7784,7 @@ dependencies = [ [[package]] name = "pallet-sudo" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "docify", "frame-benchmarking", @@ -7772,7 +7800,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" version = "27.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "docify", "frame-benchmarking", @@ -7792,7 +7820,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-support", "frame-system", @@ -7808,7 +7836,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" version = "30.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "jsonrpsee", "pallet-transaction-payment-rpc-runtime-api", @@ -7824,7 +7852,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -7836,7 +7864,7 @@ dependencies = [ [[package]] name = "pallet-treasury" version = "27.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "docify", "frame-benchmarking", @@ -7855,7 +7883,7 @@ dependencies = [ [[package]] name = "pallet-tx-pause" version = "9.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "docify", "frame-benchmarking", @@ -7873,7 +7901,7 @@ dependencies = [ [[package]] name = "pallet-utility" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-benchmarking", "frame-support", @@ -9531,7 +9559,7 @@ dependencies = [ [[package]] name = "sc-allocator" version = "23.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "log", "sp-core", @@ -9542,7 +9570,7 @@ dependencies = [ [[package]] name = "sc-authority-discovery" version = "0.34.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "futures", @@ -9597,7 +9625,7 @@ dependencies = [ [[package]] name = "sc-block-builder" version = "0.33.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "parity-scale-codec", "sp-api", @@ -9612,7 +9640,7 @@ dependencies = [ [[package]] name = "sc-chain-spec" version = "27.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "array-bytes 6.2.3", "docify", @@ -9638,7 +9666,7 @@ dependencies = [ [[package]] name = "sc-chain-spec-derive" version = "11.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", @@ -9649,7 +9677,7 @@ dependencies = [ [[package]] name = "sc-cli" version = "0.36.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "array-bytes 6.2.3", "bip39", @@ -9690,7 +9718,7 @@ dependencies = [ [[package]] name = "sc-client-api" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "fnv", "futures", @@ -9717,7 +9745,7 @@ dependencies = [ [[package]] name = "sc-client-db" version = "0.35.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "hash-db 0.16.0", "kvdb", @@ -9743,7 +9771,7 @@ dependencies = [ [[package]] name = "sc-consensus" version = "0.33.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "futures", @@ -9769,7 +9797,7 @@ dependencies = [ [[package]] name = "sc-consensus-babe" version = "0.34.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "fork-tree", @@ -9805,7 +9833,7 @@ dependencies = [ [[package]] name = "sc-consensus-babe-rpc" version = "0.34.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "futures", "jsonrpsee", @@ -9827,7 +9855,7 @@ dependencies = [ [[package]] name = "sc-consensus-epochs" version = "0.33.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "fork-tree", "parity-scale-codec", @@ -9840,7 +9868,7 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa" version = "0.19.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "ahash 0.8.11", "array-bytes 6.2.3", @@ -9883,7 +9911,7 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa-rpc" version = "0.19.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "finality-grandpa", "futures", @@ -9903,7 +9931,7 @@ dependencies = [ [[package]] name = "sc-consensus-slots" version = "0.33.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "futures", @@ -9926,7 +9954,7 @@ dependencies = [ [[package]] name = "sc-executor" version = "0.32.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", @@ -9948,7 +9976,7 @@ dependencies = [ [[package]] name = "sc-executor-common" version = "0.29.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "sc-allocator", "sp-maybe-compressed-blob", @@ -9960,7 +9988,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmtime" version = "0.29.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "anyhow", "cfg-if", @@ -9978,7 +10006,7 @@ dependencies = [ [[package]] name = "sc-informant" version = "0.33.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "ansi_term", "futures", @@ -9995,7 +10023,7 @@ dependencies = [ [[package]] name = "sc-keystore" version = "25.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "array-bytes 6.2.3", "parking_lot 0.12.3", @@ -10009,7 +10037,7 @@ dependencies = [ [[package]] name = "sc-mixnet" version = "0.4.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "array-bytes 4.2.0", "arrayvec", @@ -10038,7 +10066,7 @@ dependencies = [ [[package]] name = "sc-network" version = "0.34.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "array-bytes 6.2.3", "async-channel", @@ -10081,7 +10109,7 @@ dependencies = [ [[package]] name = "sc-network-bitswap" version = "0.33.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-channel", "cid", @@ -10101,7 +10129,7 @@ dependencies = [ [[package]] name = "sc-network-common" version = "0.33.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "bitflags 1.3.2", @@ -10118,7 +10146,7 @@ dependencies = [ [[package]] name = "sc-network-gossip" version = "0.34.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "ahash 0.8.11", "futures", @@ -10137,7 +10165,7 @@ dependencies = [ [[package]] name = "sc-network-light" version = "0.33.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "array-bytes 6.2.3", "async-channel", @@ -10158,7 +10186,7 @@ dependencies = [ [[package]] name = "sc-network-sync" version = "0.33.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "array-bytes 6.2.3", "async-channel", @@ -10195,7 +10223,7 @@ dependencies = [ [[package]] name = "sc-network-transactions" version = "0.33.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "array-bytes 6.2.3", "futures", @@ -10214,7 +10242,7 @@ dependencies = [ [[package]] name = "sc-offchain" version = "29.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "array-bytes 6.2.3", "bytes", @@ -10248,7 +10276,7 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" version = "0.17.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -10257,7 +10285,7 @@ dependencies = [ [[package]] name = "sc-rpc" version = "29.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "futures", "jsonrpsee", @@ -10289,7 +10317,7 @@ dependencies = [ [[package]] name = "sc-rpc-api" version = "0.33.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -10309,7 +10337,7 @@ dependencies = [ [[package]] name = "sc-rpc-server" version = "11.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "futures", "governor", @@ -10328,7 +10356,7 @@ dependencies = [ [[package]] name = "sc-rpc-spec-v2" version = "0.34.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "array-bytes 6.2.3", "futures", @@ -10358,7 +10386,7 @@ dependencies = [ [[package]] name = "sc-service" version = "0.35.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "directories", @@ -10421,7 +10449,7 @@ dependencies = [ [[package]] name = "sc-state-db" version = "0.30.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "log", "parity-scale-codec", @@ -10432,7 +10460,7 @@ dependencies = [ [[package]] name = "sc-storage-monitor" version = "0.16.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "clap 4.5.26", "fs4", @@ -10445,7 +10473,7 @@ dependencies = [ [[package]] name = "sc-sync-state-rpc" version = "0.34.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -10464,7 +10492,7 @@ dependencies = [ [[package]] name = "sc-sysinfo" version = "27.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "derive_more 0.99.18", "futures", @@ -10485,7 +10513,7 @@ dependencies = [ [[package]] name = "sc-telemetry" version = "15.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "chrono", "futures", @@ -10505,7 +10533,7 @@ dependencies = [ [[package]] name = "sc-tracing" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "ansi_term", "chrono", @@ -10535,7 +10563,7 @@ dependencies = [ [[package]] name = "sc-tracing-proc-macro" version = "11.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", @@ -10546,7 +10574,7 @@ dependencies = [ [[package]] name = "sc-transaction-pool" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "futures", @@ -10573,7 +10601,7 @@ dependencies = [ [[package]] name = "sc-transaction-pool-api" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "futures", @@ -10589,7 +10617,7 @@ dependencies = [ [[package]] name = "sc-utils" version = "14.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-channel", "futures", @@ -11141,7 +11169,7 @@ dependencies = [ [[package]] name = "sp-api" version = "26.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "hash-db 0.16.0", "log", @@ -11162,7 +11190,7 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" version = "15.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "Inflector", "blake2 0.10.6", @@ -11176,7 +11204,7 @@ dependencies = [ [[package]] name = "sp-application-crypto" version = "30.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "parity-scale-codec", "scale-info", @@ -11189,7 +11217,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" version = "23.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "integer-sqrt", "num-traits", @@ -11221,7 +11249,7 @@ dependencies = [ [[package]] name = "sp-authority-discovery" version = "26.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "parity-scale-codec", "scale-info", @@ -11234,7 +11262,7 @@ dependencies = [ [[package]] name = "sp-block-builder" version = "26.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "sp-api", "sp-inherents", @@ -11245,7 +11273,7 @@ dependencies = [ [[package]] name = "sp-blockchain" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "futures", "log", @@ -11263,7 +11291,7 @@ dependencies = [ [[package]] name = "sp-consensus" version = "0.32.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "futures", @@ -11278,7 +11306,7 @@ dependencies = [ [[package]] name = "sp-consensus-aura" version = "0.32.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "parity-scale-codec", @@ -11295,7 +11323,7 @@ dependencies = [ [[package]] name = "sp-consensus-babe" version = "0.32.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "parity-scale-codec", @@ -11314,7 +11342,7 @@ dependencies = [ [[package]] name = "sp-consensus-grandpa" version = "13.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "finality-grandpa", "log", @@ -11332,7 +11360,7 @@ dependencies = [ [[package]] name = "sp-consensus-slots" version = "0.32.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "parity-scale-codec", "scale-info", @@ -11344,7 +11372,7 @@ dependencies = [ [[package]] name = "sp-core" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "array-bytes 6.2.3", "bandersnatch_vrfs", @@ -11390,7 +11418,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.10.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -11411,7 +11439,7 @@ dependencies = [ [[package]] name = "sp-crypto-hashing" version = "0.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "blake2b_simd", "byteorder", @@ -11424,7 +11452,7 @@ dependencies = [ [[package]] name = "sp-crypto-hashing-proc-macro" version = "0.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "quote", "sp-crypto-hashing", @@ -11434,7 +11462,7 @@ dependencies = [ [[package]] name = "sp-database" version = "10.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "kvdb", "parking_lot 0.12.3", @@ -11443,7 +11471,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "proc-macro2", "quote", @@ -11453,7 +11481,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.25.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "environmental", "parity-scale-codec", @@ -11464,7 +11492,7 @@ dependencies = [ [[package]] name = "sp-genesis-builder" version = "0.7.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "serde_json", "sp-api", @@ -11475,7 +11503,7 @@ dependencies = [ [[package]] name = "sp-inherents" version = "26.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "impl-trait-for-tuples", @@ -11489,7 +11517,7 @@ dependencies = [ [[package]] name = "sp-io" version = "30.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "bytes", "ed25519-dalek", @@ -11514,7 +11542,7 @@ dependencies = [ [[package]] name = "sp-keyring" version = "31.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "sp-core", "sp-runtime", @@ -11524,7 +11552,7 @@ dependencies = [ [[package]] name = "sp-keystore" version = "0.34.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", @@ -11536,7 +11564,7 @@ dependencies = [ [[package]] name = "sp-maybe-compressed-blob" version = "11.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "thiserror 1.0.69", "zstd 0.12.4", @@ -11545,7 +11573,7 @@ dependencies = [ [[package]] name = "sp-metadata-ir" version = "0.6.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-metadata", "parity-scale-codec", @@ -11556,7 +11584,7 @@ dependencies = [ [[package]] name = "sp-mixnet" version = "0.4.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "parity-scale-codec", "scale-info", @@ -11568,7 +11596,7 @@ dependencies = [ [[package]] name = "sp-mmr-primitives" version = "26.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "ckb-merkle-mountain-range", "log", @@ -11586,7 +11614,7 @@ dependencies = [ [[package]] name = "sp-npos-elections" version = "26.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "parity-scale-codec", "scale-info", @@ -11600,7 +11628,7 @@ dependencies = [ [[package]] name = "sp-offchain" version = "26.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "sp-api", "sp-core", @@ -11610,7 +11638,7 @@ dependencies = [ [[package]] name = "sp-panic-handler" version = "13.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "backtrace", "lazy_static", @@ -11620,7 +11648,7 @@ dependencies = [ [[package]] name = "sp-rpc" version = "26.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "rustc-hash 1.1.0", "serde", @@ -11630,7 +11658,7 @@ dependencies = [ [[package]] name = "sp-runtime" version = "31.0.1" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "docify", "either", @@ -11654,7 +11682,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "24.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -11672,7 +11700,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "Inflector", "expander", @@ -11685,7 +11713,7 @@ dependencies = [ [[package]] name = "sp-session" version = "27.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "parity-scale-codec", "scale-info", @@ -11700,7 +11728,7 @@ dependencies = [ [[package]] name = "sp-staking" version = "26.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -11714,7 +11742,7 @@ dependencies = [ [[package]] name = "sp-state-machine" version = "0.35.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "hash-db 0.16.0", "log", @@ -11735,7 +11763,7 @@ dependencies = [ [[package]] name = "sp-statement-store" version = "10.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "aes-gcm", "curve25519-dalek 4.1.3", @@ -11760,12 +11788,12 @@ dependencies = [ [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" [[package]] name = "sp-storage" version = "19.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "impl-serde 0.4.0", "parity-scale-codec", @@ -11778,7 +11806,7 @@ dependencies = [ [[package]] name = "sp-timestamp" version = "26.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "parity-scale-codec", @@ -11791,7 +11819,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "16.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "parity-scale-codec", "sp-std", @@ -11803,7 +11831,7 @@ dependencies = [ [[package]] name = "sp-transaction-pool" version = "26.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "sp-api", "sp-runtime", @@ -11812,7 +11840,7 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" version = "26.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "parity-scale-codec", @@ -11827,7 +11855,7 @@ dependencies = [ [[package]] name = "sp-trie" version = "29.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "ahash 0.8.11", "hash-db 0.16.0", @@ -11851,7 +11879,7 @@ dependencies = [ [[package]] name = "sp-version" version = "29.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "impl-serde 0.4.0", "parity-scale-codec", @@ -11868,7 +11896,7 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" version = "13.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "parity-scale-codec", "proc-macro2", @@ -11879,7 +11907,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "20.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -11892,7 +11920,7 @@ dependencies = [ [[package]] name = "sp-weights" version = "27.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "bounded-collections", "parity-scale-codec", @@ -12559,12 +12587,12 @@ dependencies = [ [[package]] name = "substrate-build-script-utils" version = "11.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" [[package]] name = "substrate-frame-rpc-system" version = "28.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "frame-system-rpc-runtime-api", "futures", @@ -12583,7 +12611,7 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" version = "0.17.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "hyper 0.14.32", "log", @@ -12595,7 +12623,7 @@ dependencies = [ [[package]] name = "substrate-rpc-client" version = "0.33.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "jsonrpsee", @@ -12608,7 +12636,7 @@ dependencies = [ [[package]] name = "substrate-state-trie-migration-rpc" version = "27.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -12625,7 +12653,7 @@ dependencies = [ [[package]] name = "substrate-wasm-builder" version = "17.0.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "build-helper", "cargo_metadata 0.15.4", @@ -13439,7 +13467,7 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "try-runtime-cli" version = "0.38.0" -source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12#1d7cf63169779258b860de57c72f3efd4026c034" +source = "git+https://github.com/availproject/polkadot-sdk.git?branch=fusion-mvp#81366efd411ac83936383220ded36f0d8e53bc48" dependencies = [ "async-trait", "clap 4.5.26", diff --git a/Cargo.toml b/Cargo.toml index 4b9fa7d62..876961b19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ resolver = "2" members = [ "base", "pallets/dactr", + "pallets/fusion", "pallets/mandate", "pallets/system", "pallets/vector", @@ -22,15 +23,16 @@ homepage = "https://www.availproject.org/" [workspace.dependencies] -avail-core = { git = "https://github.com/availproject/avail-core", tag = "core-node-7", default-features = false, features = [ "runtime"] } -kate = { git = "https://github.com/availproject/avail-core", tag = "core-node-7", default-features = false } -kate-recovery = { git = "https://github.com/availproject/avail-core", tag = "core-node-7", default-features = false } +avail-core = { git = "https://github.com/availproject/avail-core", branch = "fusion-mvp", default-features = false, features = [ "runtime"] } +kate = { git = "https://github.com/availproject/avail-core", branch = "fusion-mvp", default-features = false } +kate-recovery = { git = "https://github.com/availproject/avail-core", branch = "fusion-mvp", default-features = false } # avail-core = { path = "../avail-core/core", default-features = false, features = [ "runtime"] } # kate = { path = "../avail-core/kate/", default-features = false } # kate-recovery = { path = "../avail-core/kate/recovery/", default-features = false} avail-base = { path = "base", default-features = false } da-control = { path = "pallets/dactr", default-features = false } +pallet-fusion = { path = "pallets/fusion", default-features = false } pallet-mandate = { path = "pallets/mandate", default-features = false } pallet-vector = { path = "pallets/vector", default-features = false } da-runtime = { path = "runtime", default-features = false } @@ -43,11 +45,10 @@ frame-system = { path = "pallets/system", default-features = false } frame-system-rpc-runtime-api = { path = "pallets/system/rpc/runtime-api", default-features = false } frame-system-benchmarking = { path = "pallets/system/benchmarking", default-features = false } - # benchmarking criterion = { version = "0.4", default-features = false } iai = "0.1.1" -iai-callgrind = "0.7.3" +iai-callgrind = "0.7.3" divan = "0.1.11" # Logging and testing @@ -66,12 +67,20 @@ async-trait = "0.1.74" rayon = "1.5.2" # Macros and code generation +codec = { package = "parity-scale-codec", version = "3", default-features = false } hex-literal = "0.3.4" static_assertions = "1.1.0" serde = { version = "1.0.197", default-features = false, features = ["derive"] } serde_json = { version = "1.0", default-features = false } -derive_more = { version = "0.99.17", default-features = false, features = ["from", "into", "display"] } -scale-info = { version = "2.5.0", default-features = false, features = ["derive","serde"] } +derive_more = { version = "0.99.17", default-features = false, features = [ + "from", + "into", + "display", +] } +scale-info = { version = "2.5.0", default-features = false, features = [ + "derive", + "serde", +] } cfg-if = "1.0" impl-trait-for-tuples = "0.2.1" docify = "0.2.6" @@ -79,17 +88,23 @@ docify = "0.2.6" # Encryptions and hashing sha2 = { version = "0.10.8", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } -ark-bn254 = { version = "0.3.0", default-features = false, features = ["curve"] } +ark-bn254 = { version = "0.3.0", default-features = false, features = [ + "curve", +] } ark-groth16 = { version = "0.3.0", default-features = false } ark-ec = "0.4.2" ark-std = { version = "0.4.0", default-features = false } -ark-serialize = { version = "0.4.0", features = ["derive"], default-features = false } +ark-serialize = { version = "0.4.0", features = [ + "derive", +], default-features = false } ark-ff = { version = "0.3.0", default-features = false } ark-snark = "0.4.0" rand = "0.8" # Misc -parity-util-mem = { version = "0.12.0", features = ["primitive-types"], default-features = false } +parity-util-mem = { version = "0.12.0", features = [ + "primitive-types", +], default-features = false } array-bytes = "6.1" trie-db = { version = "0.24.0", default-features = false } hash-db = { version = "0.15.2", default-features = false } @@ -106,7 +121,9 @@ rlp = { git = "https://github.com/paritytech/parity-common.git", tag = "rlp-v0.5 rlp-derive = "0.1.0" primitive-types = { version = "0.12.0", default-features = false } ethabi = { version = "18.0.0", default-features = false } -tiny-keccak = { version = "2.0.2", features = ["keccak"], default-features = false } +tiny-keccak = { version = "2.0.2", features = [ + "keccak", +], default-features = false } # Cli clap = { version = "4.4.17", features = ["derive"] } @@ -114,123 +131,123 @@ clap-num = "1.1.1" clap_complete = "4.0.2" # Polkadot -frame-executive = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-std = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -frame-support = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-babe = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-balances = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-timestamp = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-core = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-io = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-keyring = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-runtime = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-arithmetic = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -frame-benchmarking = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-utility = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-api = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-client-api = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-blockchain = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -frame-try-runtime = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-tracing = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-inherents = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-version = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-weights = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -api = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-storage = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-assets = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-authorship = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-asset-conversion = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-collective = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-externalities = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-runtime-interface = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -binary-merkle-tree = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-staking = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-staking = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-staking-runtime-api = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-consensus-grandpa = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-authority-discovery = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-consensus-babe = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-genesis-builder = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-transaction-pool = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-offchain = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-session = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-block-builder = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-npos-elections = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-session = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-im-online = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-grandpa = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-staking-reward-curve = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-scheduler = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-indices = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-offences = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-treasury = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-bounties = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-sudo = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-authority-discovery = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-tips = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-bags-list = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-election-provider-multi-phase = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -frame-election-provider-support = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-democracy = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-mmr = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-multisig = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-preimage = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-nomination-pools = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-nomination-pools-runtime-api = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-identity = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-proxy = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-tx-pause = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-transaction-payment = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-transaction-payment-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -pallet-staking-reward-fn = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -substrate-wasm-builder = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-cli = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-statement-store = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-executor = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-service = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-storage-monitor = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-telemetry = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-keystore = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-keystore = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-transaction-pool = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-transaction-pool-api = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-transaction-storage-proof = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-consensus-babe-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-consensus = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-consensus = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-offchain = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-consensus-grandpa-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-consensus-grandpa = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-timestamp = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-consensus-babe = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-consensus-slots = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-network = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-authority-discovery = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-chain-spec = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-client-db = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-sync-state-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-sysinfo = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-network-common = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-network-sync = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -mmr-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-rpc-api = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sc-rpc-spec-v2 = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -substrate-frame-rpc-system = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -substrate-state-trie-migration-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -frame-benchmarking-cli = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -try-runtime-cli = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -substrate-build-script-utils = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-trie = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } -sp-state-machine = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12", default-features = false } +frame-executive = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-std = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +frame-support = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-babe = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-balances = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-timestamp = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-core = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-io = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-keyring = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-runtime = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-arithmetic = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +frame-benchmarking = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-utility = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-api = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-client-api = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-blockchain = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +frame-try-runtime = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-tracing = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-inherents = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-version = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-weights = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +api = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-storage = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-assets = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-authorship = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-asset-conversion = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-collective = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-externalities = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-runtime-interface = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +binary-merkle-tree = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-staking = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-staking = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-staking-runtime-api = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-consensus-grandpa = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-authority-discovery = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-consensus-babe = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-genesis-builder = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-transaction-pool = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-offchain = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-session = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-block-builder = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-npos-elections = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-session = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-im-online = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-grandpa = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-staking-reward-curve = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-scheduler = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-indices = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-offences = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-treasury = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-bounties = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-sudo = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-authority-discovery = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-tips = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-bags-list = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-election-provider-multi-phase = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +frame-election-provider-support = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-democracy = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-mmr = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-multisig = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-preimage = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-nomination-pools = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-nomination-pools-runtime-api = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-identity = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-proxy = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-tx-pause = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-transaction-payment = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-transaction-payment-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +pallet-staking-reward-fn = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +substrate-wasm-builder = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-cli = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-statement-store = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-executor = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-service = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-storage-monitor = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-telemetry = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-keystore = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-keystore = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-transaction-pool = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-transaction-pool-api = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-transaction-storage-proof = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-consensus-babe-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-consensus = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-consensus = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-offchain = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-consensus-grandpa-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-consensus-grandpa = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-timestamp = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-consensus-babe = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-consensus-slots = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-network = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-authority-discovery = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-chain-spec = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-client-db = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-sync-state-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-sysinfo = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-network-common = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-network-sync = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +mmr-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-rpc-api = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sc-rpc-spec-v2 = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +substrate-frame-rpc-system = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +substrate-state-trie-migration-rpc = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +frame-benchmarking-cli = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +try-runtime-cli = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +substrate-build-script-utils = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-trie = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } +sp-state-machine = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp", default-features = false } -sc-block-builder = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12" } -sc-proposer-metrics = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12" } -substrate-prometheus-endpoint = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12" } -# substrate-test-runtime-client = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12" } +sc-block-builder = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp" } +sc-proposer-metrics = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp" } +substrate-prometheus-endpoint = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp" } +# substrate-test-runtime-client = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp" } # Patch from forked pallets @@ -240,7 +257,7 @@ frame-system-benchmarking = { path = "pallets/system/benchmarking" } frame-system-rpc-runtime-api = { path = "pallets/system/rpc/runtime-api" } [patch."https://github.com/paritytech/polkadot-sdk"] -sp-crypto-ec-utils = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-12" } +sp-crypto-ec-utils = { git = "https://github.com/availproject/polkadot-sdk.git", branch = "fusion-mvp" } [patch.crates-io] # Other stuff diff --git a/base/Cargo.toml b/base/Cargo.toml index 2461bfbb4..1cb4f9712 100644 --- a/base/Cargo.toml +++ b/base/Cargo.toml @@ -13,7 +13,7 @@ workspace = true avail-core = { workspace = true, default-features = false } # Substrate related -codec = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +codec = { workspace = true, default-features = false, features = ["derive"] } sp-core = { workspace = true, default-features = false, features = ["serde"] } sp-std = { workspace = true, default-features = false } sp-api = { workspace = true, default-features = false } diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index e1523cd05..e30a271bd 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] avail-base = { workspace = true, features = ["std"] } -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { workspace = true } futures.workspace = true futures-timer.workspace = true log.workspace = true diff --git a/e2e/Cargo.lock b/e2e/Cargo.lock index 990c02cec..ffbe91261 100644 --- a/e2e/Cargo.lock +++ b/e2e/Cargo.lock @@ -23,18 +23,18 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.24.2" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ - "gimli 0.31.1", + "gimli 0.28.1", ] [[package]] -name = "adler2" -version = "2.0.0" +name = "adler" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aead" @@ -83,7 +83,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom 0.2.15", + "getrandom", "once_cell", "version_check", ] @@ -95,7 +95,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom 0.2.15", + "getrandom", "once_cell", "version_check", "zerocopy", @@ -112,9 +112,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.21" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alloy-primitives" @@ -126,7 +126,7 @@ dependencies = [ "bytes", "cfg-if", "const-hex", - "derive_more 0.99.19", + "derive_more 0.99.17", "hex-literal", "itoa", "proptest", @@ -142,7 +142,7 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6c1d995bff8d011f7cd6c81820d51825e6e06d6db73914c1630ecf544d83d6" dependencies = [ - "arrayvec 0.7.6", + "arrayvec 0.7.4", "bytes", ] @@ -158,7 +158,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "syn-solidity", "tiny-keccak", ] @@ -201,9 +201,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", @@ -216,44 +216,43 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", - "once_cell", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" [[package]] name = "approx" @@ -275,7 +274,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -454,7 +453,7 @@ dependencies = [ "num-bigint", "num-traits", "paste", - "rustc_version 0.4.1", + "rustc_version 0.4.0", "zeroize", ] @@ -641,15 +640,15 @@ dependencies = [ [[package]] name = "array-bytes" -version = "6.2.3" +version = "6.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5dde061bd34119e902bbb2d9b90c5692635cf59fb91d582c2b68043f1b8293" +checksum = "6f840fb7195bcfc5e17ea40c26e5ce6d5b9ce5d584466e17703209657e459ae0" [[package]] name = "arrayref" -version = "0.3.9" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" [[package]] name = "arrayvec" @@ -662,9 +661,9 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.7.6" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "assert_matches" @@ -728,21 +727,22 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.3.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +checksum = "9f2776ead772134d55b62dd45e59a79e21612d85d0af729b8b7d3967d601a62a" dependencies = [ "concurrent-queue", - "event-listener-strategy", + "event-listener 5.3.0", + "event-listener-strategy 0.5.2", "futures-core", "pin-project-lite", ] [[package]] name = "async-executor" -version = "1.13.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +checksum = "b10202063978b3351199d68f8b22c4e47e4b1b822f8d43fd862d5ea8c006b29a" dependencies = [ "async-task", "concurrent-queue", @@ -764,9 +764,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.4.0" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" +checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" dependencies = [ "async-lock", "cfg-if", @@ -775,20 +775,20 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 0.38.44", + "rustix 0.38.34", "slab", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] name = "async-lock" -version = "3.4.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" dependencies = [ - "event-listener", - "event-listener-strategy", + "event-listener 4.0.3", + "event-listener-strategy 0.4.0", "pin-project-lite", ] @@ -805,9 +805,9 @@ dependencies = [ [[package]] name = "async-process" -version = "2.3.0" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" +checksum = "a53fc6301894e04a92cb2584fedde80cb25ba8e02d9dc39d4a87d036e22f397d" dependencies = [ "async-channel", "async-io", @@ -816,17 +816,18 @@ dependencies = [ "async-task", "blocking", "cfg-if", - "event-listener", + "event-listener 5.3.0", "futures-lite", - "rustix 0.38.44", + "rustix 0.38.34", "tracing", + "windows-sys 0.52.0", ] [[package]] name = "async-signal" -version = "0.2.10" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +checksum = "afe66191c335039c7bb78f99dc7520b0cbb166b3a1cb33a03f53d8a1c6f2afda" dependencies = [ "async-io", "async-lock", @@ -834,10 +835,10 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 0.38.44", + "rustix 0.38.34", "signal-hook-registry", "slab", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -848,13 +849,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.87" +version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -877,14 +878,14 @@ checksum = "e12882f59de5360c748c4cbf569a042d5fb0eb515f7bea9c1f470b47f6ffbd73" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] name = "autocfg" -version = "1.4.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "avail-core" @@ -894,7 +895,7 @@ dependencies = [ "binary-merkle-tree 13.0.0", "blake2b_simd", "bounded-collections", - "derive_more 0.99.19", + "derive_more 0.99.17", "ethabi-decode 2.0.0", "frame-support 28.0.0", "hash-db", @@ -929,7 +930,7 @@ dependencies = [ "base58", "bounded-collections", "derive_more 1.0.0", - "env_logger 0.11.6", + "env_logger 0.11.7", "hex", "jsonrpsee", "kate-recovery", @@ -948,17 +949,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ - "addr2line 0.24.2", + "addr2line 0.21.0", + "cc", "cfg-if", "libc", "miniz_oxide", - "object 0.36.7", + "object 0.32.2", "rustc-demangle", - "windows-targets 0.52.6", ] [[package]] @@ -1114,9 +1115,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bitvec" @@ -1152,13 +1153,13 @@ dependencies = [ [[package]] name = "blake2b_simd" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e903a20b159e944f91ec8499fe1e55651480c541ea0a584f5d967c49ad9d99" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" dependencies = [ "arrayref", - "arrayvec 0.7.6", - "constant_time_eq 0.3.1", + "arrayvec 0.7.4", + "constant_time_eq 0.3.0", ] [[package]] @@ -1181,11 +1182,12 @@ dependencies = [ [[package]] name = "blocking" -version = "1.6.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +checksum = "495f7104e962b7356f0aeb34247aca1fe7d2e783b346582db7f2904cb5717e88" dependencies = [ "async-channel", + "async-lock", "async-task", "futures-io", "futures-lite", @@ -1194,9 +1196,9 @@ dependencies = [ [[package]] name = "bounded-collections" -version = "0.2.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ed0a820ed50891d36358e997d27741a6142e382242df40ff01c89bcdcc7a2b" +checksum = "d32385ecb91a31bddaf908e8dcf4a15aef1bcd3913cc03ebfad02ff6d568abc1" dependencies = [ "log", "parity-scale-codec", @@ -1498,21 +1500,21 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byte-slice-cast" -version = "1.2.3" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytemuck" -version = "1.22.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" +checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" [[package]] name = "byteorder" @@ -1522,9 +1524,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "camino" @@ -1552,21 +1554,21 @@ checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" dependencies = [ "camino", "cargo-platform", - "semver 1.0.26", + "semver 1.0.23", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror 1.0.60", ] [[package]] name = "cc" -version = "1.2.16" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" dependencies = [ "jobserver", "libc", - "shlex", + "once_cell", ] [[package]] @@ -1603,14 +1605,14 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.40" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", - "windows-link", + "windows-targets 0.52.5", ] [[package]] @@ -1626,18 +1628,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.31" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" +checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.31" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" +checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99" dependencies = [ "anstyle", "clap_lex", @@ -1646,9 +1648,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "codespan-reporting" @@ -1657,14 +1659,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" dependencies = [ "termcolor", - "unicode-width 0.1.14", + "unicode-width", ] [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "combine" @@ -1708,15 +1710,15 @@ dependencies = [ [[package]] name = "console" -version = "0.15.11" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" dependencies = [ "encode_unicode", + "lazy_static", "libc", - "once_cell", - "unicode-width 0.2.0", - "windows-sys 0.59.0", + "unicode-width", + "windows-sys 0.52.0", ] [[package]] @@ -1753,31 +1755,11 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" dependencies = [ - "getrandom 0.2.15", + "getrandom", "once_cell", "tiny-keccak", ] -[[package]] -name = "const_format" -version = "0.2.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" -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" @@ -1786,9 +1768,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "constant_time_eq" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "constcat" @@ -1814,9 +1796,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.7" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpp_demangle" @@ -1829,9 +1811,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.17" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -1936,18 +1918,18 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-deque" -version = "0.8.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -1964,24 +1946,24 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.12" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" @@ -2132,7 +2114,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2183,9 +2165,9 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcmp-queue" -version = "0.17.1" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc44222c528b88dcc6e921e7a0dc94d66b5895aab9e9d9db8798fc62f7ccd40" +checksum = "105767016b8136031f14cca439edf28c8493e3556e6781847758511bfef2477a" dependencies = [ "bounded-collections", "bp-xcm-bridge-hub-router", @@ -2351,7 +2333,7 @@ dependencies = [ "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "rustc_version 0.4.1", + "rustc_version 0.4.0", "subtle", "zeroize", ] @@ -2364,14 +2346,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] name = "cxx" -version = "1.0.143" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "050906babad73f9b32a91cecc3063ff1e2235226dd2367dd839fd6fbc941c68a" +checksum = "342b09ea23e087717542308a865984555782302855f29427540bbe02d5e8a28a" dependencies = [ "cc", "cxxbridge-cmd", @@ -2383,47 +2365,47 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.143" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875d58f2ac56025a775b91a424515b5adf1e68205765f2c90e6dd81e269ae004" +checksum = "4f3ff8c449a5074983677c19c894eadc62b6a82ade4d6316547798eb79342ae5" dependencies = [ "cc", "codespan-reporting", "proc-macro2", "quote", "scratch", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] name = "cxxbridge-cmd" -version = "1.0.143" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19c3062da294104183e1c34ea9887941d4d8c74f6195ce9fbb430ac4b5290ede" +checksum = "40399fddbf3977647bfff7453dacffc6b5701b19a282a283369a870115d0a049" dependencies = [ "clap", "codespan-reporting", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] name = "cxxbridge-flags" -version = "1.0.143" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4b358173a166833ddef75fe468579f71727c789b8082d4cc77c38d08f656c59" +checksum = "a9161673896b799047e79a245927e7921787ad016eed6770227f3f23de2746c7" [[package]] name = "cxxbridge-macro" -version = "1.0.143" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9531217f3b5f7728244d2b7312bc6660f6b3e4cdbc118f4f1fbce48cb401a0f" +checksum = "dff513230582d396298cc00e8fb3d9a752822f85137c323fac4227ac5be6c268" dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2447,7 +2429,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2458,7 +2440,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2521,7 +2503,7 @@ checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2532,20 +2514,20 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] name = "derive_more" -version = "0.99.19" +version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case", "proc-macro2", "quote", - "rustc_version 0.4.1", - "syn 2.0.99", + "rustc_version 0.4.0", + "syn 1.0.109", ] [[package]] @@ -2565,7 +2547,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2618,7 +2600,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2633,24 +2615,24 @@ dependencies = [ "ark-serialize 0.4.2", "ark-std 0.4.0", "ark-transcript 0.0.2 (git+https://github.com/availproject/ring-vrf?tag=locked)", - "arrayvec 0.7.6", + "arrayvec 0.7.4", "zeroize", ] [[package]] name = "docify" -version = "0.2.9" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a772b62b1837c8f060432ddcc10b17aae1453ef17617a99bc07789252d2a5896" +checksum = "43a2f138ad521dc4a2ced1a4576148a6a610b4c5923933b062a263130a6802ce" dependencies = [ "docify_macros", ] [[package]] name = "docify_macros" -version = "0.2.9" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60e6be249b0a462a14784a99b19bf35a667bb5e09de611738bb7362fa4c95ff7" +checksum = "1a081e51fb188742f5a7a1164ad752121abcb22874b21e2c3b0dd040c515fdad" dependencies = [ "common-path", "derive-syn-parse 0.2.0", @@ -2658,9 +2640,9 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.99", + "syn 2.0.100", "termcolor", - "toml 0.8.20", + "toml 0.8.12", "walkdir", ] @@ -2728,9 +2710,9 @@ dependencies = [ [[package]] name = "dyn-clonable" -version = "0.9.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a36efbb9bfd58e1723780aa04b61aba95ace6a05d9ffabfdb0b43672552f0805" +checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" dependencies = [ "dyn-clonable-impl", "dyn-clone", @@ -2738,26 +2720,27 @@ dependencies = [ [[package]] name = "dyn-clonable-impl" -version = "0.9.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8671d54058979a37a26f3511fbf8d198ba1aa35ffb202c42587d918d77213a" +checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 1.0.109", ] [[package]] name = "dyn-clone" -version = "1.0.19" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "e2e" version = "0.1.0" dependencies = [ "avail-rust", + "rustls-webpki 0.102.3", "serde", "tokio", ] @@ -2818,9 +2801,9 @@ dependencies = [ [[package]] name = "either" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "elliptic-curve" @@ -2844,9 +2827,9 @@ dependencies = [ [[package]] name = "encode_unicode" -version = "1.0.0" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "enumflags2" @@ -2865,7 +2848,7 @@ checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2876,14 +2859,14 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] name = "env_filter" -version = "0.1.3" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" dependencies = [ "log", "regex", @@ -2904,14 +2887,14 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" +checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" dependencies = [ "anstream", "anstyle", "env_filter", - "humantime", + "jiff", "log", ] @@ -2923,18 +2906,18 @@ checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" [[package]] name = "equivalent" -version = "1.0.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -3012,9 +2995,20 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.4.0" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24" dependencies = [ "concurrent-queue", "parking", @@ -3023,27 +3017,36 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.3" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +dependencies = [ + "event-listener 4.0.3", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener", + "event-listener 5.3.0", "pin-project-lite", ] [[package]] name = "expander" -version = "2.2.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2c470c71d91ecbd179935b24170459e926382eaaa86b590b78814e180d8a8e2" +checksum = "00e83c02035136f1592a47964ea60c05a50e4ed8b5892cfac197063850898d4d" dependencies = [ "blake2", - "file-guard", "fs-err", - "prettyplease", + "prettier-please", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3060,9 +3063,9 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fastrand" -version = "2.3.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fastrlp" @@ -3070,7 +3073,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" dependencies = [ - "arrayvec 0.7.6", + "arrayvec 0.7.4", "auto_impl", "bytes", ] @@ -3081,7 +3084,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" dependencies = [ - "arrayvec 0.7.6", + "arrayvec 0.7.4", "auto_impl", "bytes", ] @@ -3115,16 +3118,6 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" -[[package]] -name = "file-guard" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ef72acf95ec3d7dbf61275be556299490a245f017cf084bd23b4f68cf9407c" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "file-per-thread-logger" version = "0.1.6" @@ -3137,14 +3130,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.25" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", - "libredox", - "windows-sys 0.59.0", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", ] [[package]] @@ -3193,9 +3186,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "form_urlencoded" @@ -3269,7 +3262,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3447,7 +3440,7 @@ dependencies = [ "proc-macro2", "quote", "sp-crypto-hashing 0.0.0", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3468,7 +3461,7 @@ dependencies = [ "proc-macro2", "quote", "sp-crypto-hashing 0.1.0", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3480,7 +3473,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3493,7 +3486,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3503,7 +3496,7 @@ source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7. dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3514,7 +3507,7 @@ checksum = "ed971c6435503a099bdac99fe4c5bea08981709e5b5a0a8535a1856f48561191" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3642,9 +3635,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.6.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ "fastrand", "futures-core", @@ -3661,7 +3654,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3728,19 +3721,7 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets 0.52.6", + "wasi", ] [[package]] @@ -3784,12 +3765,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "group" version = "0.13.0" @@ -3813,7 +3788,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.7.1", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -3873,17 +3848,6 @@ dependencies = [ "serde", ] -[[package]] -name = "hashbrown" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", -] - [[package]] name = "heck" version = "0.4.1" @@ -3904,9 +3868,9 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hermit-abi" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" [[package]] name = "hex" @@ -3929,7 +3893,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" dependencies = [ - "arrayvec 0.7.6", + "arrayvec 0.7.4", ] [[package]] @@ -3989,9 +3953,9 @@ dependencies = [ [[package]] name = "http" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", @@ -4010,12 +3974,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "futures-util", + "futures-core", "http", "http-body", "pin-project-lite", @@ -4029,9 +3993,9 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "humantime" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" [[package]] name = "hyper" @@ -4073,9 +4037,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" dependencies = [ "bytes", "futures-channel", @@ -4086,15 +4050,16 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", + "tower", "tower-service", "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -4228,7 +4193,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -4269,9 +4234,9 @@ dependencies = [ [[package]] name = "impl-codec" -version = "0.7.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d40b9d5e17727407e55028eafc22b2dc68781786e6d7eb8a21103f5058e3a14" +checksum = "b67aa010c1e3da95bf151bd8b4c059b2ed7e75387cdb969b4f8f2723a43f9941" dependencies = [ "parity-scale-codec", ] @@ -4316,29 +4281,29 @@ dependencies = [ [[package]] name = "impl-trait-for-tuples" -version = "0.2.3" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 1.0.109", ] [[package]] name = "include_dir" -version = "0.7.4" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" +checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e" dependencies = [ "include_dir_macros", ] [[package]] name = "include_dir_macros" -version = "0.7.4" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" +checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" dependencies = [ "proc-macro2", "quote", @@ -4357,12 +4322,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.1" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.14.5", ] [[package]] @@ -4373,9 +4338,9 @@ checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" [[package]] name = "inout" -version = "0.1.4" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ "generic-array", ] @@ -4402,20 +4367,20 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.15" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "hermit-abi 0.4.0", + "hermit-abi 0.5.0", "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" [[package]] name = "itertools" @@ -4455,9 +4420,33 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jiff" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d699bc6dfc879fb1bf9bdff0d4c56f0884fc6f0d0eb0fba397a6d00cd9a6b85e" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] [[package]] name = "jni" @@ -4469,7 +4458,7 @@ dependencies = [ "combine", "jni-sys", "log", - "thiserror 1.0.69", + "thiserror 1.0.60", "walkdir", ] @@ -4526,7 +4515,7 @@ dependencies = [ "rustls-pki-types", "rustls-platform-verifier", "soketto", - "thiserror 1.0.69", + "thiserror 1.0.60", "tokio", "tokio-rustls", "tokio-util", @@ -4552,7 +4541,7 @@ dependencies = [ "rustc-hash 2.1.1", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror 1.0.60", "tokio", "tokio-stream", "tracing", @@ -4576,7 +4565,7 @@ dependencies = [ "rustls-platform-verifier", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror 1.0.60", "tokio", "tower", "tracing", @@ -4592,7 +4581,7 @@ dependencies = [ "http", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror 1.0.60", ] [[package]] @@ -4610,9 +4599,9 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.4" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ "cfg-if", "ecdsa", @@ -4628,7 +4617,7 @@ version = "0.10.0" source = "git+https://github.com/availproject/avail-core?tag=core-node-7#70458d5430a5209f14369c42ded3243fce8fa1cb" dependencies = [ "avail-core", - "derive_more 0.99.19", + "derive_more 0.99.17", "dusk-bytes", "dusk-plonk", "once_cell", @@ -4663,21 +4652,21 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.170" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libm" -version = "0.2.11" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libredox" @@ -4685,9 +4674,8 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.5.0", "libc", - "redox_syscall", ] [[package]] @@ -4764,9 +4752,9 @@ checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "linux-raw-sys" -version = "0.4.15" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "litemap" @@ -4786,9 +4774,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" dependencies = [ "serde", ] @@ -4804,11 +4792,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.12.5" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.14.5", ] [[package]] @@ -4829,7 +4817,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -4843,7 +4831,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -4854,7 +4842,7 @@ checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -4865,7 +4853,7 @@ checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -4888,9 +4876,9 @@ dependencies = [ [[package]] name = "matrixmultiply" -version = "0.3.9" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" +checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2" dependencies = [ "autocfg", "rawpointer", @@ -4898,9 +4886,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "memfd" @@ -4908,7 +4896,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" dependencies = [ - "rustix 0.38.44", + "rustix 0.38.34", ] [[package]] @@ -4949,11 +4937,11 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ - "adler2", + "adler", ] [[package]] @@ -4963,7 +4951,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.52.0", ] @@ -5022,9 +5010,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.6" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" dependencies = [ "num-integer", "num-traits", @@ -5053,7 +5041,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -5062,7 +5050,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ - "arrayvec 0.7.6", + "arrayvec 0.7.4", "itoa", ] @@ -5138,9 +5126,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" @@ -5150,9 +5138,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "overload" @@ -5740,7 +5728,7 @@ checksum = "3170e2f4a3d95f2ace274b703a72630294f0a27c687a4adbad9590e2b3e5fe82" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -5793,9 +5781,9 @@ dependencies = [ [[package]] name = "pallet-delegated-staking" -version = "5.0.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "117f003a97f980514c6db25a50c22aaec2a9ccb5664b3cb32f52fb990e0b0c12" +checksum = "8502ef7c76f4c0613b4f6bd70413caba7068eeed6fc5fd2ac84fd61afc07d559" dependencies = [ "frame-support 38.2.0", "frame-system", @@ -6229,9 +6217,9 @@ dependencies = [ [[package]] name = "pallet-nomination-pools" -version = "35.0.2" +version = "35.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d04f050ab02af6cbe058e101abb8706be7f8ea7958e5bf1d4cd8caa6b66c71" +checksum = "04f3b3eb893cd3da58c86db519d8d5f2f1c014ff08942b087cb475e789cd45cf" dependencies = [ "frame-support 38.2.0", "frame-system", @@ -6499,7 +6487,7 @@ dependencies = [ "polkavm-linker 0.10.0", "sp-runtime 39.0.5", "tempfile", - "toml 0.8.20", + "toml 0.8.12", ] [[package]] @@ -6545,7 +6533,7 @@ checksum = "b8aee42afa416be6324cf6650c137da9742f27dc7be3c7ed39ad9748baf3b9ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -6734,9 +6722,9 @@ dependencies = [ [[package]] name = "pallet-staking" -version = "38.0.0" +version = "38.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c870d123f4f053b56af808a4beae1ffc4309a696e829796c26837936c926db3b" +checksum = "8efdbfe23385add01c734e6ddd7967e11a04fad0da7e4e42e6ae2501d1e12016" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -7014,9 +7002,9 @@ dependencies = [ [[package]] name = "pallet-xcm" -version = "17.0.1" +version = "17.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989676964dbda5f5275650fbdcd3894fe7fac626d113abf89d572b4952adcc36" +checksum = "ff8893d5736d085729ed6d698a727a1511dd2b787b48ad0dc2d86136f142cc3e" dependencies = [ "bounded-collections", "frame-benchmarking", @@ -7182,31 +7170,29 @@ checksum = "16b56e3a2420138bdb970f84dfb9c774aea80fa0e7371549eedec0d80c209c67" [[package]] name = "parity-scale-codec" -version = "3.7.4" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9fde3d0718baf5bc92f577d652001da0f8d54cd03a7974e118d04fc888dc23d" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ - "arrayvec 0.7.6", + "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.7.4" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581c837bb6b9541ce7faa9377c20616e4fb7650f6b0f68bc93c827ee504fb7b3" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.99", + "syn 1.0.109", ] [[package]] @@ -7246,15 +7232,15 @@ checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" [[package]] name = "parking" -version = "2.2.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" dependencies = [ "lock_api", "parking_lot_core", @@ -7268,9 +7254,9 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.1", "smallvec", - "windows-targets 0.52.6", + "windows-targets 0.52.5", ] [[package]] @@ -7329,29 +7315,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -7361,9 +7347,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.4" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +checksum = "464db0c665917b13ebb5d453ccdec4add5658ee1adc7affc7677615356a8afaf" dependencies = [ "atomic-waker", "fastrand", @@ -7415,7 +7401,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52b5648a2e8ce1f9a0f8c41c38def670cefd91932cd793468e1a5b0b0b4e4af1" dependencies = [ "bounded-collections", - "derive_more 0.99.19", + "derive_more 0.99.17", "parity-scale-codec", "polkadot-core-primitives", "scale-info", @@ -7550,7 +7536,7 @@ checksum = "1d4cdf181c2419b35c2cbde813da2d8ee777b69b4a6fa346b962d144e3521976" dependencies = [ "bitflags 1.3.2", "bitvec", - "derive_more 0.99.19", + "derive_more 0.99.17", "frame-benchmarking", "frame-support 38.2.0", "frame-system", @@ -7919,12 +7905,6 @@ dependencies = [ "polkavm-assembler 0.10.0", ] -[[package]] -name = "polkavm-common" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31ff33982a807d8567645d4784b9b5d7ab87bcb494f534a57cadd9012688e102" - [[package]] name = "polkavm-derive" version = "0.9.1" @@ -7943,15 +7923,6 @@ dependencies = [ "polkavm-derive-impl-macro 0.10.0", ] -[[package]] -name = "polkavm-derive" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2eb703f3b6404c13228402e98a5eae063fd16b8f58afe334073ec105ee4117e" -dependencies = [ - "polkavm-derive-impl-macro 0.18.0", -] - [[package]] name = "polkavm-derive-impl" version = "0.9.0" @@ -7961,7 +7932,7 @@ dependencies = [ "polkavm-common 0.9.0", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -7973,19 +7944,7 @@ dependencies = [ "polkavm-common 0.10.0", "proc-macro2", "quote", - "syn 2.0.99", -] - -[[package]] -name = "polkavm-derive-impl" -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.99", + "syn 2.0.100", ] [[package]] @@ -7995,7 +7954,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" dependencies = [ "polkavm-derive-impl 0.9.0", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8005,17 +7964,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9324fe036de37c17829af233b46ef6b5562d4a0c09bb7fdb9f8378856dee30cf" dependencies = [ "polkavm-derive-impl 0.10.0", - "syn 2.0.99", -] - -[[package]] -name = "polkavm-derive-impl-macro" -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.99", + "syn 2.0.100", ] [[package]] @@ -8062,17 +8011,17 @@ checksum = "26e45fa59c7e1bb12ef5289080601e9ec9b31435f6e32800a5c90c132453d126" [[package]] name = "polling" -version = "3.7.4" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +checksum = "645493cf344456ef24219d02a768cf1fb92ddf8c92161679ae3d91b91a637be3" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi 0.4.0", + "hermit-abi 0.3.9", "pin-project-lite", - "rustix 0.38.44", + "rustix 0.38.34", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -8098,6 +8047,21 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "portable-atomic" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -8106,21 +8070,18 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] -name = "prettyplease" -version = "0.2.30" +name = "prettier-please" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1ccf34da56fc294e7d4ccf69a85992b7dfb826b7cf57bac6a70bba3494cc08a" +checksum = "22020dfcf177fcc7bf5deaf7440af371400c67c0de14c399938d8ed4fb4645d3" dependencies = [ "proc-macro2", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8144,7 +8105,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d15600a7d856470b7d278b3fe0e311fe28c2526348549f8ef2ff7db3299c87f5" dependencies = [ "fixed-hash", - "impl-codec 0.7.1", + "impl-codec 0.7.0", "impl-num-traits", "impl-serde 0.5.0", "scale-info", @@ -8153,11 +8114,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.2.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_edit", + "toml_edit 0.21.1", ] [[package]] @@ -8203,18 +8164,18 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] name = "proc-macro-warning" -version = "1.84.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75eea531cfcd120e0851a3f8aed42c4841f78c889eefafd96339c72677ae42c3" +checksum = "834da187cfe638ae8abb0203f0b33e5ccdb02a28e7199f2f47b3e2754f50edca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8234,7 +8195,7 @@ checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.9.0", + "bitflags 2.5.0", "lazy_static", "num-traits", "rand", @@ -8248,9 +8209,9 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.25" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58e5423e24c18cc840e1c98370b3993c6649cd1678b4d24318bcf0a083cbe88" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" dependencies = [ "cc", ] @@ -8263,9 +8224,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -8303,7 +8264,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom", ] [[package]] @@ -8343,11 +8304,20 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.5.0", ] [[package]] @@ -8356,29 +8326,29 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.15", + "getrandom", "libredox", - "thiserror 1.0.69", + "thiserror 1.0.60", ] [[package]] name = "ref-cast" -version = "1.0.24" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.24" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8471,7 +8441,7 @@ dependencies = [ "ark-serialize 0.4.2", "ark-std 0.4.0", "ark-transcript 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "arrayvec 0.7.6", + "arrayvec 0.7.4", "blake2", "common", "fflonk", @@ -8479,14 +8449,15 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.11" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da5349ae27d3887ca812fb375b45a4fbb36d8d12d2df394968cd86e35683fe73" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.15", + "getrandom", "libc", + "spin", "untrusted", "windows-sys 0.52.0", ] @@ -8594,11 +8565,11 @@ dependencies = [ [[package]] name = "rustc_version" -version = "0.4.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.26", + "semver 1.0.23", ] [[package]] @@ -8617,37 +8588,37 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.44" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.5.0", "errno", "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", + "linux-raw-sys 0.4.13", + "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.23.23" +version = "0.23.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" +checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" dependencies = [ "log", "once_cell", - "ring 0.17.11", + "ring 0.17.8", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.103.0", "subtle", "zeroize", ] [[package]] name = "rustls-native-certs" -version = "0.7.3" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -8658,10 +8629,11 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.2.0" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ + "base64 0.22.1", "rustls-pki-types", ] @@ -8685,7 +8657,7 @@ dependencies = [ "rustls", "rustls-native-certs", "rustls-platform-verifier-android", - "rustls-webpki", + "rustls-webpki 0.102.3", "security-framework", "security-framework-sys", "webpki-roots", @@ -8700,20 +8672,31 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.102.8" +version = "0.102.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf" dependencies = [ - "ring 0.17.11", + "ring 0.17.8", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aa4eeac2588ffff23e9d7a7e9b3f971c5fb5b7ebc9452745e0c232c64f83b2f" +dependencies = [ + "ring 0.17.8", "rustls-pki-types", "untrusted", ] [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "092474d1a01ea8278f69e6a358998405fae5b8b963ddaeb2b0b04a128bf1dfb0" [[package]] name = "rusty-fork" @@ -8734,14 +8717,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5174a470eeb535a721ae9fdd6e291c2411a906b96592182d05217591d5c5cf7b" dependencies = [ "byteorder", - "derive_more 0.99.19", + "derive_more 0.99.17", ] [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safe-mix" @@ -8754,9 +8737,9 @@ dependencies = [ [[package]] name = "safe_arch" -version = "0.7.4" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" +checksum = "f398075ce1e6a179b46f51bd88d0598b92b00d3551f1a2d4ac49e771b56ac354" dependencies = [ "bytemuck", ] @@ -8788,7 +8771,7 @@ dependencies = [ "log", "sp-core 34.0.0", "sp-wasm-interface 21.0.1", - "thiserror 1.0.69", + "thiserror 1.0.60", ] [[package]] @@ -8825,7 +8808,7 @@ dependencies = [ "sc-allocator", "sp-maybe-compressed-blob", "sp-wasm-interface 21.0.1", - "thiserror 1.0.69", + "thiserror 1.0.60", "wasm-instrument", ] @@ -8896,7 +8879,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8924,7 +8907,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8950,7 +8933,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8972,7 +8955,7 @@ dependencies = [ "proc-macro2", "quote", "scale-info", - "syn 2.0.99", + "syn 2.0.100", "thiserror 2.0.12", ] @@ -8997,18 +8980,18 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] name = "schnellru" -version = "0.2.4" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "356285bbf17bea63d9e52e96bd18f039672ac92b55b8cb997d6162a2a37d1649" +checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" dependencies = [ "ahash 0.8.11", "cfg-if", @@ -9023,7 +9006,7 @@ checksum = "8de18f6d8ba0aad7045f5feae07ec29899c1112584a38509a84ad7b04451eaa0" dependencies = [ "aead", "arrayref", - "arrayvec 0.7.6", + "arrayvec 0.7.4", "curve25519-dalek", "getrandom_or_panic", "merlin", @@ -9131,11 +9114,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.11.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -9145,9 +9128,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -9182,9 +9165,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.26" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] @@ -9206,9 +9189,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.218" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] @@ -9224,22 +9207,22 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.16" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "364fec0df39c49a083c9a8a18a23a6bcfd9af130fe9fe321d18520a0d113e09e" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.218" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -9256,9 +9239,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" dependencies = [ "serde", ] @@ -9327,12 +9310,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -9411,15 +9388,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.14.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smol" -version = "2.0.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33bd3e260892199c3ccfc487c88b2da2265080acb316cd920da72fdfd7c599f" +checksum = "e635339259e51ef85ac7aa29a1cd991b957047507288697a690e80ab97d07cad" dependencies = [ "async-channel", "async-executor", @@ -9438,7 +9415,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "966e72d77a3b2171bb7461d0cb91f43670c63558c62d7cf42809cae6c8b6b818" dependencies = [ - "arrayvec 0.7.6", + "arrayvec 0.7.4", "async-lock", "atomic-take", "base64 0.22.1", @@ -9447,10 +9424,10 @@ dependencies = [ "bs58", "chacha20", "crossbeam-queue", - "derive_more 0.99.19", + "derive_more 0.99.17", "ed25519-zebra", "either", - "event-listener", + "event-listener 5.3.0", "fnv", "futures-lite", "futures-util", @@ -9497,9 +9474,9 @@ dependencies = [ "base64 0.22.1", "blake2-rfc", "bs58", - "derive_more 0.99.19", + "derive_more 0.99.17", "either", - "event-listener", + "event-listener 5.3.0", "fnv", "futures-channel", "futures-lite", @@ -9508,7 +9485,7 @@ dependencies = [ "hex", "itertools 0.13.0", "log", - "lru 0.12.5", + "lru 0.12.3", "parking_lot", "pin-project", "rand", @@ -9534,9 +9511,9 @@ dependencies = [ [[package]] name = "snowbridge-beacon-primitives" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10bd720997e558beb556d354238fa90781deb38241cf31c1b6368738ef21c279" +checksum = "25492622eb3e9e8f4e1c8abdfc4253b71735ea2dd8f571c5054292849b1a31cd" dependencies = [ "byte-slice-cast", "frame-support 38.2.0", @@ -9643,9 +9620,9 @@ dependencies = [ [[package]] name = "snowbridge-pallet-ethereum-client" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d53d32d8470c643f9f8c1f508e1e34263f76297e4c9150e10e8f2e0b63992e1" +checksum = "65826ed8585a614c0818e5e8da5a57bb0da36ba3e540e193672ac66d2f131d6c" dependencies = [ "frame-benchmarking", "frame-support 38.2.0", @@ -9681,9 +9658,9 @@ dependencies = [ [[package]] name = "snowbridge-pallet-inbound-queue" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2e6a9d00e60e3744e6b6f0c21fea6694b9c6401ac40e41340a96e561dcf1935" +checksum = "82a21efb385a4ec84476b1eb3d850905d77a395e5e477047752981daaadcdca7" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -9848,9 +9825,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -9889,7 +9866,7 @@ dependencies = [ "sp-std 14.0.0 (git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12)", "sp-trie 29.0.0", "sp-version 29.0.0", - "thiserror 1.0.69", + "thiserror 1.0.60", ] [[package]] @@ -9912,7 +9889,7 @@ dependencies = [ "sp-state-machine 0.43.0", "sp-trie 37.0.0", "sp-version 37.0.0", - "thiserror 1.0.69", + "thiserror 1.0.60", ] [[package]] @@ -9926,7 +9903,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -9941,7 +9918,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -10003,7 +9980,7 @@ dependencies = [ [[package]] name = "sp-ark-bls12-381" version = "0.4.2" -source = "git+https://github.com/paritytech/arkworks-substrate#f08093a5f7c32778eae1295430ec064dccd062a6" +source = "git+https://github.com/paritytech/arkworks-substrate#caa2eed74beb885dd07c7db5f916f2281dad818f" dependencies = [ "ark-bls12-381-ext", "sp-crypto-ec-utils 0.10.0", @@ -10012,7 +9989,7 @@ dependencies = [ [[package]] name = "sp-ark-ed-on-bls12-381-bandersnatch" version = "0.4.2" -source = "git+https://github.com/paritytech/arkworks-substrate#f08093a5f7c32778eae1295430ec064dccd062a6" +source = "git+https://github.com/paritytech/arkworks-substrate#caa2eed74beb885dd07c7db5f916f2281dad818f" dependencies = [ "ark-ed-on-bls12-381-bandersnatch-ext", "sp-crypto-ec-utils 0.10.0", @@ -10182,7 +10159,7 @@ dependencies = [ "sp-storage 19.0.0 (git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12)", "ss58-registry", "substrate-bip39 0.4.6", - "thiserror 1.0.69", + "thiserror 1.0.60", "tracing", "w3f-bls", "zeroize", @@ -10229,7 +10206,7 @@ dependencies = [ "sp-storage 21.0.0", "ss58-registry", "substrate-bip39 0.6.0", - "thiserror 1.0.69", + "thiserror 1.0.60", "tracing", "w3f-bls", "zeroize", @@ -10247,7 +10224,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.10.0" -source = "git+https://github.com/paritytech/polkadot-sdk#9a8061e6efc6607383160249319573696270d672" +source = "git+https://github.com/paritytech/polkadot-sdk#1e89a311471eba937a9552d7d1f55af1661feb08" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -10319,7 +10296,7 @@ source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7. dependencies = [ "quote", "sp-crypto-hashing 0.0.0", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -10330,7 +10307,7 @@ checksum = "b85d0f1f1e44bd8617eb2a48203ee854981229e3e79e6f468c7175d5fd37489b" dependencies = [ "quote", "sp-crypto-hashing 0.1.0", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -10341,7 +10318,7 @@ checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -10351,17 +10328,17 @@ source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7. dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#9a8061e6efc6607383160249319573696270d672" +source = "git+https://github.com/paritytech/polkadot-sdk#1e89a311471eba937a9552d7d1f55af1661feb08" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -10378,7 +10355,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.25.0" -source = "git+https://github.com/paritytech/polkadot-sdk#9a8061e6efc6607383160249319573696270d672" +source = "git+https://github.com/paritytech/polkadot-sdk#1e89a311471eba937a9552d7d1f55af1661feb08" dependencies = [ "environmental", "parity-scale-codec", @@ -10431,7 +10408,7 @@ dependencies = [ "scale-info", "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12)", - "thiserror 1.0.69", + "thiserror 1.0.60", ] [[package]] @@ -10445,7 +10422,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-runtime 39.0.5", - "thiserror 1.0.69", + "thiserror 1.0.60", ] [[package]] @@ -10520,7 +10497,7 @@ dependencies = [ "parking_lot", "sp-core 28.0.0", "sp-externalities 0.25.0 (git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12)", - "thiserror 1.0.69", + "thiserror 1.0.60", ] [[package]] @@ -10541,7 +10518,7 @@ version = "11.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0c768c11afbe698a090386876911da4236af199cd38a5866748df4d8628aeff" dependencies = [ - "thiserror 1.0.69", + "thiserror 1.0.60", "zstd 0.12.4", ] @@ -10594,7 +10571,7 @@ dependencies = [ "sp-core 34.0.0", "sp-debug-derive 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "sp-runtime 39.0.5", - "thiserror 1.0.69", + "thiserror 1.0.60", ] [[package]] @@ -10714,12 +10691,12 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "24.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#9a8061e6efc6607383160249319573696270d672" +source = "git+https://github.com/paritytech/polkadot-sdk#1e89a311471eba937a9552d7d1f55af1661feb08" dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", - "polkavm-derive 0.18.0", + "polkavm-derive 0.9.1", "primitive-types 0.13.1", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk)", "sp-runtime-interface-proc-macro 17.0.0 (git+https://github.com/paritytech/polkadot-sdk)", @@ -10760,20 +10737,20 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#9a8061e6efc6607383160249319573696270d672" +source = "git+https://github.com/paritytech/polkadot-sdk#1e89a311471eba937a9552d7d1f55af1661feb08" dependencies = [ "Inflector", "expander", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -10787,7 +10764,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -10863,7 +10840,7 @@ dependencies = [ "sp-panic-handler 13.0.0", "sp-std 14.0.0 (git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12)", "sp-trie 29.0.0", - "thiserror 1.0.69", + "thiserror 1.0.60", "tracing", "trie-db 0.28.0", ] @@ -10884,7 +10861,7 @@ dependencies = [ "sp-externalities 0.29.0", "sp-panic-handler 13.0.1", "sp-trie 37.0.0", - "thiserror 1.0.69", + "thiserror 1.0.60", "tracing", "trie-db 0.29.1", ] @@ -10910,7 +10887,7 @@ dependencies = [ "sp-externalities 0.29.0", "sp-runtime 39.0.5", "sp-runtime-interface 28.0.0", - "thiserror 1.0.69", + "thiserror 1.0.60", "x25519-dalek", ] @@ -10928,7 +10905,7 @@ source = "git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7. [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#9a8061e6efc6607383160249319573696270d672" +source = "git+https://github.com/paritytech/polkadot-sdk#1e89a311471eba937a9552d7d1f55af1661feb08" [[package]] name = "sp-storage" @@ -10946,7 +10923,7 @@ dependencies = [ [[package]] name = "sp-storage" version = "19.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#9a8061e6efc6607383160249319573696270d672" +source = "git+https://github.com/paritytech/polkadot-sdk#1e89a311471eba937a9552d7d1f55af1661feb08" dependencies = [ "impl-serde 0.5.0", "parity-scale-codec", @@ -10978,7 +10955,7 @@ dependencies = [ "parity-scale-codec", "sp-inherents 34.0.0", "sp-runtime 39.0.5", - "thiserror 1.0.69", + "thiserror 1.0.60", ] [[package]] @@ -10996,12 +10973,12 @@ dependencies = [ [[package]] name = "sp-tracing" version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#9a8061e6efc6607383160249319573696270d672" +source = "git+https://github.com/paritytech/polkadot-sdk#1e89a311471eba937a9552d7d1f55af1661feb08" dependencies = [ "parity-scale-codec", "tracing", "tracing-core", - "tracing-subscriber 0.3.19", + "tracing-subscriber 0.3.18", ] [[package]] @@ -11013,7 +10990,7 @@ dependencies = [ "parity-scale-codec", "tracing", "tracing-core", - "tracing-subscriber 0.3.19", + "tracing-subscriber 0.3.18", ] [[package]] @@ -11059,7 +11036,7 @@ dependencies = [ "sp-core 28.0.0", "sp-externalities 0.25.0 (git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12)", "sp-std 14.0.0 (git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12)", - "thiserror 1.0.69", + "thiserror 1.0.60", "tracing", "trie-db 0.28.0", "trie-root", @@ -11083,7 +11060,7 @@ dependencies = [ "schnellru", "sp-core 34.0.0", "sp-externalities 0.29.0", - "thiserror 1.0.69", + "thiserror 1.0.60", "tracing", "trie-db 0.29.1", "trie-root", @@ -11103,7 +11080,7 @@ dependencies = [ "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/availproject/polkadot-sdk.git?tag=polkadot-1.7.1-patch-12)", "sp-version-proc-macro 13.0.0", - "thiserror 1.0.69", + "thiserror 1.0.60", ] [[package]] @@ -11121,7 +11098,7 @@ dependencies = [ "sp-runtime 39.0.5", "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "sp-version-proc-macro 14.0.0", - "thiserror 1.0.69", + "thiserror 1.0.60", ] [[package]] @@ -11132,7 +11109,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -11144,7 +11121,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -11163,7 +11140,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "20.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#9a8061e6efc6607383160249319573696270d672" +source = "git+https://github.com/paritytech/polkadot-sdk#1e89a311471eba937a9552d7d1f55af1661feb08" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -11232,9 +11209,9 @@ dependencies = [ [[package]] name = "ss58-registry" -version = "1.51.0" +version = "1.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19409f13998e55816d1c728395af0b52ec066206341d939e22e7766df9b494b8" +checksum = "4743ce898933fbff7bbf414f497c459a782d496269644b3d650a398ae6a487ba" dependencies = [ "Inflector", "num-format", @@ -11290,9 +11267,9 @@ dependencies = [ [[package]] name = "staging-xcm" -version = "14.2.0" +version = "14.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bee7cd999e9cdf10f8db72342070d456e21e82a0f5962ff3b87edbd5f2b20e" +checksum = "250c5290c308d1f462403dc4e7926976727917e98a196de1ea4a49c86341f21c" dependencies = [ "array-bytes", "bounded-collections", @@ -11413,7 +11390,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -11458,16 +11435,16 @@ dependencies = [ "sp-maybe-compressed-blob", "strum 0.26.3", "tempfile", - "toml 0.8.20", + "toml 0.8.12", "walkdir", "wasm-opt", ] [[package]] name = "subtle" -version = "2.6.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "subxt" @@ -11520,7 +11497,7 @@ dependencies = [ "scale-info", "scale-typegen", "subxt-metadata", - "syn 2.0.99", + "syn 2.0.100", "thiserror 2.0.12", ] @@ -11584,7 +11561,7 @@ dependencies = [ "scale-typegen", "subxt-codegen", "subxt-utils-fetchmetadata", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -11654,9 +11631,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.99" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -11672,7 +11649,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -11695,7 +11672,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -11706,22 +11683,21 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.16" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tempfile" -version = "3.17.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230" +checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" dependencies = [ "cfg-if", "fastrand", - "getrandom 0.3.1", "once_cell", - "rustix 0.38.44", - "windows-sys 0.59.0", + "rustix 0.38.34", + "windows-sys 0.52.0", ] [[package]] @@ -11751,11 +11727,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.69" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" dependencies = [ - "thiserror-impl 1.0.69", + "thiserror-impl 1.0.60", ] [[package]] @@ -11769,13 +11745,13 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "1.0.69" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -11786,7 +11762,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -11821,9 +11797,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.38" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb041120f25f8fbe8fd2dbe4671c7c2ed74d83be2e7a77529bf7e0790ae3f472" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -11836,15 +11812,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.3" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.20" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -11871,9 +11847,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.9.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -11886,9 +11862,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.43.0" +version = "1.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" dependencies = [ "backtrace", "bytes", @@ -11908,7 +11884,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -11934,9 +11910,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" dependencies = [ "bytes", "futures-core", @@ -11957,36 +11933,47 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.20" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.22.12", ] [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.24" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.2.6", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" +dependencies = [ + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.8", ] [[package]] @@ -11999,6 +11986,7 @@ dependencies = [ "futures-util", "pin-project", "pin-project-lite", + "tokio", "tower-layer", "tower-service", "tracing", @@ -12006,21 +11994,21 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.3" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" [[package]] name = "tower-service" -version = "0.3.3" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "log", "pin-project-lite", @@ -12030,20 +12018,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -12105,9 +12093,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.19" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers 0.1.0", "nu-ansi-term", @@ -12188,9 +12176,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.18.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" @@ -12230,9 +12218,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -12245,21 +12233,15 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - -[[package]] -name = "unicode-width" -version = "0.2.0" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" [[package]] name = "unicode-xid" -version = "0.2.6" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "universal-hash" @@ -12302,27 +12284,27 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "utf8parse" -version = "0.2.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "valuable" -version = "0.1.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version_check" -version = "0.9.5" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "w3f-bls" -version = "0.1.8" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a3028804c8bbae2a97a15b71ffc0e308c4b01a520994aafa77d56e94e19024" +checksum = "7335e4c132c28cc43caef6adb339789e599e39adbe78da0c4d547fad48cbc331" dependencies = [ "ark-bls12-377", "ark-bls12-381", @@ -12338,7 +12320,7 @@ dependencies = [ "rand_core", "sha2 0.10.8", "sha3", - "thiserror 1.0.69", + "thiserror 1.0.60", "zeroize", ] @@ -12376,15 +12358,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasi" -version = "0.13.3+wasi-0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" -dependencies = [ - "wit-bindgen-rt", -] - [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -12407,7 +12380,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "wasm-bindgen-shared", ] @@ -12442,7 +12415,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -12476,7 +12449,7 @@ dependencies = [ "strum 0.24.1", "strum_macros 0.24.3", "tempfile", - "thiserror 1.0.69", + "thiserror 1.0.60", "wasm-opt-cxx-sys", "wasm-opt-sys", ] @@ -12511,7 +12484,7 @@ version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50386c99b9c32bd2ed71a55b6dd4040af2580530fae8bdb9a6576571a80d0cca" dependencies = [ - "arrayvec 0.7.6", + "arrayvec 0.7.4", "multi-stash", "num-derive", "num-traits", @@ -12637,7 +12610,7 @@ dependencies = [ "log", "object 0.30.4", "target-lexicon", - "thiserror 1.0.69", + "thiserror 1.0.60", "wasmparser", "wasmtime-cranelift-shared", "wasmtime-environ", @@ -12672,7 +12645,7 @@ dependencies = [ "object 0.30.4", "serde", "target-lexicon", - "thiserror 1.0.69", + "thiserror 1.0.60", "wasmparser", "wasmtime-types", ] @@ -12755,7 +12728,7 @@ checksum = "a4f6fffd2a1011887d57f07654dd112791e872e3ff4a2e626aee8059ee17f06f" dependencies = [ "cranelift-entity", "serde", - "thiserror 1.0.69", + "thiserror 1.0.60", "wasmparser", ] @@ -12781,9 +12754,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.8" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" +checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" dependencies = [ "rustls-pki-types", ] @@ -12807,9 +12780,9 @@ dependencies = [ [[package]] name = "wide" -version = "0.7.32" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41b5576b9a81633f3e8df296ce0063042a73507636cbe956c61133dd7034ab22" +checksum = "aab6594190de06d718a5dbc5fa781ab62f8903797056480e549ca74add6b7065" dependencies = [ "bytemuck", "safe_arch", @@ -12833,11 +12806,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -12852,15 +12825,9 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.6", + "windows-targets 0.52.5", ] -[[package]] -name = "windows-link" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" - [[package]] name = "windows-sys" version = "0.45.0" @@ -12885,16 +12852,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", + "windows-targets 0.52.5", ] [[package]] @@ -12929,18 +12887,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "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]] @@ -12957,9 +12915,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -12975,9 +12933,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -12993,15 +12951,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" [[package]] name = "windows_i686_gnullvm" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -13017,9 +12975,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -13035,9 +12993,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -13053,9 +13011,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -13071,26 +13029,26 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.7.3" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ "memchr", ] [[package]] -name = "wit-bindgen-rt" -version = "0.33.0" +name = "winnow" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d" dependencies = [ - "bitflags 2.9.0", + "memchr", ] [[package]] @@ -13135,14 +13093,14 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] name = "xcm-runtime-apis" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f3d96bd7362d9e6884ef6762f08737d89205a358d059a0451353f3e91985ca5" +checksum = "9820d596ca59a981951d2d01924ba0d45b0ab5671fd24dacf68415dbe1fe1053" dependencies = [ "frame-support 38.2.0", "parity-scale-codec", @@ -13202,29 +13160,28 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "synstructure 0.13.1", ] [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" dependencies = [ - "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -13244,15 +13201,15 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "synstructure 0.13.1", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" dependencies = [ "zeroize_derive", ] @@ -13265,7 +13222,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -13287,7 +13244,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] diff --git a/e2e/Cargo.toml b/e2e/Cargo.toml index da2d36856..9db3aaf99 100644 --- a/e2e/Cargo.toml +++ b/e2e/Cargo.toml @@ -11,3 +11,4 @@ avail-rust = { git = "https://github.com/availproject/avail-rust", tag = "v0.1.4 # Other serde = { version = "1.0.195", default-features = false, features = [ "derive", "alloc" ] } tokio = { version = "1.43.0", features = ["sync", "fs", "macros", "rt-multi-thread"] } +rustls-webpki = "0.102" diff --git a/node/Cargo.toml b/node/Cargo.toml index 3f8194161..db4eb9c25 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -32,7 +32,7 @@ frame-system = { workspace = true, default-features = false } sc-basic-authorship.workspace = true # 3rd-party -codec = { package = "parity-scale-codec", version = "3" } +codec = { workspace = true } clap = { workspace = true, optional = true } clap-num = { workspace = true, optional = true } jsonrpsee.workspace = true diff --git a/pallets/dactr/Cargo.toml b/pallets/dactr/Cargo.toml index b477e22be..5e52fc739 100644 --- a/pallets/dactr/Cargo.toml +++ b/pallets/dactr/Cargo.toml @@ -30,7 +30,7 @@ derive_more.workspace = true # Substrate serde = { workspace = true, optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive", ] } +codec = { workspace = true, default-features = false, features = [ "derive", ] } scale-info = { workspace = true, default-features = false } sp-core = { workspace = true, default-features = false } sp-std = { workspace = true, default-features = false } diff --git a/pallets/fusion/Cargo.toml b/pallets/fusion/Cargo.toml new file mode 100644 index 000000000..1890b924f --- /dev/null +++ b/pallets/fusion/Cargo.toml @@ -0,0 +1,64 @@ +[package] +name = "pallet-fusion" +version = "1.0.0" +edition = "2021" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +frame-system = { workspace = true, default-features = false } +hex-literal = { workspace = true } +log.workspace = true + +# Substrate +codec = { workspace = true, default-features = false, features = ["derive"] } +scale-info = { workspace = true, default-features = false } +frame-support = { workspace = true, default-features = false } +sp-core = { workspace = true, default-features = false } +sp-io = { workspace = true, default-features = false } +sp-runtime = { workspace = true, default-features = false } +sp-std = { workspace = true, default-features = false } +sp-staking = { workspace = true, default-features = false, features = ["serde"] } +pallet-balances = { workspace = true, default-features = false } +pallet-staking = { workspace = true, default-features = false } +pallet-staking-reward-curve = { workspace = true, default-features = false } +frame-election-provider-support = { workspace = true, default-features = false } +pallet-timestamp = { workspace = true, default-features = false } +pallet-session = { workspace = true, default-features = false } +pallet-authorship = { workspace = true, default-features = false } + +# Benchmarking +frame-benchmarking = { workspace = true, default-features = false, optional = true } + +[dev-dependencies] +sp-core = { workspace = true, default-features = false } +avail-core = { workspace = true, default-features = false } +hex = "0.4" + +[features] +default = [ "std" ] +std = [ + "codec/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "pallet-balances/std", + "scale-info/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-staking/std", + "sp-std/std", +] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/pallets/fusion/src/benchmarking.rs b/pallets/fusion/src/benchmarking.rs new file mode 100644 index 000000000..5387a5d91 --- /dev/null +++ b/pallets/fusion/src/benchmarking.rs @@ -0,0 +1,825 @@ +#![cfg(feature = "runtime-benchmarks")] + +use super::*; +use crate::Pallet as Fusion; +use frame_benchmarking::{ + account as benchmark_account, impl_benchmark_test_suite, v1::BenchmarkError, v2::*, +}; +use frame_support::assert_ok; +use frame_system::RawOrigin; +use sp_core::H160; +use sp_runtime::SaturatedConversion; + +fn get_account(name: &'static str) -> T::AccountId { + let account: T::AccountId = benchmark_account(name, 0, 0); + account +} + +fn init_benchmarks() { + let alice: T::AccountId = get_account::("ALICE"); + let bob: T::AccountId = get_account::("BOB"); + let charlie: T::AccountId = get_account::("CHARLIE"); + let dave: T::AccountId = get_account::("DAVE"); + let eve: T::AccountId = get_account::("EVE"); + let ferdie: T::AccountId = get_account::("FERDIE"); + + let balance: BalanceOf = 10_000_000_000_000_000_000_000u128.saturated_into(); + + T::Currency::make_free_balance_be( + &Fusion::::avail_account(), + 100_000_000_000_000_000_000_000u128.saturated_into(), + ); + T::Currency::make_free_balance_be(&alice, balance); + T::Currency::make_free_balance_be(&bob, balance); + T::Currency::make_free_balance_be(&charlie, balance); + T::Currency::make_free_balance_be(&dave, balance); + T::Currency::make_free_balance_be(&eve, balance); + T::Currency::make_free_balance_be(&ferdie, balance); + + let origin: T::RuntimeOrigin = RawOrigin::Root.into(); + assert_ok!(Fusion::::update_max_tvl( + origin.clone(), + 10_000_000_000_000_000_000_000_000u128.saturated_into() + )); + let slash_destination = FusionAddress::EvmAddress(H160::repeat_byte(0x09)); + assert_ok!(Fusion::::set_slash_destination( + origin.clone(), + Some(slash_destination), + Some(ferdie) + )); + + T::StakingFusionDataProvider::add_dummy_validator(get_account::("BOB")); +} + +fn create_avail_currency() { + let origin = RawOrigin::Root; + let currency_id = 0; + let nb_decimals = 18; + let max_amount = 1_000_000_000_000_000_000_000_000; + let min_amount = 0; + let initial_conversion_rate: BalanceOf = 1_000_000_000_000_000_000u128.saturated_into(); + let name: BoundedVec = b"Avail".to_vec().try_into().unwrap(); + + assert_ok!(Fusion::::create_currency( + origin.into(), + currency_id, + name, + nb_decimals, + max_amount, + min_amount, + initial_conversion_rate, + )); +} + +fn create_avail_pool() { + let origin = RawOrigin::Root; + let pool_id = 0; + let currency_id = 0; + let apy = Perbill::from_percent(10); + let alice: T::AccountId = get_account::("ALICE"); + let nominator = Some(alice); + + assert_ok!(Fusion::::create_pool( + origin.clone().into(), + pool_id, + currency_id, + apy, + nominator + )); + + let valid_targets: BoundedVec = + vec![get_account::("BOB")].try_into().unwrap(); + + assert_ok!(Fusion::::nominate( + origin.clone().into(), + pool_id, + valid_targets + )); + + assert_ok!(Fusion::::fill_pool_account( + RawOrigin::Signed(get_account::("ALICE")).into(), + pool_id, + 1_000_000_000_000_000_000_000u128.saturated_into() + )); + + assert_ok!(Fusion::::set_pool( + origin.clone().into(), + pool_id, + None, + Some(FusionPoolState::Open), + ConfigOp::Noop, + ConfigOp::Noop, + None + )); +} + +fn create_btc_currency() { + let origin = RawOrigin::Root; + let currency_id = 1; + let nb_decimals = 8; + let max_amount = 10_000_000_000; + let min_amount = 1_000_000; + let initial_conversion_rate: BalanceOf = 10_000_000_000_000_000_000u128.saturated_into(); + let name: BoundedVec = b"Bitcoin".to_vec().try_into().unwrap(); + + assert_ok!(Fusion::::create_currency( + origin.into(), + currency_id, + name, + nb_decimals, + max_amount, + min_amount, + initial_conversion_rate, + )); +} + +fn create_btc_pool() { + let origin = RawOrigin::Root; + let pool_id = 1; + let currency_id = 1; + let apy = Perbill::from_percent(5); + let alice: T::AccountId = get_account::("ALICE"); + let nominator = Some(alice); + + assert_ok!(Fusion::::create_pool( + origin.clone().into(), + pool_id, + currency_id, + apy, + nominator + )); + + let valid_targets: BoundedVec = + vec![get_account::("BOB")].try_into().unwrap(); + + assert_ok!(Fusion::::nominate( + origin.clone().into(), + pool_id, + valid_targets + )); + + assert_ok!(Fusion::::fill_pool_account( + RawOrigin::Signed(get_account::("ALICE")).into(), + pool_id, + 1_000_000_000_000_000_000_000u128.saturated_into() + )); + + assert_ok!(Fusion::::set_pool( + origin.clone().into(), + pool_id, + None, + Some(FusionPoolState::Open), + ConfigOp::Noop, + ConfigOp::Noop, + None + )); +} + +fn fill_pool_with_dummy_members(pool_id: PoolId) { + let mut pool = Fusion::::pools(pool_id).unwrap(); + let max_members = T::MaxMembersPerPool::get(); + let dummy_address = FusionAddress::EvmAddress(H160::repeat_byte(0x09)); + let target_count = max_members / 2; + for _ in 0..target_count { + pool.members.try_push((dummy_address, 0)).unwrap(); + } + Pools::::insert(pool_id, pool); + + let pool = Fusion::::pools(pool_id).unwrap(); + assert!(pool.members.len() > 0); +} + +fn fill_era_data( + era: EraIndex, + validator: T::AccountId, + fusion_address: FusionAddress, + pool_id: PoolId, + amount: u128, +) { + EraDurations::::insert(era, 120_000); + + let max_members = T::MaxMembersPerPool::get(); + let halfway_members = (max_members / 2) as usize; + + let mut exposure = FusionExposure:: { + era, + apy: Perbill::from_percent(10), + total_avail: amount.saturated_into(), + total_points: amount, + user_points: BoundedVec::default(), + targets: BoundedVec::try_from(vec![validator.clone()]).unwrap(), + native_exposure_data: Some( + BoundedVec::try_from(vec![(validator.clone(), amount.saturated_into())]).unwrap(), + ), + boost_additional_apy: Perbill::from_percent(5), + boost_members: Default::default(), + boost_total_points: amount, + boost_total_avail: amount.saturated_into(), + }; + + // Add dummy members + for _ in 0..halfway_members { + exposure + .user_points + .try_push((FusionAddress::EvmAddress(H160::repeat_byte(0x01)), 0)) + .unwrap(); + exposure + .boost_members + .try_push(FusionAddress::EvmAddress(H160::repeat_byte(0x01))) + .unwrap(); + } + + // Add specified member + exposure + .user_points + .try_push((fusion_address, amount)) + .unwrap(); + exposure.boost_members.try_push(fusion_address).unwrap(); + + Exposures::::insert(era, pool_id, exposure); + + T::StakingFusionDataProvider::add_dummy_era_points(validator, era); +} + +fn create_era_reward(era: EraIndex, pool_id: PoolId, amount: u128) { + let era_reward = EraReward:: { + rewards: amount.saturated_into(), + claimed_rewards: 0u128.saturated_into(), + additional_rewards: amount.saturated_into(), + additional_claimed_rewards: 0u128.saturated_into(), + }; + + EraRewards::::insert(era, pool_id, era_reward); +} + +#[benchmarks( + where ::RuntimeCall: From>, +)] +mod benchmarks { + use super::*; + + #[benchmark] + fn create_currency() -> Result<(), BenchmarkError> { + init_benchmarks::(); + + let origin = RawOrigin::Root; + let currency_id = 0; + let nb_decimals = 18; + let max_amount = 1_000_000_000_000_000_000_000_000; + let min_amount = 0; + let initial_conversion_rate: BalanceOf = 1_000_000_000_000_000_000u128.saturated_into(); + let name: BoundedVec = b"Avail".to_vec().try_into().unwrap(); + + #[extrinsic_call] + _( + origin, + currency_id, + name, + nb_decimals, + max_amount, + min_amount, + initial_conversion_rate, + ); + + Ok(()) + } + + #[benchmark] + fn set_currency() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + + let origin = RawOrigin::Root; + let currency_id = 0; + let max_amount = 1_000_000_000_000_000_000_000_000; + let min_amount = 0; + let name: BoundedVec = b"Avail".to_vec().try_into().unwrap(); + + #[extrinsic_call] + _( + origin, + currency_id, + Some(name), + Some(max_amount), + Some(min_amount), + ); + + Ok(()) + } + + #[benchmark] + fn destroy_currency() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + create_btc_currency::(); + + let origin = RawOrigin::Root; + let currency_id = 1; + + #[extrinsic_call] + _(origin, currency_id); + + Ok(()) + } + + #[benchmark] + fn set_currency_conversion_rate() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + + let origin = RawOrigin::Root; + let currency_id = 0; + let new_conversion_rate: BalanceOf = 1_100_000_000_000_000_000u128.saturated_into(); + + #[extrinsic_call] + _(origin, currency_id, new_conversion_rate); + + Ok(()) + } + + #[benchmark] + fn create_pool() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + + let origin = RawOrigin::Root; + let pool_id = 0; + let currency_id = 0; + let apy = Perbill::from_percent(10); + let alice: T::AccountId = get_account::("ALICE"); + let nominator = Some(alice); + + #[extrinsic_call] + _(origin, pool_id, currency_id, apy, nominator); + + Ok(()) + } + + #[benchmark] + fn set_pool() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + create_avail_pool::(); + + let origin = RawOrigin::Root; + let pool_id = 0; + let apy = Some(Perbill::from_percent(15)); + let state = Some(FusionPoolState::Open); + let nominator = ConfigOp::Set(get_account::("DAVE")); + let boost_data = ConfigOp::Set((Perbill::from_percent(5), 1_000_000_000_000_000_000)); + let retry_rewards_for_eras = None; + + #[extrinsic_call] + _( + origin, + pool_id, + apy, + state, + nominator, + boost_data, + retry_rewards_for_eras, + ); + + Ok(()) + } + + #[benchmark] + fn set_pool_with_retry(e: Linear<0, 10>) -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + create_avail_pool::(); + create_btc_currency::(); + create_btc_pool::(); + + let pool_id = 1; + let apy = Some(Perbill::from_percent(15)); + let state = Some(FusionPoolState::Open); + let nominator = ConfigOp::Set(get_account::("DAVE")); + let boost_data = ConfigOp::Set((Perbill::from_percent(5), 1_000_000_000_000_000_000)); + let fusion_address = FusionAddress::new_evm(H160::zero()); + fill_pool_with_dummy_members::(1); + + for era in 1..=e { + fill_era_data::( + era, + get_account::("BOB"), + fusion_address, + pool_id, + 1_000_000_000_000_000_000_000, + ); + } + + let retry_rewards_for_eras = + Some(BoundedVec::try_from((1..=e).collect::>()).unwrap()); + + let origin = RawOrigin::Root; + #[extrinsic_call] + set_pool( + origin, + pool_id, + apy, + state, + nominator, + boost_data, + retry_rewards_for_eras, + ); + + Ok(()) + } + + #[benchmark] + fn destroy_pool() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + create_avail_pool::(); + + let origin = RawOrigin::Root; + let pool_id = 0; + let leftover_destination = Some(get_account::("DAVE")); + Fusion::::destroy_pool(origin.clone().into(), pool_id, None).unwrap(); + + #[extrinsic_call] + _(origin, pool_id, leftover_destination); + + Ok(()) + } + + #[benchmark] + fn fill_pool_account() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + create_avail_pool::(); + + let pool_id = 0; + let amount: BalanceOf = 100_000_000_000_000_000_000u128.saturated_into(); + let address = get_account::("ALICE"); + let origin = RawOrigin::Signed(address); + + #[extrinsic_call] + _(origin, pool_id, amount); + + Ok(()) + } + + #[benchmark] + fn nominate() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + create_avail_pool::(); + + let origin = RawOrigin::Root; + let pool_id = 0; + let valid_targets: BoundedVec = + vec![get_account::("BOB")].try_into().unwrap(); + + #[extrinsic_call] + _(origin, pool_id, valid_targets); + + Ok(()) + } + + #[benchmark] + fn set_controller_address() -> Result<(), BenchmarkError> { + init_benchmarks::(); + + let fusion_address = FusionAddress::new_evm(H160::zero()); + let controller_address: T::AccountId = get_account::("ALICE"); + let new_controller_address: T::AccountId = get_account::("BOB"); + Fusion::::do_set_controller_address(fusion_address, Some(controller_address.clone())) + .unwrap(); + let origin = RawOrigin::Signed(controller_address); + + #[extrinsic_call] + _(origin, fusion_address, Some(new_controller_address)); + + Ok(()) + } + + #[benchmark] + fn set_slash_destination() -> Result<(), BenchmarkError> { + init_benchmarks::(); + + let origin = RawOrigin::Root; + let fusion_address = FusionAddress::new_evm(H160::zero()); + + #[extrinsic_call] + _(origin, Some(fusion_address), None); + + Ok(()) + } + + #[benchmark] + fn update_max_tvl() -> Result<(), BenchmarkError> { + init_benchmarks::(); + + let origin = RawOrigin::Root; + + #[extrinsic_call] + _( + origin, + 100_000_000_000_000_000_000_000_000u128.saturated_into(), + ); + + Ok(()) + } + + #[benchmark] + fn set_compounding() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + create_avail_pool::(); + create_btc_currency::(); + create_btc_pool::(); + + let fusion_address = FusionAddress::new_evm(H160::zero()); + let controller_address: T::AccountId = get_account::("ALICE"); + let origin = RawOrigin::Signed(controller_address.clone()); + Fusion::::do_set_controller_address(fusion_address, Some(controller_address.clone())) + .unwrap(); + Fusion::::add_to_currency_balance(fusion_address, 1, 100_000_000, false).unwrap(); + Fusion::::stake(origin.clone().into(), fusion_address, 1, 100_000_000).unwrap(); + + #[extrinsic_call] + _(origin, fusion_address, 1, false); + + Ok(()) + } + + #[benchmark] + fn stake() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + create_avail_pool::(); + create_btc_currency::(); + create_btc_pool::(); + + let fusion_address = FusionAddress::new_evm(H160::zero()); + let controller_address: T::AccountId = get_account::("ALICE"); + Fusion::::do_set_controller_address(fusion_address, Some(controller_address.clone())) + .unwrap(); + Fusion::::add_to_currency_balance(fusion_address, 1, 100_000_000, false).unwrap(); + fill_pool_with_dummy_members::(1); + + let origin = RawOrigin::Signed(controller_address); + + #[extrinsic_call] + _(origin, fusion_address, 1, 100_000_000); + + Ok(()) + } + + #[benchmark] + fn claim_rewards() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + create_avail_pool::(); + create_btc_currency::(); + create_btc_pool::(); + + let pool_id = 1; + let fusion_address = FusionAddress::new_evm(H160::zero()); + fill_pool_with_dummy_members::(1); + fill_era_data::( + 0, + get_account::("BOB"), + fusion_address, + 1, + 1_000_000_000_000_000_000_000, + ); + create_era_reward::(0, 1, 1_000_000_000_000_000_000); + + let pool = Fusion::::pools(pool_id).unwrap(); + let balance: BalanceOf = 10_000_000_000_000_000_000_000u128.saturated_into(); + T::Currency::make_free_balance_be(&pool.claimable_account, balance); + + let origin = RawOrigin::Signed(get_account::("ALICE")); + #[extrinsic_call] + _(origin, 0, pool_id, fusion_address); + + Ok(()) + } + + #[benchmark] + fn unbond_currency() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + create_avail_pool::(); + create_btc_currency::(); + create_btc_pool::(); + + let fusion_address = FusionAddress::new_evm(H160::zero()); + let controller_address: T::AccountId = get_account::("ALICE"); + let origin = RawOrigin::Signed(controller_address.clone()); + Fusion::::do_set_controller_address(fusion_address, Some(controller_address.clone())) + .unwrap(); + Fusion::::add_to_currency_balance(fusion_address, 1, 100_000_000, false).unwrap(); + Fusion::::set_pool( + RawOrigin::Root.into(), + 1, + None, + None, + ConfigOp::Noop, + ConfigOp::Set((Perbill::from_percent(5), 1_000_000_000_000_000_000)), + None, + ) + .unwrap(); + + fill_pool_with_dummy_members::(1); + fill_era_data::( + 0, + get_account::("BOB"), + fusion_address, + 1, + 1_000_000_000_000_000_000_000, + ); + + Fusion::::stake(origin.clone().into(), fusion_address, 1, 100_000_000).unwrap(); + HasBoost::::insert(1, fusion_address, true); + + let max_members = T::MaxMembersPerPool::get(); + let halfway_members = (max_members / 2) as usize; + let mut unbonding_chunk: BoundedVec< + (FusionAddress, FusionCurrencyBalance), + T::MaxMembersPerPool, + > = BoundedVec::default(); + for _ in 0..halfway_members { + unbonding_chunk + .try_push((FusionAddress::EvmAddress(H160::repeat_byte(0x01)), 0)) + .unwrap() + } + UnbondingChunks::::insert(1, T::BondingDuration::get(), unbonding_chunk); + + #[extrinsic_call] + _(origin, fusion_address, 1, Some(100_000_000)); + + Ok(()) + } + + #[benchmark] + fn withdraw_unbonded_currency() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + create_avail_pool::(); + create_btc_currency::(); + create_btc_pool::(); + + let fusion_address = FusionAddress::new_evm(H160::zero()); + let controller_address: T::AccountId = get_account::("ALICE"); + let origin = RawOrigin::Signed(controller_address.clone()); + Fusion::::do_set_controller_address(fusion_address, Some(controller_address.clone())) + .unwrap(); + Fusion::::add_to_currency_balance(fusion_address, 1, 100_000_000, false).unwrap(); + Fusion::::set_pool( + RawOrigin::Root.into(), + 1, + None, + None, + ConfigOp::Noop, + ConfigOp::Set((Perbill::from_percent(5), 1_000_000_000_000_000_000)), + None, + ) + .unwrap(); + + fill_pool_with_dummy_members::(1); + fill_era_data::( + 0, + get_account::("BOB"), + fusion_address, + 1, + 1_000_000_000_000_000_000_000, + ); + + Fusion::::stake(origin.clone().into(), fusion_address, 1, 100_000_000).unwrap(); + HasBoost::::insert(1, fusion_address, true); + + let max_members = T::MaxMembersPerPool::get(); + let halfway_members = (max_members / 2) as usize; + let mut unbonding_chunk: BoundedVec< + (FusionAddress, FusionCurrencyBalance), + T::MaxMembersPerPool, + > = BoundedVec::default(); + for _ in 0..halfway_members { + unbonding_chunk + .try_push((FusionAddress::EvmAddress(H160::repeat_byte(0x01)), 0)) + .unwrap() + } + unbonding_chunk + .try_push((fusion_address, 100_000_000)) + .unwrap(); + UnbondingChunks::::insert(1, T::BondingDuration::get(), unbonding_chunk); + + Fusion::::unbond_currency(origin.clone().into(), fusion_address, 1, Some(100_000_000)) + .unwrap(); + + T::StakingFusionDataProvider::set_dummy_active_era(T::BondingDuration::get() + 1); + + #[extrinsic_call] + _(origin, fusion_address, 1); + + Ok(()) + } + + #[benchmark] + fn withdraw_avail_to_controller() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + create_avail_pool::(); + + let fusion_address = FusionAddress::new_evm(H160::zero()); + let controller_address: T::AccountId = get_account::("ALICE"); + let origin = RawOrigin::Signed(controller_address.clone()); + Fusion::::do_set_controller_address(fusion_address, Some(controller_address.clone())) + .unwrap(); + Fusion::::add_to_currency_balance(fusion_address, 0, 10_000_000_000_000_000_000, false) + .unwrap(); + + #[extrinsic_call] + _(origin, fusion_address, 9_000_000_000_000_000_000); + + Ok(()) + } + + #[benchmark] + fn set_pool_boost_allocations() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + create_avail_pool::(); + create_btc_currency::(); + create_btc_pool::(); + + let fusion_address = FusionAddress::new_evm(H160::zero()); + let controller_address: T::AccountId = get_account::("ALICE"); + let origin = RawOrigin::Signed(controller_address.clone()); + Fusion::::do_set_controller_address(fusion_address, Some(controller_address.clone())) + .unwrap(); + + Fusion::::add_to_currency_balance(fusion_address, 0, 10_000_000_000_000_000_000, false) + .unwrap(); + Fusion::::add_to_currency_balance(fusion_address, 1, 100_000_000, false).unwrap(); + Fusion::::set_pool( + RawOrigin::Root.into(), + 0, + None, + None, + ConfigOp::Noop, + ConfigOp::Set((Perbill::from_percent(5), 1_000_000_000_000_000_000)), + None, + ) + .unwrap(); + Fusion::::set_pool( + RawOrigin::Root.into(), + 1, + None, + None, + ConfigOp::Noop, + ConfigOp::Set((Perbill::from_percent(5), 1_000_000_000_000_000_000)), + None, + ) + .unwrap(); + + fill_pool_with_dummy_members::(0); + fill_pool_with_dummy_members::(1); + + Fusion::::stake( + origin.clone().into(), + fusion_address, + 0, + 10_000_000_000_000_000_000, + ) + .unwrap(); + Fusion::::stake(origin.clone().into(), fusion_address, 1, 100_000_000).unwrap(); + + HasBoost::::insert(0, fusion_address, true); + HasBoost::::insert(1, fusion_address, true); + + #[extrinsic_call] + _( + origin, + fusion_address, + BoundedVec::try_from(vec![0, 1]).unwrap(), + ); + + Ok(()) + } + + #[benchmark] + fn withdraw_pool_account() -> Result<(), BenchmarkError> { + init_benchmarks::(); + create_avail_currency::(); + create_avail_pool::(); + + let origin = RawOrigin::Root; + + #[extrinsic_call] + _( + origin, + 0, + 100_000_000_000_000_000_000u128.saturated_into(), + get_account::("ALICE"), + ); + + Ok(()) + } + + impl_benchmark_test_suite!(Fusion, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/pallets/fusion/src/lib.rs b/pallets/fusion/src/lib.rs new file mode 100644 index 000000000..cfc14b53e --- /dev/null +++ b/pallets/fusion/src/lib.rs @@ -0,0 +1,3357 @@ +#![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; +mod traits; +pub mod types; +mod weights; + +use sp_std::collections::btree_map::BTreeMap; + +use crate::types::*; +use alloc::{format, string::String}; +use frame_support::{ + dispatch::GetDispatchInfo, + pallet_prelude::*, + traits::{ + Currency, ExistenceRequirement, LockableCurrency, OnUnbalanced, UnfilteredDispatchable, + WithdrawReasons, + }, + PalletId, +}; +use frame_system::pallet_prelude::*; +pub use pallet::*; +use pallet_staking::traits::FusionExt; +use sp_core::U256; + +use sp_runtime::{ + traits::{AccountIdConversion, Bounded, Zero}, + Perbill, Saturating, +}; +use sp_staking::{currency_to_vote::CurrencyToVote, EraIndex}; +use sp_std::collections::btree_set::BTreeSet; +use sp_std::{vec, vec::Vec}; + +pub use traits::{PoolAccountProvider, StakingFusionDataProvider}; +pub use weights::WeightInfo; + +pub type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + +pub type NegativeImbalanceOf = <::Currency as Currency< + ::AccountId, +>>::NegativeImbalance; + +pub const AVAIL_CURRENCY_ID: u32 = 0; +pub const AVAIL_POOL_ID: u32 = 0; +pub const MILLISECONDS_PER_YEAR: u64 = 1000 * 3600 * 24 * 36525 / 100; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// A sudo-able call. + type RuntimeCall: Parameter + + UnfilteredDispatchable + + GetDispatchInfo; + + /// Type representing the weight of this pallet + type WeightInfo: WeightInfo; + + /// Someone who can call the admin extrinsics. + type ApprovedOrigin: EnsureOrigin; + + /// Currency type for this pallet. + type Currency: LockableCurrency>; + + /// Convert a balance into a number used for election calculation. + type CurrencyToVote: sp_staking::currency_to_vote::CurrencyToVote>; + + /// The destination for rewards that were not claimed after 'HistoryDepth' eras. + type RewardRemainder: OnUnbalanced>; + + /// Pallet id used to derive accounts used by the pallet + #[pallet::constant] + type PalletId: Get; + + /// Maximum allowed for the currency name + #[pallet::constant] + type MaxCurrencyNameLength: Get; + + /// Maximum number of members in a pool + #[pallet::constant] + type MaxMembersPerPool: Get; + + /// Maximum number of selectable targets for a pool + #[pallet::constant] + type MaxTargets: Get; + + /// Maximum number of parallel partial unbonds + #[pallet::constant] + type MaxUnbonding: Get; + + /// Maximum of number of concurrent pending slashes for a pool + #[pallet::constant] + type MaxSlashesPerPool: Get; + + /// Maximum number of pools behind a validator, mostly used to set bounds + #[pallet::constant] + type MaxPoolsPerValidator: Get; + + /// Period for funds to be available after unbonding + #[pallet::constant] + type BondingDuration: Get; + + /// Period to veto a slash + #[pallet::constant] + type SlashDeferDuration: Get; + + /// Number of era for which to keep Fusion data + #[pallet::constant] + type HistoryDepth: Get; + + /// A provider that gives the information from the staking pallet. + type StakingFusionDataProvider: StakingFusionDataProvider; + + /// A provider that gives the pool accounts, needed because behaviour is different in tests and production + type PoolAccountProvider: PoolAccountProvider; + } + + #[pallet::pallet] + pub struct Pallet(_); + + /// Stores the total value locked in avail and the maximum total value locked authorized + #[pallet::storage] + #[pallet::getter(fn tvl_data)] + pub type TotalValueLockedData = StorageValue<_, TVLData, ValueQuery>; + + /// Stores all the fusion currencies + #[pallet::storage] + #[pallet::getter(fn currencies)] + pub type Currencies = + StorageMap<_, Twox64Concat, CurrencyId, FusionCurrency, OptionQuery>; + + /// Stores all the fusion pools + #[pallet::storage] + #[pallet::getter(fn pools)] + pub type Pools = StorageMap<_, Twox64Concat, PoolId, FusionPool, OptionQuery>; + + /// Mapping from the pools funds account address to the pool id + #[pallet::storage] + #[pallet::getter(fn pool_account_to_id)] + pub type PoolsAccountToId = + StorageMap<_, Twox64Concat, T::AccountId, PoolId, OptionQuery>; + + /// Stores all the membership of users in pools + #[pallet::storage] + #[pallet::getter(fn memberships)] + pub type Memberships = StorageDoubleMap< + _, + Blake2_128Concat, + FusionAddress, + Twox64Concat, + PoolId, + FusionMembership, + OptionQuery, + >; + + /// Stores all the users idle balances + #[pallet::storage] + #[pallet::getter(fn user_currency_balances)] + pub type UserCurrencyBalances = StorageDoubleMap< + _, + Blake2_128Concat, + FusionAddress, + Twox64Concat, + CurrencyId, + FusionUserCurrencyBalance, + OptionQuery, + >; + + /// Stores era rewards for each pool + #[pallet::storage] + #[pallet::getter(fn era_rewards)] + pub type EraRewards = StorageDoubleMap< + _, + Twox64Concat, + EraIndex, + Twox64Concat, + PoolId, + EraReward, + OptionQuery, + >; + + /// Stores the conversion rates for currencies + /// How much one unit of currency is equal in AVAIL + #[pallet::storage] + #[pallet::getter(fn currency_rates)] + pub type CurrencyRates = StorageDoubleMap< + _, + Twox64Concat, + EraIndex, + Twox64Concat, + CurrencyId, + BalanceOf, + OptionQuery, + >; + + /// Stores the next currency changes to be applied next era + #[pallet::storage] + #[pallet::getter(fn currency_rate_changes)] + pub type CurrencyRateChanges = + StorageMap<_, Twox64Concat, CurrencyId, BalanceOf, ValueQuery>; + + /// Mapping from Fusion address to Substrate address + #[pallet::storage] + #[pallet::getter(fn fusion_address_to_substrate_address)] + pub type FusionAddressToSubstrateAddress = + StorageMap<_, Blake2_128Concat, FusionAddress, T::AccountId, OptionQuery>; + + /// Stores the era durations for HistoryDepth eras + /// It is used in case claiming reward for a pool failed because of low balance + /// We will be able to compute those rewards later using era duration + #[pallet::storage] + #[pallet::getter(fn era_durations)] + pub type EraDurations = StorageMap<_, Twox64Concat, EraIndex, u64, OptionQuery>; + + /// Stores the fusion era exposure for HistoryDepth eras + #[pallet::storage] + #[pallet::getter(fn exposures)] + pub type Exposures = StorageDoubleMap< + _, + Twox64Concat, + EraIndex, + Twox64Concat, + PoolId, + FusionExposure, + OptionQuery, + >; + + /// Stores the pool ids that backed a validator for a specific era + /// (era, ValidatorAddress) => PoolIds that backed the validator for the era + #[pallet::storage] + #[pallet::getter(fn pools_backing_validator)] + pub type PoolsBackingValidator = StorageDoubleMap< + _, + Twox64Concat, + EraIndex, + Twox64Concat, + T::AccountId, + BoundedVec, + ValueQuery, + >; + + /// Stores the fusion claimed rewards for HistoryDepth eras + #[pallet::storage] + #[pallet::getter(fn claimed_rewards)] + pub type ClaimedRewards = StorageDoubleMap< + _, + Twox64Concat, + EraIndex, + Twox64Concat, + (PoolId, FusionAddress), + BalanceOf, + ValueQuery, + >; + + /// Stores Fusion address of the slash destination + /// It can be controlled with technical committee + #[pallet::storage] + #[pallet::getter(fn slash_destination)] + pub type SlashDestination = StorageValue<_, FusionAddress, OptionQuery>; + + /// Stores the number of slashes for a given era, a validator and a pool funds account + /// (era, (validator, funds_account)) => number of pending_slash + /// Used mainly to quickly determine if a slashed nominator is from Fusion pallet + #[pallet::storage] + #[pallet::getter(fn has_pending_slash)] + pub type HasPendingSlash = StorageDoubleMap< + _, + Twox64Concat, + EraIndex, + Twox64Concat, + (T::AccountId, T::AccountId), + u32, + ValueQuery, + >; + + /// Stores the unbonding chunks of all the pallet + /// For a given pool and era, will return a vector of chunks + #[pallet::storage] + #[pallet::getter(fn unbonding_chunks)] + pub type UnbondingChunks = StorageDoubleMap< + _, + Twox64Concat, + PoolId, + Twox64Concat, + EraIndex, + BoundedVec<(FusionAddress, FusionCurrencyBalance), T::MaxMembersPerPool>, + ValueQuery, + >; + + /// Stores the pool ids of pool having an boost alongside the minimum to get the boost + #[pallet::storage] + #[pallet::getter(fn pools_with_boost)] + pub type PoolsWithBoost = + StorageMap<_, Twox64Concat, PoolId, FusionCurrencyBalance, OptionQuery>; + + /// Stores true if the user has boost in the pool + #[pallet::storage] + #[pallet::getter(fn has_boost)] + pub type HasBoost = + StorageDoubleMap<_, Twox64Concat, PoolId, Twox64Concat, FusionAddress, bool, ValueQuery>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Event triggered when the funding account is filled with new funds + FundsAccountFilled { + sender: T::AccountId, + amount: BalanceOf, + }, + FundsAccountWithdrawn { + recipient: T::AccountId, + amount: BalanceOf, + }, + /// Event triggered when a new currency is created + CurrencyCreated { + currency_id: CurrencyId, + name: BoundedVec, + nb_decimals: u8, + max_amount: FusionCurrencyBalance, + min_amount: FusionCurrencyBalance, + initial_conversion_rate: BalanceOf, + }, + /// Event triggered when a currency's properties are updated + CurrencySet { + currency_id: CurrencyId, + name: Option>, + max_amount: Option, + min_amount: Option, + }, + /// Event triggered when a currency is deleted + CurrencyDeleted { currency_id: CurrencyId }, + /// Event triggered when a conversion rate is set for a currency + CurrencyConversionRateSet { + currency_id: CurrencyId, + conversion_rate: BalanceOf, + }, + /// Event triggered when a currency is deposited into the system + CurrencyDeposited { + currency_id: CurrencyId, + fusion_address: FusionAddress, + amount: FusionCurrencyBalance, + }, + /// Event triggered when a user unbonds currency from a pool + CurrencyUnbonded { + pool_id: PoolId, + currency_id: CurrencyId, + fusion_address: FusionAddress, + unbonded_amount: FusionCurrencyBalance, + points: Points, + era: EraIndex, + }, + /// Event triggered when a user withdraws unbonded currency + CurrencyWithdrawn { + pool_id: PoolId, + currency_id: CurrencyId, + fusion_address: FusionAddress, + amount: FusionCurrencyBalance, + }, + /// Event triggered when the controller address for a user is changed + ControllerAddressSet { + fusion_address: FusionAddress, + new_controller_address: Option, + }, + /// Event triggered when the Fusion address and controller address are set for the Slash destination + SlashDestinationSet { + fusion_address: Option, + controller_address: Option, + }, + /// Event triggered when the compounding value is changed for a pool member + CompoundingSet { + pool_id: PoolId, + fusion_address: FusionAddress, + compound: bool, + }, + /// Event triggered when a new Fusion pool is created + PoolCreated { + pool_id: PoolId, + currency_id: CurrencyId, + apy: Perbill, + state: FusionPoolState, + nominator: Option, + funds_account: T::AccountId, + claimable_account: T::AccountId, + }, + /// Event triggered when a Fusion pool's properties are updated + PoolSet { + pool_id: PoolId, + apy: Option, + state: Option, + nominator: ConfigOp, + boost_data: ConfigOp<(Perbill, FusionCurrencyBalance)>, + }, + /// Event triggered when a user joins a pool + PoolJoined { + pool_id: PoolId, + fusion_address: FusionAddress, + currency_id: CurrencyId, + amount: FusionCurrencyBalance, + points: Points, + }, + /// Event triggered when a user bonds extra currency into a pool + PoolBondExtra { + pool_id: PoolId, + fusion_address: FusionAddress, + currency_id: CurrencyId, + amount: FusionCurrencyBalance, + points: Points, + }, + /// Event triggered when a user's pool membership is removed + PoolMembershipRemoved { + pool_id: PoolId, + fusion_address: FusionAddress, + }, + /// Event triggered when a pool is deleted + PoolDeleted { + pool_id: PoolId, + leftover: BalanceOf, + }, + /// Event triggered when a pool state was changed to destroying + PoolDestroying { pool_id: PoolId }, + /// Event triggered when a pool nominates a list of targets (validators) + Nominated { + pool_id: PoolId, + targets: BoundedVec, + }, + /// Event triggered when unclaimed rewards are sent to the remainder + RewardRemainderSent { amount: BalanceOf }, + /// Event triggered when rewards are set for an era + RewardSet { + era: EraIndex, + rewarded_pools: Vec, + total_rewarded: BalanceOf, + paused_pools: Vec, + paused_pools_missed_rewards: Vec>, + retry: bool, + }, + /// Event triggered when a user claims rewards for a pool and era + RewardClaimed { + pool_id: PoolId, + fusion_address: FusionAddress, + era: EraIndex, + reward: BalanceOf, + }, + /// Event triggered when exposures are set for an era + ExposuresSet { era: EraIndex }, + /// Event triggered when AVAIL is withdrawn to the controller account + AvailWithdrawnToController { + fusion_address: FusionAddress, + controller: T::AccountId, + amount: BalanceOf, + }, + /// Event triggered when the maximum total value locked authorized is updated. + MaxTVLUpdated(BalanceOf), + /// Event triggered when a slash was reported and it concern a fusion pool + FusionSlashReported { + pool_id: PoolId, + slash_era: EraIndex, + slash_ratio: Perbill, + validator: T::AccountId, + }, + /// Event triggered when one or multiple slashes are cancelled + FusionSlashCancelled { + pool_ids: Vec, + slash_era: EraIndex, + validators: Vec, + }, + /// Event triggered when a pool get slashed + FusionPoolSlashed { + currency_id: CurrencyId, + pool_id: PoolId, + slash_era: EraIndex, + amount: FusionCurrencyBalance, + }, + /// Event triggered when pools boost allocations have been set for a user + UserBoostAllocationsOptimized { + fusion_address: FusionAddress, + pools_added: Vec, + pools_removed: Vec, + }, + /// An error has happened in an automatic function + ErrorDataEvent { detail: String }, + } + + #[pallet::error] + pub enum Error { + /// The id is already used + CurrencyAlreadyExists, + /// No currency with the specified id + CurrencyNotFound, + /// The currency is already destroyed + CurrencyDestroyed, + /// Currency is not deletable cause a pool exist with the currency id + PoolExistsForCurrency, + /// The maximum amount of the currency is lower than what's already in the system + InvalidMaxAmount, + /// The minimum amount stakeable for this currency is greater than the maximum amount allowed in the system + InvalidMinAmount, + /// Pool id is already taken + PoolAlreadyExists, + /// Cannot create a pool in state destroying + CannotSetPoolToDestroying, + /// Pool was not found in storage + PoolNotFound, + /// The currency rate was not found + CurrencyRateNotFound, + /// Arithmetic error when doing conversions + ArithmeticError, + /// Arithmetic error when doing points conversions + ArithmeticPointsError, + /// The substrate address does not correspond to the Fusion address in the mapping + InvalidSubstrateAddress, + /// The pool is not open + PoolNotOpen, + /// The bond amount is lower than the currency minimum allowed to bond + BondAmoundTooLow, + /// The bond amount would make the currency go past the maximum allowed in the system + BondWouldExceedMaxForCurrency, + /// The pool is full of members + PoolMemberLimitReached, + /// User has not balance record for the currency + NoCurrencyBalanceForUser, + /// The user has not enough balance of the specified currency + NotEnoughCurrencyBalanceForUser, + /// User is not a member of the pool + MembershipNotFound, + /// User has no more points to unbond + NoActivePointsToUnbond, + /// The currency name is invalid + InvalidName, + /// The currency's number of decimals is invalid + InvalidNumberOfDecimals, + /// The max number for a currency cannot be 0 + InvalidMaxNumber, + /// The conversion rate for the currency is not valid + InvalidConversionRate, + /// The APY for a pool cannot be 0 + InvalidAPY, + /// The provided amount is not valid (cannot be 0) + InvalidAmount, + /// The amount to unbond is invalid + InvalidUnbondAmount, + /// Unbonding this amount will make the remaining below minimum + AmountWillGoBelowMinimum, + /// User has too much unbonding chunks + MaxUnbondingChunksExceeded, + /// No funds are available to withdraw + NoFundsToWithdraw, + /// Caller is not authorized for this operation + NotAuthorized, + /// No rewards were found for the era + NoRewardsForEra, + /// The user has no funds, so no rewards can be claimed + NoRewardsToClaim, + /// The exposure is not founds + ExposureNotFound, + /// The user was not found in the exposure + UserNotFoundInExposure, + /// Rewards were already claimed for this user / era + AlreadyClaimed, + /// A user tried to unbond another user but it's only allowed if the pool is destroying + PoolIsNotDestroying, + /// Action is not allowed as the pool is destroying + PoolIsDestroying, + /// The pool is not ready to get cleaned from the storage + PoolCannotBeCleaned, + /// To handle compounding and easy bouding and unbonding, avail currency has no minimum + NoMinAmountForAvailCurrency, + /// There is no controller address to withdraw to + NoControllerAddressForUser, + /// If you're active points are below minimum, you cannot set compound to true + CannotSetCompoudingWithLessThanMinimum, + /// The state cannot be set to open if the pool is not nominating + PoolIsNotNominating, + /// The pool needs target if its state is open or blocked + ActivePoolNeedsTargets, + /// The controller of the slash destination can only be set with the correct extrinsic + CannotSetControllerForSlashDestination, + /// A user tried to claim but the account is empty, can try again later + NotEnoughClaimableBalanceInPool, + /// The maximum TVL was reached + MaxTVLReached, + /// No valid validators was provided in the targets + NoValidValidators, + /// Era duration was not recorded properly so we cannot retry + EraDurationNotFound, + /// Pool has leftover funds, but we did not specify where it should go + NoLeftoverDestinationProvided, + /// The limit in the pool pending slashes have been reached + PendingSlashLimitReached, + /// Slash not found in pool + SlashNotFound, + /// The user does not have a membership in the AVAIL pool + NoAvailMembership, + /// The pool does not have boost configured + PoolHasNoBoost, + /// The user does not have enough AVAIL to allocate to the boosted pools + NotEnoughAvailForBoost, + /// The TC cannot set a controller address for a user, it can only remove (to clean) + RootCanOnlyRemoveController, + /// We cannot delete Avail currency + CannotDestroyAvailCurrency, + /// Action cannot be performed because the entity id 0 was not created (avail currency or avail pool) + EntityZeroDoesNotExist, + /// Action cannot be performed because other pools still exist + OtherPoolsExist, + /// We cannot directly deposit Avail, we can only use `deposit_avail_to_fusion` + CannotDepositAvailCurrency, + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn integrity_test() { + // Checks that Fusion bonding duration is greater than slash defer duration + assert!( + T::SlashDeferDuration::get() < T::BondingDuration::get() || T::BondingDuration::get() == 0, + "As per documentation, slash defer duration ({}) should be less than bonding duration ({}).", + T::SlashDeferDuration::get(), + T::BondingDuration::get(), + ) + } + } + + #[pallet::call] + impl Pallet { + /// TODO - Dummy extrinsic to add currency without bridge, to be removed + #[pallet::call_index(99)] + #[pallet::weight(T::WeightInfo::create_currency())] + pub fn deposit_currency_dummy( + origin: OriginFor, + fusion_address: FusionAddress, + currency_id: CurrencyId, + amount: FusionCurrencyBalance, + ) -> DispatchResult { + ensure_signed(origin)?; + Self::do_deposit_currency(fusion_address, currency_id, amount)?; + Ok(()) + } + + /// Creates a new currency + #[pallet::call_index(0)] + #[pallet::weight(T::WeightInfo::create_currency())] + pub fn create_currency( + origin: OriginFor, + currency_id: CurrencyId, + name: BoundedVec, + nb_decimals: u8, + max_amount: FusionCurrencyBalance, + min_amount: FusionCurrencyBalance, + initial_conversion_rate: BalanceOf, + ) -> DispatchResult { + ensure_root(origin)?; + + ensure!( + !Currencies::::contains_key(currency_id), + Error::::CurrencyAlreadyExists + ); + if currency_id != 0 { + ensure!( + Currencies::::contains_key(AVAIL_CURRENCY_ID), + Error::::EntityZeroDoesNotExist + ); + } + + ensure!(name.len() > 0, Error::::InvalidName); + ensure!(nb_decimals > 0, Error::::InvalidNumberOfDecimals); + ensure!( + max_amount > 0 && max_amount > min_amount, + Error::::InvalidMaxNumber + ); + ensure!( + initial_conversion_rate > BalanceOf::::zero(), + Error::::InvalidConversionRate + ); + + if currency_id == AVAIL_CURRENCY_ID { + ensure!(min_amount == 0, Error::::NoMinAmountForAvailCurrency); + } + + // Fill pallet main account with ED if empty + Self::ensure_account_has_ed(&Self::avail_account()); + + let new_currency = FusionCurrency:: { + name: name.clone(), + nb_decimals, + total_staked_native: 0, + total_slashed_native: 0, + total_unbonding_native: 0, + max_amount, + min_amount, + is_destroyed: false, + }; + + Currencies::::insert(currency_id, new_currency); + CurrencyRates::::insert( + T::StakingFusionDataProvider::active_era(), + currency_id, + initial_conversion_rate, + ); + CurrencyRateChanges::::insert(currency_id, initial_conversion_rate); + + Self::deposit_event(Event::CurrencyCreated { + currency_id, + name, + nb_decimals, + min_amount, + max_amount, + initial_conversion_rate, + }); + + Ok(()) + } + + /// Updates an existing currency + #[pallet::call_index(1)] + #[pallet::weight(T::WeightInfo::set_currency())] + pub fn set_currency( + origin: OriginFor, + currency_id: CurrencyId, + name: Option>, + max_amount: Option, + min_amount: Option, + ) -> DispatchResult { + ensure_root(origin)?; + + Currencies::::try_mutate(currency_id, |currency_opt| { + let currency = currency_opt.as_mut().ok_or(Error::::CurrencyNotFound)?; + + ensure!(!currency.is_destroyed, Error::::CurrencyDestroyed); + + if let Some(name) = name.clone() { + ensure!(name.len() > 0, Error::::InvalidName); + currency.name = name; + } + + if let Some(max_amount) = max_amount { + ensure!(max_amount > 0, Error::::InvalidMaxNumber); + let total_staked_and_unbonding = currency + .total_staked_native + .saturating_add(currency.total_unbonding_native); + ensure!( + max_amount >= total_staked_and_unbonding, + Error::::InvalidMaxAmount + ); + currency.max_amount = max_amount; + } + + if let Some(min_amount) = min_amount { + ensure!( + min_amount <= currency.max_amount, + Error::::InvalidMinAmount + ); + ensure!( + currency_id != AVAIL_CURRENCY_ID || min_amount == 0, + Error::::NoMinAmountForAvailCurrency + ); + currency.min_amount = min_amount; + } + + Self::deposit_event(Event::CurrencySet { + currency_id, + name, + min_amount, + max_amount, + }); + + Ok(()) + }) + } + + /// Deletes a currency + #[pallet::call_index(2)] + #[pallet::weight(T::WeightInfo::destroy_currency())] + pub fn destroy_currency(origin: OriginFor, currency_id: CurrencyId) -> DispatchResult { + ensure_root(origin)?; + + let pool_exists = Pools::::iter().any(|(_, pool)| pool.currency_id == currency_id); + ensure!(!pool_exists, Error::::PoolExistsForCurrency); + + ensure!( + currency_id != AVAIL_CURRENCY_ID, + Error::::CannotDestroyAvailCurrency + ); + + Currencies::::try_mutate(currency_id, |currency_opt| { + let currency = currency_opt.as_mut().ok_or(Error::::CurrencyNotFound)?; + ensure!(!currency.is_destroyed, Error::::CurrencyDestroyed); + currency.is_destroyed = true; + CurrencyRateChanges::::remove(currency_id); // CurrencyRates will clean itself using history depth + Self::deposit_event(Event::CurrencyDeleted { currency_id }); + Ok(()) + }) + } + + /// Sets the conversion rate for a currency for the next era + #[pallet::call_index(3)] + #[pallet::weight(T::WeightInfo::set_currency_conversion_rate())] + pub fn set_currency_conversion_rate( + origin: OriginFor, + currency_id: CurrencyId, + conversion_rate: BalanceOf, + ) -> DispatchResult { + ensure_root(origin)?; + + ensure!( + conversion_rate > BalanceOf::::zero(), + Error::::InvalidConversionRate + ); + + Currencies::::try_get(currency_id) + .map_err(|_| Error::::CurrencyNotFound) + .and_then(|currency| { + ensure!(!currency.is_destroyed, Error::::CurrencyDestroyed); + Ok(()) + })?; + + CurrencyRateChanges::::insert(currency_id, conversion_rate); + + Self::deposit_event(Event::CurrencyConversionRateSet { + currency_id, + conversion_rate, + }); + + Ok(()) + } + + /// Creates a new fusion pool + #[pallet::call_index(4)] + #[pallet::weight(T::WeightInfo::create_pool())] + pub fn create_pool( + origin: OriginFor, + pool_id: PoolId, + currency_id: CurrencyId, + apy: Perbill, + nominator: Option, + ) -> DispatchResult { + ensure_root(origin)?; + + ensure!( + !Pools::::contains_key(pool_id), + Error::::PoolAlreadyExists + ); + if pool_id != 0 { + ensure!( + Pools::::contains_key(AVAIL_POOL_ID), + Error::::EntityZeroDoesNotExist + ); + } + + ensure!(apy > Perbill::zero(), Error::::InvalidAPY); + + let currency = Currencies::::get(currency_id).ok_or(Error::::CurrencyNotFound)?; + ensure!(!currency.is_destroyed, Error::::CurrencyDestroyed); + + let funds_account = Self::get_pool_funds_account(pool_id); + let claimable_account = Self::get_pool_claimable_account(pool_id); + + Self::ensure_account_has_ed(&funds_account); + Self::ensure_account_has_ed(&claimable_account); + + let new_pool = FusionPool:: { + currency_id, + apy, + funds_account: funds_account.clone(), + claimable_account: claimable_account.clone(), + state: FusionPoolState::Paused, + nominator: nominator.clone(), + members: BoundedVec::default(), + targets: BoundedVec::default(), + total_staked_native: 0, + total_staked_points: 0, + total_slashed_native: 0, + total_unbonding_native: 0, + pending_slashes: BoundedVec::default(), + boost_data: None, + }; + + PoolsAccountToId::::insert(&new_pool.funds_account, pool_id); + Pools::::insert(pool_id, new_pool); + + Self::deposit_event(Event::PoolCreated { + pool_id, + currency_id, + apy, + state: FusionPoolState::Paused, + nominator, + funds_account, + claimable_account, + }); + + Ok(()) + } + + /// Updates an existing fusion pool + /// If some rewards were missed due to low balance in account, + /// `retry_rewards_for_era` can be used to generate those missing rewards. + /// This can only be used to pause all pools using a batch call. + #[pallet::call_index(5)] + #[pallet::weight(({ + let nb_retry_eras = retry_rewards_for_eras + .as_ref() + .map_or(0, |eras| eras.len() as u32); + if nb_retry_eras > 0 { + T::WeightInfo::set_pool() + } else { + T::WeightInfo::set_pool_with_retry(nb_retry_eras) + } + }, DispatchClass::Normal))] + pub fn set_pool( + origin: OriginFor, + pool_id: PoolId, + apy: Option, + state: Option, + nominator: ConfigOp, + boost_data: ConfigOp<(Perbill, FusionCurrencyBalance)>, // Additional apy, min to earn + retry_rewards_for_eras: Option>>, + ) -> DispatchResult { + ensure_root(origin)?; + + Pools::::try_mutate(pool_id, |maybe_pool| -> DispatchResult { + let pool = maybe_pool.as_mut().ok_or(Error::::PoolNotFound)?; + + let is_only_retry = retry_rewards_for_eras.is_some() + && apy.is_none() + && state.is_none() + && matches!(nominator, ConfigOp::Noop) + && matches!(boost_data, ConfigOp::Noop); + + ensure!( + pool.state != FusionPoolState::Destroying || is_only_retry, + Error::::PoolIsDestroying + ); + + if let Some(apy) = apy { + ensure!(apy > Perbill::zero(), Error::::InvalidAPY); + pool.apy = apy; + } + + if let Some(state) = state { + ensure!( + state != FusionPoolState::Destroying, + Error::::CannotSetPoolToDestroying + ); + if state == FusionPoolState::Open || state == FusionPoolState::Blocked { + ensure!(pool.targets.len() > 0, Error::::PoolIsNotNominating); + let currency = Currencies::::get(pool.currency_id) + .ok_or(Error::::CurrencyNotFound)?; + ensure!(!currency.is_destroyed, Error::::CurrencyDestroyed); + } + + pool.state = state; + } + + pool.nominator = match nominator.clone() { + ConfigOp::Noop => pool.nominator.clone(), + ConfigOp::Remove => None, + ConfigOp::Set(value) => Some(value), + }; + + match boost_data { + ConfigOp::Remove => pool.set_boost(pool_id, None)?, + ConfigOp::Set(value) => pool.set_boost(pool_id, Some(value))?, + _ => { /* Do Nothing */ }, + }; + + Ok(()) + })?; + + if let Some(retry_rewards_for_eras) = retry_rewards_for_eras { + retry_rewards_for_eras + .into_iter() + .try_for_each(|era| -> DispatchResult { + let era_duration = + EraDurations::::get(era).ok_or(Error::::EraDurationNotFound)?; + Self::compute_era_rewards(era, era_duration, Some(pool_id)); + Ok(()) + })?; + } + + // Emit an event for pool update + Self::deposit_event(Event::PoolSet { + pool_id, + apy, + state, + nominator, + boost_data, + }); + + Ok(()) + } + + /// Deletes a pool + /// Called once to set the pool to destroying + /// Called a second time when everything is cleaned to actually destroy it + #[pallet::call_index(6)] + #[pallet::weight(T::WeightInfo::destroy_pool())] + pub fn destroy_pool( + origin: OriginFor, + pool_id: PoolId, + leftover_destination: Option, + ) -> DispatchResult { + ensure_root(origin)?; + + if pool_id == AVAIL_POOL_ID { + ensure!( + Pools::::iter_keys().count() == 1, + Error::::OtherPoolsExist + ) + } + + Pools::::try_mutate(pool_id, |maybe_pool| -> DispatchResult { + let pool = maybe_pool.as_mut().ok_or(Error::::PoolNotFound)?; + + if pool.state != FusionPoolState::Destroying { + pool.state = FusionPoolState::Destroying; + Self::deposit_event(Event::PoolDestroying { pool_id }); + } else { + let leftover = + Self::check_and_cleanup_pool(pool_id, pool, leftover_destination)?; + *maybe_pool = None; + Self::deposit_event(Event::PoolDeleted { pool_id, leftover }); + } + + Ok(()) + }) + } + + /// Fills the funds account with the specified amount of funds. + #[pallet::call_index(7)] + #[pallet::weight(T::WeightInfo::fill_pool_account())] + pub fn fill_pool_account( + origin: OriginFor, + pool_id: PoolId, + amount: BalanceOf, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + ensure!(amount > BalanceOf::::zero(), Error::::InvalidAmount); + + let funds_account = Self::get_pool_funds_account(pool_id); + + T::Currency::transfer( + &who, + &funds_account, + amount, + ExistenceRequirement::KeepAlive, + )?; + + Self::deposit_event(Event::FundsAccountFilled { + sender: who, + amount, + }); + + Ok(()) + } + + /// Nominates a list of validators for a given pool. + #[pallet::call_index(8)] + #[pallet::weight(T::WeightInfo::nominate())] + pub fn nominate( + origin: OriginFor, + pool_id: PoolId, + targets: BoundedVec, + ) -> DispatchResult { + // Check if the origin is root, if not, check if it's a signed origin. + let who = ensure_signed_or_root(origin)?; + + // Fetch the pool and ensure it exists + Pools::::try_mutate(pool_id, |pool_opt| -> DispatchResult { + let pool = pool_opt.as_mut().ok_or(Error::::PoolNotFound)?; + + // If the caller is not root, ensure it's the nominator of the pool + if let Some(who) = who { + ensure!( + Some(&who) == pool.nominator.as_ref(), + Error::::NotAuthorized + ); + } + + // We cannot change nominations if the pool is destroying + ensure!( + pool.state != FusionPoolState::Destroying, + Error::::PoolIsDestroying + ); + + // If the pool is open or blocked, nomination must not be empty + if pool.state == FusionPoolState::Open || pool.state == FusionPoolState::Blocked { + ensure!(targets.len() > 0, Error::::ActivePoolNeedsTargets); + } + + // Check that targets contains only validators + ensure!( + targets + .iter() + .all(|target| T::StakingFusionDataProvider::is_valid_validator(target)), + Error::::NoValidValidators + ); + + // Update the targets of the pool + pool.targets = targets.clone(); + + // Emit event for nomination + Self::deposit_event(Event::Nominated { pool_id, targets }); + + Ok(()) + }) + } + + /// Change the Substrate controller address. + #[pallet::call_index(9)] + #[pallet::weight(T::WeightInfo::set_controller_address())] + pub fn set_controller_address( + origin: OriginFor, + fusion_address: FusionAddress, + new_controller_address: Option, + ) -> DispatchResult { + if let Some(who) = ensure_signed_or_root(origin)? { + // TODO - commented for tests only + // Self::ensure_valid_fusion_origin(who, fusion_address)?; + let _ = Self::ensure_valid_fusion_origin(who, fusion_address); + } else { + // TODO - commented for tests only + // ensure!( + // new_controller_address.is_none(), + // Error::::RootCanOnlyRemoveController + // ); + } + + let slash_destination = SlashDestination::::get(); + if let Some(slash_address) = slash_destination { + ensure!( + fusion_address != slash_address, + Error::::CannotSetControllerForSlashDestination + ); + } + + Self::do_set_controller_address(fusion_address, new_controller_address)?; + Ok(()) + } + + /// Change the Slash destination Fusion address. + #[pallet::call_index(10)] + #[pallet::weight(T::WeightInfo::set_slash_destination())] + pub fn set_slash_destination( + origin: OriginFor, + fusion_address: Option, + controller_address: Option, + ) -> DispatchResult { + ensure_root(origin)?; + + if let Some(fusion_address) = fusion_address { + SlashDestination::::put(fusion_address); + Self::do_set_controller_address(fusion_address, controller_address.clone())?; + } else { + if let Some(current_address) = SlashDestination::::get() { + Self::do_set_controller_address(current_address, None)?; + } + SlashDestination::::kill(); + } + + Self::deposit_event(Event::SlashDestinationSet { + fusion_address, + controller_address, + }); + + Ok(()) + } + + /// Updates the maximum TVL authorized in the Fusion pallet. + #[pallet::call_index(11)] + #[pallet::weight(T::WeightInfo::update_max_tvl())] + pub fn update_max_tvl(origin: OriginFor, new_max_tvl: BalanceOf) -> DispatchResult { + ensure_root(origin)?; + let mut tvl_data = >::get(); + ensure!( + new_max_tvl >= tvl_data.total_value_locked, + Error::::MaxTVLReached + ); + tvl_data.max_total_value_locked = new_max_tvl; + >::put(tvl_data); + Self::deposit_event(Event::MaxTVLUpdated(new_max_tvl)); + Ok(()) + } + + /// Set the destination of the reward for the user. + #[pallet::call_index(12)] + #[pallet::weight(T::WeightInfo::set_compounding())] + pub fn set_compounding( + origin: OriginFor, + fusion_address: FusionAddress, + pool_id: PoolId, + compound: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::ensure_valid_fusion_origin(who, fusion_address)?; + Self::do_set_compounding(fusion_address, pool_id, compound)?; + Ok(()) + } + + /// Stake currency into a pool, either by joining or bonding extra. + #[pallet::call_index(13)] + #[pallet::weight(T::WeightInfo::stake())] + pub fn stake( + origin: OriginFor, + fusion_address: FusionAddress, + pool_id: PoolId, + amount: FusionCurrencyBalance, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::ensure_valid_fusion_origin(who, fusion_address)?; + Self::do_stake(fusion_address, pool_id, amount, false)?; + Ok(()) + } + + /// Claims the rewards for an Fusion address for a specific era and pool. + #[pallet::call_index(14)] + #[pallet::weight(T::WeightInfo::claim_rewards())] + pub fn claim_rewards( + origin: OriginFor, + era: EraIndex, + pool_id: PoolId, + fusion_address: FusionAddress, + ) -> DispatchResult { + ensure_signed(origin)?; + Self::do_claim_rewards(era, pool_id, fusion_address) + } + + /// Unbonds an amount of currency from a pool + #[pallet::call_index(15)] + #[pallet::weight(T::WeightInfo::unbond_currency())] + pub fn unbond_currency( + origin: OriginFor, + fusion_address: FusionAddress, + pool_id: PoolId, + unbond_amount: Option, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::ensure_valid_fusion_origin(who, fusion_address)?; + Self::do_unbond(fusion_address, pool_id, unbond_amount, false)?; + Ok(()) + } + + /// Withdraws unbonded currency after the bonding duration has passed. + #[pallet::call_index(16)] + #[pallet::weight(T::WeightInfo::withdraw_unbonded_currency())] + pub fn withdraw_unbonded_currency( + origin: OriginFor, + fusion_address: FusionAddress, + pool_id: PoolId, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::ensure_valid_fusion_origin(who, fusion_address)?; + Self::do_withdraw_unbonded_currency(fusion_address, pool_id, false)?; + Ok(()) + } + + /// Unbonds an amount of currency from a pool on behalf on another user + /// Only works if the pool is destroying + #[pallet::call_index(17)] + #[pallet::weight(T::WeightInfo::unbond_currency())] + pub fn unbond_currency_other( + origin: OriginFor, + fusion_address: FusionAddress, + pool_id: PoolId, + ) -> DispatchResult { + ensure_signed(origin)?; + Self::do_unbond(fusion_address, pool_id, None, true)?; + Ok(()) + } + + /// Withdraws unbonded currency after the bonding duration has passed. + /// Only works if the pool is destroying + #[pallet::call_index(18)] + #[pallet::weight(T::WeightInfo::withdraw_unbonded_currency())] + pub fn withdraw_unbonded_currency_other( + origin: OriginFor, + fusion_address: FusionAddress, + pool_id: PoolId, + ) -> DispatchResult { + ensure_signed(origin)?; + Self::do_withdraw_unbonded_currency(fusion_address, pool_id, true)?; + Ok(()) + } + + /// Withdraws unbonded Avail Fusion Currency to the controller account. + /// Only works for avail pool + #[pallet::call_index(19)] + #[pallet::weight(T::WeightInfo::withdraw_avail_to_controller())] + pub fn withdraw_avail_to_controller( + origin: OriginFor, + fusion_address: FusionAddress, + amount: FusionCurrencyBalance, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::ensure_valid_fusion_origin(who, fusion_address)?; + Self::do_withdraw_avail_to_controller(fusion_address, amount)?; + Ok(()) + } + + /// Extrinsic to allow user to setup boost pool allocations + #[pallet::call_index(20)] + #[pallet::weight(T::WeightInfo::set_pool_boost_allocations())] + pub fn set_pool_boost_allocations( + origin: OriginFor, + fusion_address: FusionAddress, + pool_ids: BoundedVec>, + ) -> DispatchResult { + let mut is_root = false; + if let Some(who) = ensure_signed_or_root(origin)? { + Self::ensure_valid_fusion_origin(who, fusion_address)?; + } else { + is_root = true; + } + Self::do_set_pool_boost_allocations(fusion_address, pool_ids, is_root)?; + Ok(()) + } + + /// Retrieve funds from a pool account. + #[pallet::call_index(21)] + #[pallet::weight(T::WeightInfo::withdraw_pool_account())] + pub fn withdraw_pool_account( + origin: OriginFor, + pool_id: PoolId, + amount: BalanceOf, + dest: T::AccountId, + ) -> DispatchResult { + ensure_root(origin)?; + + ensure!(amount > BalanceOf::::zero(), Error::::InvalidAmount); + + let funds_account = Self::get_pool_funds_account(pool_id); + + let existence_requirement = if Pools::::get(pool_id) + .map_or(false, |pool| pool.state != FusionPoolState::Destroying) + { + ExistenceRequirement::KeepAlive + } else { + ExistenceRequirement::AllowDeath + }; + + T::Currency::transfer(&funds_account, &dest, amount, existence_requirement)?; + + Self::deposit_event(Event::FundsAccountWithdrawn { + recipient: dest, + amount, + }); + + Ok(()) + } + + /// Deposit native AVAIL into the Fusion balance for a FusionAddress. + /// Only callable from a signed Substrate (non-EVM) account which must be the controller + /// of the given FusionAddress. + #[pallet::call_index(22)] + #[pallet::weight(T::WeightInfo::deposit_avail_to_fusion())] + pub fn deposit_avail_to_fusion( + origin: OriginFor, + fusion_address: FusionAddress, + amount: BalanceOf, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::ensure_valid_fusion_origin(who.clone(), fusion_address)?; + + ensure!(!amount.is_zero(), Error::::InvalidAmount); + + let currency = + Currencies::::get(AVAIL_CURRENCY_ID).ok_or(Error::::CurrencyNotFound)?; + + let avail_in_currency = currency.avail_to_currency(AVAIL_CURRENCY_ID, amount, None)?; + let pallet_avail = Self::avail_account(); + T::Currency::transfer(&who, &pallet_avail, amount, ExistenceRequirement::KeepAlive)?; + + Self::add_to_currency_balance( + fusion_address, + AVAIL_CURRENCY_ID, + avail_in_currency, + true, + )?; + + Self::deposit_event(Event::CurrencyDeposited { + fusion_address, + currency_id: AVAIL_CURRENCY_ID, + amount: avail_in_currency, + }); + + Ok(()) + } + } +} + +impl Pallet { + /// Avail fusion currency account holds the native avail corresponding to the equivalent in Avail Fusion currency + pub fn avail_account() -> T::AccountId { + T::PalletId::get().into_sub_account_truncating(FusionAccountType::AvailCurrency) + } + + /// Helper to convert u128 to U256 + pub fn u256(value: u128) -> U256 { + U256::from(value) + } + + /// Helper to convert U256 to balance + pub fn balance(value: U256) -> BalanceOf { + let value: u128 = value.try_into().unwrap_or(u128::MAX); + value.try_into().unwrap_or(BalanceOf::::max_value()) + } + + /// Helper to convert U256 to fusion currency + pub fn fusion_currency(value: U256) -> FusionCurrencyBalance { + value.try_into().unwrap_or(u128::MAX) + } + + /// Helper to convert U256 to points + pub fn points(value: U256) -> Points { + value.try_into().unwrap_or(u128::MAX) + } + + /// Ensures the origin is signed and that the provided Fusion address maps to the correct Substrate account. + pub fn ensure_valid_fusion_origin( + who: T::AccountId, + fusion_address: FusionAddress, + ) -> DispatchResult { + let mapped_address = FusionAddressToSubstrateAddress::::get(fusion_address) + .ok_or(Error::::InvalidSubstrateAddress)?; + ensure!(who == mapped_address, Error::::InvalidSubstrateAddress); + Ok(()) + } + + /// Adds the fusion currency amount to the user's idle balance for a specific currency. + pub fn add_to_currency_balance( + fusion_address: FusionAddress, + currency_id: CurrencyId, + amount: FusionCurrencyBalance, + skip_check: bool, + ) -> DispatchResult { + if !skip_check { + let _ = Currencies::::get(currency_id).ok_or(Error::::CurrencyNotFound)?; + } + UserCurrencyBalances::::mutate(fusion_address, currency_id, |balance_opt| { + if let Some(balance) = balance_opt { + balance.amount = balance.amount.saturating_add(amount); + } else { + *balance_opt = Some(FusionUserCurrencyBalance { + fusion_address, + currency_id, + amount, + }); + } + }); + + Ok(()) + } + + /// Withdraw the fusion currency amount from the user's idle balance for a specific currency. + pub fn withdraw_from_currency_balance( + fusion_address: FusionAddress, + currency_id: CurrencyId, + amount: FusionCurrencyBalance, + ) -> DispatchResult { + UserCurrencyBalances::::try_mutate( + fusion_address, + currency_id, + |balance_opt| -> DispatchResult { + let balance = balance_opt + .as_mut() + .ok_or(Error::::NoCurrencyBalanceForUser)?; + ensure!( + balance.amount >= amount, + Error::::NotEnoughCurrencyBalanceForUser + ); + + balance.amount = balance.amount.saturating_sub(amount); + + if balance.amount == 0 { + *balance_opt = None; + } + + Ok(()) + }, + ) + } + + /// Function to check if a pool should be removed and perform cleanup if necessary + pub fn check_and_cleanup_pool( + pool_id: PoolId, + pool: &FusionPool, + leftover_destination: Option, + ) -> Result, DispatchError> { + let has_no_members = pool.members.is_empty(); + let has_no_points = pool.total_staked_points == 0; + let has_no_staked_native = pool.total_staked_native == 0; + let has_no_unbonding_native = pool.total_unbonding_native == 0; + + // Ensure the pool is ready for cleanup + ensure!( + has_no_members && has_no_points && has_no_staked_native && has_no_unbonding_native, + Error::::PoolCannotBeCleaned + ); + + // We do this check after because it is costlier so we prefer to not do it everytime + ensure!( + !Self::pool_has_unclaimed_rewards(pool_id), + Error::::PoolCannotBeCleaned + ); + + let destination = leftover_destination.ok_or(Error::::NoLeftoverDestinationProvided)?; + let zero = BalanceOf::::zero(); + + // Retrieve balances of funds account and send to the leftover destination + let funds_balance = T::Currency::free_balance(&pool.funds_account); + if funds_balance > zero { + // Transfer funds from funds_account to leftover_destination + T::Currency::transfer( + &pool.funds_account, + &destination, + funds_balance, + ExistenceRequirement::AllowDeath, + )?; + } + + // Retrieve balances of claimable account and send to the leftover destination + let claimable_balance = T::Currency::free_balance(&pool.claimable_account); + if claimable_balance > zero { + // Transfer funds from claimable_account to leftover_destination + T::Currency::transfer( + &pool.claimable_account, + &destination, + claimable_balance, + ExistenceRequirement::AllowDeath, + )?; + } + + for key in EraRewards::::iter_keys() { + if key.1 == pool_id { + EraRewards::::remove(key.0, key.1); + } + } + for key in Exposures::::iter_keys() { + if key.1 == pool_id { + Exposures::::remove(key.0, key.1); + } + } + for key in ClaimedRewards::::iter_keys() { + if key.1 .0 == pool_id { + ClaimedRewards::::remove(key.0, key.1); + } + } + + PoolsAccountToId::::remove(&pool.funds_account); + PoolsWithBoost::::remove(pool_id); + + Ok(funds_balance.saturating_add(claimable_balance)) + } + + /// Returns true if the pool has unclaimed rewards + fn pool_has_unclaimed_rewards(pool_id: PoolId) -> bool { + let active_era = T::StakingFusionDataProvider::active_era(); + let history_depth = T::HistoryDepth::get(); + let start_era = active_era.saturating_sub(history_depth); + + for era in start_era..active_era { + if let Some(reward) = EraRewards::::get(era, pool_id) { + if reward.rewards != reward.claimed_rewards + || reward.additional_rewards != reward.additional_claimed_rewards + { + return true; + } + } + } + + false + } + + /// Setup the fusion currency rates for the new era + pub fn setup_currency_rates(era: EraIndex) -> DispatchResult { + for (currency_id, currency) in Currencies::::iter() { + // Skip if the currency is destroyed + if currency.is_destroyed { + continue; + } + + // Get the new rate from the rate changes storage + let rate = CurrencyRateChanges::::get(currency_id); + + // Insert the rate for the next era + CurrencyRates::::insert(era.saturating_add(1), currency_id, rate); + } + Ok(()) + } + + /// Clean history depth storages and send old pending rewards to 'RewardRemainder' + pub fn clean_history_depth_storages(era: EraIndex) -> DispatchResult { + let history_depth = T::HistoryDepth::get(); + + let Some(era_to_clear) = era.checked_sub(history_depth) else { + return Ok(()); + }; + + // Clean Exposures - u32::MAX is safe knowing the maximum number of pools is low + let _ = Exposures::::clear_prefix(era_to_clear, u32::MAX, None); + + // Clean PoolsBackingValidator - u32::MAX is safe knowing the maximum number of pools is low + let _ = PoolsBackingValidator::::clear_prefix(era_to_clear, u32::MAX, None); + + // Clean old era durations + EraDurations::::remove(era_to_clear); + + // Clean currency rates + let _ = CurrencyRates::::clear_prefix(era_to_clear, u32::MAX, None); + + // Clean claimed rewards + let _ = ClaimedRewards::::clear_prefix(era_to_clear, u32::MAX, None); + + // Clean slashes that did not get applied, this means a bug happened and should be fixed. + for ((validator, funds_account), nb_pending_slash) in + HasPendingSlash::::iter_prefix(era_to_clear) + { + if nb_pending_slash > 0 { + let Some(pool_id) = Self::get_pool_id_from_funds_account(&funds_account) else { + continue; + }; + let _ = Pools::::try_mutate(pool_id, |pool_opt| -> DispatchResult { + let pool = pool_opt.as_mut().ok_or(Error::::PoolNotFound)?; + pool.pending_slashes.retain(|slash| { + !(slash.slash_era == era_to_clear && slash.validator == validator) + }); + Ok(()) + }); + } + } + let _ = HasPendingSlash::::clear_prefix(era_to_clear, u32::MAX, None); + + // Clean fusion era rewards and compute remaining rewards + let existential_deposit = T::Currency::minimum_balance(); + let mut total_remaining = BalanceOf::::zero(); + EraRewards::::drain_prefix(era_to_clear).for_each(|(pool_id, rewards)| { + let remaining_rewards = rewards.rewards.saturating_sub(rewards.claimed_rewards); + if remaining_rewards > BalanceOf::::zero() { + let claimable_account = Self::get_pool_claimable_account(pool_id); + let claimable_balance = T::Currency::free_balance(&claimable_account) + .saturating_sub(existential_deposit); + if claimable_balance > remaining_rewards { + let imbalance = T::Currency::withdraw( + &claimable_account, + remaining_rewards, + WithdrawReasons::all(), + ExistenceRequirement::KeepAlive, + ); + if let Ok(imbalance) = imbalance { + T::RewardRemainder::on_unbalanced(imbalance); + total_remaining = total_remaining.saturating_add(remaining_rewards); + } + } + } + }); + if total_remaining > BalanceOf::::zero() { + Self::deposit_event(Event::RewardRemainderSent { + amount: total_remaining, + }); + } + + Ok(()) + } + + /// Compute rewards for each pool and set them in storage + /// Reward computatation is done at the end of era N for era N + pub fn compute_era_rewards(era: EraIndex, era_duration: u64, maybe_pool_id: Option) { + let mut total_rewarded = BalanceOf::::zero(); + let mut rewarded_pools: Vec = vec![]; + let mut paused_pools: Vec = vec![]; + let mut paused_pools_missed_rewards: Vec> = vec![]; + let existential_deposit = T::Currency::minimum_balance(); + + let exposures_iter = + Exposures::::iter_prefix(era).filter(|(pool_id, _)| match maybe_pool_id { + Some(ref id) => pool_id == id, + None => true, + }); + + let is_retry = maybe_pool_id.is_some(); + + for (pool_id, fusion_exposure) in exposures_iter { + let Some(mut pool) = Pools::::get(pool_id) else { + Self::deposit_event(Event::ErrorDataEvent { + detail: format!("Pool with PoolId {:?} not found for Era {:?}. Reward could not have been set.", pool_id, era) + }); + continue; + }; + + if fusion_exposure.total_avail.is_zero() + || fusion_exposure.user_points.is_empty() + || fusion_exposure.targets.is_empty() + || Perbill::is_zero(&fusion_exposure.apy) + || EraRewards::::get(era, pool_id).is_some() + { + // No need to pause the pool cause it's just not supposed to get rewards. + continue; + } + + // Era reward computation for a pool + let apy = fusion_exposure.apy; + let fraction_of_year = Perbill::from_rational(era_duration, MILLISECONDS_PER_YEAR); + let total_avail = fusion_exposure.total_avail; + let total_avail_reward_for_year = apy * total_avail; + let pool_era_reward = fraction_of_year * total_avail_reward_for_year; + + // Boost era reward computation for a pool + let mut boost_reward = BalanceOf::::default(); + if fusion_exposure.boost_members.len() > 0 + && fusion_exposure.boost_total_points > 0 + && fusion_exposure.boost_additional_apy > Perbill::zero() + && fusion_exposure.boost_total_avail > BalanceOf::::zero() + { + let boost_additional_apy = fusion_exposure.boost_additional_apy; + let boost_total_avail = fusion_exposure.boost_total_avail; + let total_avail_reward_for_year = boost_additional_apy * boost_total_avail; + boost_reward = fraction_of_year * total_avail_reward_for_year; + } + + // Check that the pool actually backed a validator and that this validator has earned points during the era + let mut should_earn_rewards = false; + if is_retry { + should_earn_rewards = true; + } + if !should_earn_rewards { + if let Some(native_exposure_data) = fusion_exposure.native_exposure_data { + let validators_backed: Vec = native_exposure_data + .into_iter() + .map(|(account_id, _balance)| account_id) + .collect(); + should_earn_rewards = T::StakingFusionDataProvider::has_earned_era_points( + era, + &validators_backed, + ); + } + } + + if !should_earn_rewards { + Self::pause_pool( + pool_id, + &mut pool, + "Fusion pool selected validators have not earned rewards", + &mut paused_pools, + &mut paused_pools_missed_rewards, + pool_era_reward, + ); + continue; + } + + // Get the pool funds balances + let pool_funds_balance = T::Currency::free_balance(&pool.funds_account); + let era_rewards_with_boost = pool_era_reward.saturating_add(boost_reward); + + // In case of insufficient balance in pool account, we pause the pool + // This means the reward won't get paid for this era. + if era_rewards_with_boost > pool_funds_balance.saturating_sub(existential_deposit) { + Self::pause_pool( + pool_id, + &mut pool, + "Insufficient funds in fusion pool account.", + &mut paused_pools, + &mut paused_pools_missed_rewards, + era_rewards_with_boost, + ); + continue; + } + + if T::Currency::transfer( + &pool.funds_account, + &pool.claimable_account, + era_rewards_with_boost, + ExistenceRequirement::KeepAlive, + ) + .is_err() + { + Self::pause_pool( + pool_id, + &mut pool, + "An error has occured during transfer from pool funds account to claimable account.", + &mut paused_pools, + &mut paused_pools_missed_rewards, + era_rewards_with_boost, + ); + continue; + } + + total_rewarded = total_rewarded.saturating_add(era_rewards_with_boost); + + EraRewards::::insert( + era, + pool_id, + EraReward { + rewards: pool_era_reward, + claimed_rewards: BalanceOf::::default(), + additional_rewards: boost_reward, + additional_claimed_rewards: BalanceOf::::default(), + }, + ); + + rewarded_pools.push(pool_id); + } + + // Record Era duration in case we need it later, eg. for a retry + if EraDurations::::get(era).is_none() { + EraDurations::::insert(era, era_duration); + } + + if !rewarded_pools.is_empty() || !paused_pools.is_empty() { + Self::deposit_event(Event::RewardSet { + era, + rewarded_pools, + paused_pools, + total_rewarded, + paused_pools_missed_rewards, + retry: maybe_pool_id.is_some(), + }); + } + } + + pub fn pause_pool( + pool_id: PoolId, + pool: &mut FusionPool, + reason: &str, + paused_pools: &mut Vec, + paused_pools_missed_rewards: &mut Vec>, + pool_era_reward: BalanceOf, + ) { + if pool.is_active() { + Self::deposit_event(Event::ErrorDataEvent { + detail: format!("Pausing pool {:?}: {}.", pool_id, reason), + }); + pool.state = FusionPoolState::Paused; + Pools::::insert(pool_id, pool); + paused_pools.push(pool_id); + paused_pools_missed_rewards.push(pool_era_reward); + } + } + + /// Increase total value locked in avail + pub fn add_to_tvl( + currency_id: CurrencyId, + currency: &FusionCurrency, + value: FusionCurrencyBalance, + ) -> DispatchResult { + let mut tvl_data = TotalValueLockedData::::get(); + let avail_value = currency.currency_to_avail(currency_id, value, None)?; + tvl_data.add(avail_value)?; + TotalValueLockedData::::put(tvl_data); + Ok(()) + } + + /// Decrease total value locked in avail + pub fn sub_from_tvl( + currency_id: CurrencyId, + currency: &FusionCurrency, + value: FusionCurrencyBalance, + ) -> DispatchResult { + let mut tvl_data = TotalValueLockedData::::get(); + let avail_value = currency.currency_to_avail(currency_id, value, None)?; + tvl_data.sub(avail_value); + TotalValueLockedData::::put(tvl_data); + Ok(()) + } + + /// Deposits a specified amount of currency for a given Fusion address and currency ID. + pub fn do_deposit_currency( + fusion_address: FusionAddress, + currency_id: CurrencyId, + amount: FusionCurrencyBalance, + ) -> DispatchResult { + ensure!( + currency_id != AVAIL_CURRENCY_ID, + Error::::CannotDepositAvailCurrency + ); + + Self::add_to_currency_balance(fusion_address, currency_id, amount, false)?; + + Self::deposit_event(Event::CurrencyDeposited { + fusion_address, + currency_id, + amount, + }); + + Ok(()) + } + + /// Sets or unsets a controller address for a specific Fusion address. + pub fn do_set_controller_address( + fusion_address: FusionAddress, + new_controller_address: Option, + ) -> DispatchResult { + if let Some(ref new_controller_address) = new_controller_address { + FusionAddressToSubstrateAddress::::insert(fusion_address, new_controller_address); + } else { + FusionAddressToSubstrateAddress::::remove(fusion_address); + } + + Self::deposit_event(Event::ControllerAddressSet { + fusion_address, + new_controller_address, + }); + + Ok(()) + } + + /// Configures whether the specified Fusion address should compound rewards in a given pool. + pub fn do_set_compounding( + fusion_address: FusionAddress, + pool_id: PoolId, + compound: bool, + ) -> DispatchResult { + Memberships::::try_mutate(fusion_address, pool_id, |membership_opt| { + let membership = membership_opt + .as_mut() + .ok_or(Error::::MembershipNotFound)?; + let pool = Pools::::get(pool_id).ok_or(Error::::PoolNotFound)?; + let currency = + Currencies::::get(pool.currency_id).ok_or(Error::::CurrencyNotFound)?; + let active_currency_balance = + pool.points_to_currency(membership.active_points, Some(¤cy))?; + if compound { + ensure!( + active_currency_balance >= currency.min_amount, + Error::::CannotSetCompoudingWithLessThanMinimum + ) + } + + membership.is_compounding = compound; + + Self::deposit_event(Event::::CompoundingSet { + fusion_address, + pool_id, + compound, + }); + Ok::<(), Error>(()) + })?; + + Ok(()) + } + + /// Stakes a specified amount of currency into a pool for a given Fusion address. + /// If `skip_checks` is true, some checks (like pool state or pallet balance) may be skipped. + pub fn do_stake( + fusion_address: FusionAddress, + pool_id: PoolId, + amount: FusionCurrencyBalance, + skip_checks: bool, + ) -> DispatchResult { + // Fetch pool and currency + let mut pool = Pools::::get(pool_id).ok_or(Error::::PoolNotFound)?; + let mut currency = + Currencies::::get(pool.currency_id).ok_or(Error::::CurrencyNotFound)?; + + let maybe_membership = Memberships::::get(fusion_address, pool_id); + + if !skip_checks { + // Ensure amount is greater than 0 + ensure!(amount > 0, Error::::InvalidAmount); + // Ensure they are open or allowed to compound + ensure!( + pool.state == FusionPoolState::Open + || (pool.state == FusionPoolState::Blocked && maybe_membership.is_some()), + Error::::PoolNotOpen + ); + ensure!(!currency.is_destroyed, Error::::CurrencyDestroyed); + + // Ensure the total staked does not exceed the max allowable amount + ensure!( + currency.total_staked_native.saturating_add(amount) <= currency.max_amount, + Error::::BondWouldExceedMaxForCurrency + ); + } + + // Fetch and ensure user has enough currency balance + Self::withdraw_from_currency_balance(fusion_address, pool.currency_id, amount)?; + + // Convert currency amount to points + let points = pool.currency_to_points(amount, Some(¤cy))?; + + // Common logic to update currency and pool data + currency.total_staked_native = currency.total_staked_native.saturating_add(amount); + pool.total_staked_native = pool.total_staked_native.saturating_add(amount); + pool.total_staked_points = pool.total_staked_points.saturating_add(points); + + // Update TVL + Self::add_to_tvl(pool.currency_id, ¤cy, amount)?; + + // Check if the user is already a member of the pool + if let Some(mut membership) = maybe_membership { + // Update user's active points and save membership + membership.active_points = membership.active_points.saturating_add(points); + + // Ensure user will have more than minimum balance + // Useful if the user was slashed and his balance went below minimum required + // He can only bond to top up to the minimum or withdraw all + let current_amount = + pool.points_to_currency(membership.active_points, Some(¤cy))?; + ensure!( + current_amount.saturating_add(amount) > currency.min_amount, + Error::::BondAmoundTooLow + ); + + // Update the pool's member points + if let Some(member) = pool + .members + .iter_mut() + .find(|(address, _)| *address == fusion_address) + { + member.1 = member.1.saturating_add(points); + } + + // Check if the user has boost in the pool + if let Some(ref mut boost_data) = pool.boost_data { + if HasBoost::::get(pool_id, fusion_address) { + // We add the additional points to the elligible points + boost_data.elligible_total_points = + boost_data.elligible_total_points.saturating_add(points); + } + } + + Memberships::::insert(fusion_address, pool_id, membership); + Pools::::insert(pool_id, &pool); + Currencies::::insert(pool.currency_id, ¤cy); + + // Emit event for extra bond + Self::deposit_event(Event::PoolBondExtra { + fusion_address, + pool_id, + currency_id: pool.currency_id, + amount, + points, + }); + } else { + // Ensure the amount meets the minimum staking requirement + ensure!(amount >= currency.min_amount, Error::::BondAmoundTooLow); + + // Update pool members + pool.members + .try_push((fusion_address, points)) + .map_err(|_| Error::::PoolMemberLimitReached)?; + + // Insert new membership for user + let new_membership = FusionMembership:: { + fusion_address, + joined_era: T::StakingFusionDataProvider::active_era(), + active_points: points, + unbonding_eras: BoundedVec::default(), + is_compounding: true, + }; + Memberships::::insert(fusion_address, pool_id, new_membership); + Pools::::insert(pool_id, &pool); + Currencies::::insert(pool.currency_id, ¤cy); + + // Emit event for pool join + Self::deposit_event(Event::PoolJoined { + fusion_address, + pool_id, + currency_id: pool.currency_id, + amount, + points, + }); + } + + Ok(()) + } + + /// Claims rewards for a specified era and pool for a given Fusion address. + pub fn do_claim_rewards( + era: EraIndex, + pool_id: PoolId, + fusion_address: FusionAddress, + ) -> DispatchResult { + // Get the fusion exposure for the pool and era + let exposure = Exposures::::get(era, pool_id).ok_or(Error::::ExposureNotFound)?; + + EraRewards::::try_mutate(era, pool_id, |maybe_reward| -> DispatchResult { + // Ensure rewards are available for the given era and pool + let era_rewards = maybe_reward.as_mut().ok_or(Error::::NoRewardsForEra)?; + + // Ensure the user has not already claimed the reward for this era and pool + ensure!( + !ClaimedRewards::::contains_key(era, (pool_id, fusion_address)), + Error::::AlreadyClaimed + ); + + let (user_reward_balance, user_points) = + Self::compute_basic_rewards(fusion_address, &exposure, era_rewards)?; + + let boost_rewards = + Self::compute_boost_rewards(fusion_address, &exposure, era_rewards, user_points)?; + + let total_user_rewards = user_reward_balance.saturating_add(boost_rewards); + + ensure!( + total_user_rewards > BalanceOf::::zero(), + Error::::NoRewardsToClaim + ); + + // Fetch avail currency + let avail_currency = + Currencies::::get(AVAIL_CURRENCY_ID).ok_or(Error::::CurrencyNotFound)?; + + // Update the claimed rewards field by adding the user's reward + era_rewards.claimed_rewards = era_rewards + .claimed_rewards + .saturating_add(total_user_rewards); + + // Convert the avail reward to avail currency + let avail_in_currency = avail_currency.avail_to_currency( + AVAIL_CURRENCY_ID, + total_user_rewards, + Some(era), + )?; + + // Transfer claimable avail to avail fusion currency account for holding + let pool_claimable_account = Self::get_pool_claimable_account(pool_id); + + // Check that it has enough funds + let pool_claimable_balance = T::Currency::free_balance(&pool_claimable_account); + let existential_deposit = T::Currency::minimum_balance(); + ensure!( + total_user_rewards <= pool_claimable_balance.saturating_sub(existential_deposit), + Error::::NotEnoughClaimableBalanceInPool + ); + + // Mark rewards as claimed + ClaimedRewards::::insert(era, (pool_id, fusion_address), total_user_rewards); + + // Send the funds to the avail holdings account + T::Currency::transfer( + &pool_claimable_account, + &Self::avail_account(), + total_user_rewards, + ExistenceRequirement::KeepAlive, + )?; + + // We can now add the equivalent in fusion currency + Self::add_to_currency_balance( + fusion_address, + AVAIL_CURRENCY_ID, + avail_in_currency, + true, + )?; + + // Handle compounding or adding to the user's idle balance + let Some(membership) = Memberships::::get(fusion_address, pool_id) else { + return Ok(()); + }; + + // Checks before calling stake + let avail_pool = Pools::::get(AVAIL_POOL_ID).ok_or(Error::::PoolNotFound)?; + let has_avail_membership = + Memberships::::get(fusion_address, AVAIL_POOL_ID).is_some(); + let can_stake_to_pool = avail_pool.state == FusionPoolState::Open + || (avail_pool.state == FusionPoolState::Blocked && has_avail_membership); + let wont_overflow_maximum_amount = avail_currency + .total_staked_native + .saturating_add(avail_in_currency) + <= avail_currency.max_amount; + let wont_overflow_maximum_members = has_avail_membership + || (avail_pool.members.len() as u32) < T::MaxMembersPerPool::get(); + + if membership.is_compounding + && avail_in_currency > 0 + && can_stake_to_pool + && wont_overflow_maximum_amount + && wont_overflow_maximum_members + { + // At this point this should never fail except in case of arithmetic errors which is ok + Self::do_stake(fusion_address, AVAIL_POOL_ID, avail_in_currency, true)?; + } + + Self::deposit_event(Event::RewardClaimed { + fusion_address, + pool_id, + era, + reward: total_user_rewards, + }); + + Ok(()) + })?; + + Ok(()) + } + + /// Unbonds a specified amount of currency from a pool for a given Fusion address. + /// If `other` is true, the unbonding is performed on behalf of another user. + pub fn do_unbond( + fusion_address: FusionAddress, + pool_id: PoolId, + unbond_amount: Option, + other: bool, + ) -> DispatchResult { + // Retrieve the user's membership in the pool + let mut membership = + Memberships::::get(fusion_address, pool_id).ok_or(Error::::MembershipNotFound)?; + + // Ensure the user has active points to unbond + ensure!( + membership.active_points > 0, + Error::::NoActivePointsToUnbond + ); + + // Fetch pool and currency details + let mut pool = Pools::::get(pool_id).ok_or(Error::::PoolNotFound)?; + let mut currency = + Currencies::::get(pool.currency_id).ok_or(Error::::CurrencyNotFound)?; + + // Allow permissionless only if pool is destroying + ensure!( + !other || pool.state == FusionPoolState::Destroying, + Error::::PoolIsNotDestroying + ); + + // Convert points to currency to determine how much to unbond + let currency_value = pool.points_to_currency(membership.active_points, Some(¤cy))?; + + let unbond_amount = unbond_amount.unwrap_or(currency_value); + + ensure!(unbond_amount > 0, Error::::InvalidAmount); + + // Ensure user has enough points to unbond the requested amount + let requested_points = pool.currency_to_points(unbond_amount, Some(¤cy))?; + ensure!( + membership.active_points >= requested_points, + Error::::InvalidUnbondAmount + ); + + let is_full_unbond = requested_points == membership.active_points; + + let new_balance = currency_value.saturating_sub(unbond_amount); + + // Ensure it's full unbond or valid partial unbond + ensure!( + is_full_unbond || new_balance >= currency.min_amount, + Error::::AmountWillGoBelowMinimum + ); + + // Get current era + let current_era = T::StakingFusionDataProvider::active_era(); + + // Add the unbonding chunk to the related storage + let mut era_pool_unbonding_chunk = UnbondingChunks::::get(pool_id, current_era); + let existing_index = era_pool_unbonding_chunk + .iter() + .position(|(addr, _)| *addr == fusion_address); + if let Some(index) = existing_index { + era_pool_unbonding_chunk[index].1 = era_pool_unbonding_chunk[index] + .1 + .saturating_add(unbond_amount); + } else { + era_pool_unbonding_chunk + .try_push((fusion_address, unbond_amount)) + .map_err(|_| Error::::PoolMemberLimitReached)?; + + // If the unbonding chunk is new, we add its info in the membership + membership + .unbonding_eras + .try_push(current_era) + .map_err(|_| Error::::MaxUnbondingChunksExceeded)?; + } + UnbondingChunks::::insert(pool_id, current_era, era_pool_unbonding_chunk); + + // Update membership points + membership.active_points = membership.active_points.saturating_sub(requested_points); + + // If it is a full unbond, we set compounding to false as user probably want to leave the pool and he'll receive some rewards after + if is_full_unbond { + membership.is_compounding = false; + } + + // Update the pool's member points + if let Some(member_index) = pool + .members + .iter() + .position(|(address, _)| *address == fusion_address) + { + // Subtract the user's points from the member entry + if let Some((_, member_points)) = pool.members.get_mut(member_index) { + *member_points = membership.active_points; + } + } + + // Check if the user has boost in the pool + if let Some(ref mut boost_data) = pool.boost_data { + if HasBoost::::get(pool_id, fusion_address) { + // We substract the additional points to the elligible points + boost_data.elligible_total_points = boost_data + .elligible_total_points + .saturating_sub(requested_points); + } + } + + // Update pool totals + pool.total_staked_points = pool.total_staked_points.saturating_sub(requested_points); + pool.total_staked_native = pool.total_staked_native.saturating_sub(unbond_amount); + pool.total_unbonding_native = pool.total_unbonding_native.saturating_add(unbond_amount); + + // Update currency totals + currency.total_staked_native = currency.total_staked_native.saturating_sub(unbond_amount); + currency.total_unbonding_native = currency + .total_unbonding_native + .saturating_add(unbond_amount); + + // Update TVL + Self::sub_from_tvl(pool.currency_id, ¤cy, unbond_amount)?; + + // Save the updated state back to storage + Memberships::::insert(fusion_address, pool_id, membership); + Pools::::insert(pool_id, &pool); + Currencies::::insert(pool.currency_id, ¤cy); + + // If the user has unbonded from Avail pool, we need to check if we need to remove him from some boost pools + if pool_id == AVAIL_POOL_ID { + Self::check_boost_allocation_removal(fusion_address, new_balance)?; + } + + // Emit event + Self::deposit_event(Event::CurrencyUnbonded { + fusion_address, + pool_id, + currency_id: pool.currency_id, + unbonded_amount: unbond_amount, + points: requested_points, + era: current_era, + }); + + Ok(()) + } + + /// Withdraws unbonded currency for a given Fusion address after the bonding duration has passed. + /// If `other` is true, the withdrawal is performed on behalf of another user. + pub fn do_withdraw_unbonded_currency( + fusion_address: FusionAddress, + pool_id: PoolId, + other: bool, + ) -> DispatchResult { + // Ensure user is a member of the pool + let mut membership = + Memberships::::get(fusion_address, pool_id).ok_or(Error::::MembershipNotFound)?; + + // Fetch pool and currency data + let mut pool = Pools::::get(pool_id).ok_or(Error::::PoolNotFound)?; + let mut currency = + Currencies::::get(pool.currency_id).ok_or(Error::::CurrencyNotFound)?; + + // Allow permissionless only if pool is destroying + ensure!( + !other || pool.state == FusionPoolState::Destroying, + Error::::PoolIsNotDestroying + ); + + ensure!( + !membership.unbonding_eras.is_empty(), + Error::::NoFundsToWithdraw + ); + + // Get active era + let active_era = T::StakingFusionDataProvider::active_era(); + + // Check if there are any unbonded chunks that are now withdrawable + let mut total_withdrawable: FusionCurrencyBalance = 0; + let mut remaining_unbonding_eras = BoundedVec::default(); + + for era in membership.unbonding_eras.iter() { + if era + T::BondingDuration::get() <= active_era { + // This chunk is now withdrawable + let mut pool_era_unbonding_chunks = UnbondingChunks::::get(pool_id, era); + let maybe_unbonding_chunk_index = pool_era_unbonding_chunks + .iter() + .position(|(addr, _)| *addr == fusion_address); + + if let Some(unbonding_chunk_index) = maybe_unbonding_chunk_index { + let unbonding_chunk = pool_era_unbonding_chunks.remove(unbonding_chunk_index); + total_withdrawable = total_withdrawable.saturating_add(unbonding_chunk.1); + + if !pool_era_unbonding_chunks.is_empty() { + UnbondingChunks::::insert(pool_id, era, pool_era_unbonding_chunks); + } else { + UnbondingChunks::::remove(pool_id, era); + } + } else { + Self::deposit_event(Event::ErrorDataEvent { + detail: format!("An unbonding chunk was not found for user: {fusion_address:?}, era: {era:?} and pool id {pool_id:?}. Storage was cleaned but it should get fixed") + }); + } + } else { + // Keep this chunk as it's not withdrawable yet + remaining_unbonding_eras + .try_push(*era) + .map_err(|_| Error::::MaxUnbondingChunksExceeded)?; + } + } + + // Ensure there is something to withdraw + ensure!(total_withdrawable > 0, Error::::NoFundsToWithdraw); + + // Update the user's membership by removing processed unbonding chunks + membership.unbonding_eras = remaining_unbonding_eras; + + // Update pool and currency data + pool.total_unbonding_native = pool + .total_unbonding_native + .saturating_sub(total_withdrawable); + currency.total_unbonding_native = currency + .total_unbonding_native + .saturating_sub(total_withdrawable); + + // Update the user's currency balance + Self::add_to_currency_balance(fusion_address, pool.currency_id, total_withdrawable, true)?; + + // Check if the user should be removed from the pool membership + if membership.unbonding_eras.is_empty() && membership.active_points == 0 { + // Remove the user from members in pool + pool.members + .retain(|(address, _)| *address != fusion_address); + + // Remove the user's membership from the pool + Memberships::::remove(fusion_address, pool_id); + + // If we remove the membership and the user had boost in pool, we need to clean it + if HasBoost::::get(pool_id, fusion_address) { + HasBoost::::remove(pool_id, fusion_address); + + if let Some(ref mut boost_data) = pool.boost_data { + boost_data + .elligible_members + .retain(|address| *address != fusion_address); + } + } + + // Emit event for removing pool membership + Self::deposit_event(Event::PoolMembershipRemoved { + fusion_address, + pool_id, + }); + } else { + // If there are remaining unbonding chunks or active points, update the membership + Memberships::::insert(fusion_address, pool_id, membership); + } + + Pools::::insert(pool_id, &pool); + Currencies::::insert(pool.currency_id, ¤cy); + + // Emit event for successful withdrawal + Self::deposit_event(Event::CurrencyWithdrawn { + fusion_address, + pool_id, + currency_id: pool.currency_id, + amount: total_withdrawable, + }); + + Ok(()) + } + + /// Withdraws AVAIL currency to the controller account for a given Fusion address. + pub fn do_withdraw_avail_to_controller( + fusion_address: FusionAddress, + amount: FusionCurrencyBalance, + ) -> DispatchResult { + // Ensure amount is valid + ensure!(amount > 0, Error::::InvalidAmount); + + // Get the currency + let currency = + Currencies::::get(AVAIL_CURRENCY_ID).ok_or(Error::::CurrencyNotFound)?; + + let one_avail = 10u128.pow(currency.nb_decimals.into()); + + // Get the controller account + let controller_account = FusionAddressToSubstrateAddress::::get(fusion_address) + .ok_or(Error::::NoControllerAddressForUser)?; + + // Retrieve the user's balance of AVAIL currency + let balance = UserCurrencyBalances::::get(fusion_address, AVAIL_CURRENCY_ID) + .ok_or(Error::::NoCurrencyBalanceForUser)? + .amount; + + // Ensure the balance is greater than 0 + ensure!(balance > 0, Error::::NoFundsToWithdraw); + ensure!( + amount <= balance, + Error::::NotEnoughCurrencyBalanceForUser + ); + if amount < balance { + ensure!( + balance.checked_sub(amount).unwrap_or_default() >= one_avail, + Error::::AmountWillGoBelowMinimum, + ); + } + + // Fusion currency in avail + let amount_avail = currency.currency_to_avail(AVAIL_CURRENCY_ID, amount, None)?; + + T::Currency::transfer( + &Self::avail_account(), + &controller_account, + amount_avail, + ExistenceRequirement::KeepAlive, + )?; + + if amount == balance { + // Remove the user's AVAIL currency balance after minting + UserCurrencyBalances::::remove(fusion_address, AVAIL_CURRENCY_ID); + } else { + let remaining: FusionCurrencyBalance = balance + .checked_sub(amount) + .ok_or(Error::::ArithmeticError)?; + UserCurrencyBalances::::insert( + fusion_address, + AVAIL_CURRENCY_ID, + FusionUserCurrencyBalance { + currency_id: AVAIL_CURRENCY_ID, + fusion_address, + amount: remaining, + }, + ); + } + + // Emit an event indicating successful withdrawal + Self::deposit_event(Event::AvailWithdrawnToController { + fusion_address, + controller: controller_account, + amount: amount_avail, + }); + + Ok(()) + } + + /// Return the pool funds account + pub fn get_pool_funds_account(id: PoolId) -> T::AccountId { + T::PoolAccountProvider::get_pool_funds_account(id) + } + + /// Return the pool claimable account + pub fn get_pool_claimable_account(id: PoolId) -> T::AccountId { + T::PoolAccountProvider::get_pool_claimable_account(id) + } + + /// Checks if the user boost allocation need to be removed + pub fn check_boost_allocation_removal( + fusion_address: FusionAddress, + new_avail_balance: FusionCurrencyBalance, + ) -> DispatchResult { + let mut total_avail_required: FusionCurrencyBalance = 0; + let mut user_pool_ids: Vec<(PoolId, FusionCurrencyBalance)> = Vec::new(); + + for (pool_id, min_avail_to_earn) in PoolsWithBoost::::iter() { + if HasBoost::::get(pool_id, fusion_address) { + user_pool_ids.push((pool_id, min_avail_to_earn)); + total_avail_required = total_avail_required.saturating_add(min_avail_to_earn); + } + } + + if new_avail_balance >= total_avail_required { + return Ok(()); + } + + // If we're here, we need to remove the user boost from some pool + // Sort pools by min_avail_to_earn in descending order + user_pool_ids.sort_by(|a, b| b.1.cmp(&a.1)); + + // Remove pools until the total required Avail is within the new balance + for (pool_id, min_avail_to_earn) in user_pool_ids { + // Remove the user's boost status from the pool + HasBoost::::remove(pool_id, fusion_address); + + Pools::::try_mutate(pool_id, |pool_opt| -> DispatchResult { + let pool = pool_opt.as_mut().ok_or(Error::::PoolNotFound)?; + if let Some(ref mut boost_data) = pool.boost_data { + let membership = Memberships::::get(fusion_address, pool_id) + .ok_or(Error::::MembershipNotFound)?; + boost_data.elligible_total_points = boost_data + .elligible_total_points + .saturating_sub(membership.active_points); + boost_data + .elligible_members + .retain(|address| *address != fusion_address); + } + Ok(()) + })?; + + total_avail_required = total_avail_required.saturating_sub(min_avail_to_earn); + + if new_avail_balance >= total_avail_required { + break; + } + } + + Ok(()) + } + + /// Function to remove all boost for everyone in case the Avail pool is slashed + pub fn shutdown_pools_boost() { + for (pool_id, _) in PoolsWithBoost::::iter() { + let _ = HasBoost::::clear_prefix(pool_id, u32::MAX, None); + let _ = Pools::::try_mutate(pool_id, |pool_opt| -> DispatchResult { + if let Some(pool) = pool_opt.as_mut() { + if let Some(ref mut boost_data) = pool.boost_data { + boost_data.elligible_total_points = 0; + boost_data.elligible_members = BoundedVec::default(); + } + }; + Ok(()) + }); + } + } + + /// Helper to compute the rewards for a pool member, return the rewards and the user points to avoid iterating to compute boost rewards + pub fn compute_basic_rewards( + fusion_address: FusionAddress, + exposure: &FusionExposure, + era_rewards: &EraReward, + ) -> Result<(BalanceOf, U256), DispatchError> { + // Find the user's points in this era for the pool + let user_points = exposure + .user_points + .iter() + .find(|(user, _)| *user == fusion_address) + .map(|(_, points)| points) + .ok_or(Error::::UserNotFoundInExposure)?; + + // Calculate the rewards + let user_points = Self::u256(*user_points); + let total_points = Self::u256(exposure.total_points); + let rewards_u128: u128 = era_rewards + .rewards + .try_into() + .map_err(|_| Error::::ArithmeticError)?; + let rewards = Self::u256(rewards_u128); + + let user_reward = rewards + .saturating_mul(user_points) + .checked_div(total_points) + .ok_or(Error::::ArithmeticError)?; + let user_reward_balance = Self::balance(user_reward); + + Ok((user_reward_balance, user_points)) + } + + /// Helper to compute the boost reward for a pool member + pub fn compute_boost_rewards( + fusion_address: FusionAddress, + exposure: &FusionExposure, + era_rewards: &EraReward, + user_points: U256, + ) -> Result, DispatchError> { + // Calculate the boost rewards + let mut user_boost_rewards_balance = BalanceOf::::zero(); + if exposure.boost_members.contains(&fusion_address) { + let total_boost_points = Self::u256(exposure.boost_total_points); + + let boost_rewards_u128: u128 = era_rewards + .additional_rewards + .try_into() + .map_err(|_| Error::::ArithmeticError)?; + let boost_rewards = Self::u256(boost_rewards_u128); + + let user_boost_reward = boost_rewards + .saturating_mul(user_points) + .checked_div(total_boost_points) + .ok_or(Error::::ArithmeticError)?; + + user_boost_rewards_balance = Self::balance(user_boost_reward); + } + Ok(user_boost_rewards_balance) + } + + pub fn do_set_pool_boost_allocations( + fusion_address: FusionAddress, + pool_ids: BoundedVec>, + is_root: bool, + ) -> DispatchResult { + // Get user's current boost allocations to check for permission + let user_memberships: Vec = + Memberships::::iter_key_prefix(fusion_address).collect(); + let mut current_boost_pools: Vec = Vec::new(); + for pool_id in user_memberships.iter() { + if HasBoost::::get(*pool_id, fusion_address) { + current_boost_pools.push(*pool_id); + } + } + + // This extrinsic can be called by root only if the user has no current boost allocation + ensure!( + current_boost_pools.is_empty() || !is_root, + Error::::NotAuthorized + ); + + // Get user's AVAIL balance in pool 0 + let avail_pool_id = AVAIL_POOL_ID; + let avail_membership = Memberships::::get(fusion_address, avail_pool_id) + .ok_or(Error::::NoAvailMembership)?; + let avail_currency = + Currencies::::get(AVAIL_CURRENCY_ID).ok_or(Error::::CurrencyNotFound)?; + let avail_pool = Pools::::get(avail_pool_id).ok_or(Error::::PoolNotFound)?; + let user_avail_balance = + avail_pool.points_to_currency(avail_membership.active_points, Some(&avail_currency))?; + + // Calculate total minimum AVAIL required + let mut total_min_avail_required: FusionCurrencyBalance = 0; + for pool_id in pool_ids.iter() { + let min_avail_to_earn = + PoolsWithBoost::::get(*pool_id).ok_or(Error::::PoolHasNoBoost)?; + total_min_avail_required = total_min_avail_required.saturating_add(min_avail_to_earn); + } + + // Ensure user has enough AVAIL + ensure!( + user_avail_balance >= total_min_avail_required, + Error::::NotEnoughAvailForBoost + ); + + // Create sets for efficient comparison + let selected_pools: BTreeSet = pool_ids.iter().cloned().collect(); + let current_boost_pools_set: BTreeSet = + current_boost_pools.iter().cloned().collect(); + + // Pools to remove boost from: in current but not in selected + let pools_to_remove: Vec = current_boost_pools_set + .difference(&selected_pools) + .cloned() + .collect(); + + // Pools to add boost to: in selected but not in current + let pools_to_add: Vec = selected_pools + .difference(¤t_boost_pools_set) + .cloned() + .collect(); + + // Remove user from boost in pools_to_remove + for pool_id in pools_to_remove.iter() { + // Remove HasBoost entry + HasBoost::::remove(*pool_id, fusion_address); + + // Update pool's boost_data + Pools::::try_mutate(*pool_id, |maybe_pool| -> DispatchResult { + let pool = maybe_pool.as_mut().ok_or(Error::::PoolNotFound)?; + if let Some(ref mut boost_data) = pool.boost_data { + // Get the user's active points in the pool + let membership = Memberships::::get(fusion_address, *pool_id) + .ok_or(Error::::MembershipNotFound)?; + boost_data.elligible_total_points = boost_data + .elligible_total_points + .saturating_sub(membership.active_points); + boost_data + .elligible_members + .retain(|addr| *addr != fusion_address); + } + Ok(()) + })?; + } + + // Add user to boost in pools_to_add + for pool_id in pools_to_add.iter() { + // Insert HasBoost entry + HasBoost::::insert(*pool_id, fusion_address, true); + + // Update pool's boost data + Pools::::try_mutate(*pool_id, |maybe_pool| -> DispatchResult { + let pool = maybe_pool.as_mut().ok_or(Error::::PoolNotFound)?; + if let Some(ref mut boost_data) = pool.boost_data { + // Get the user's active points in the pool + let membership = Memberships::::get(fusion_address, *pool_id) + .ok_or(Error::::MembershipNotFound)?; + boost_data.elligible_total_points = boost_data + .elligible_total_points + .saturating_add(membership.active_points); + boost_data + .elligible_members + .try_push(fusion_address) + .map_err(|_| Error::::PoolMemberLimitReached)?; + } else { + // Pool does not have boost data + return Err(Error::::PoolHasNoBoost.into()); + } + Ok(()) + })?; + } + + // Emit event indicating the optimization result + Self::deposit_event(Event::::UserBoostAllocationsOptimized { + fusion_address, + pools_added: pools_to_add, + pools_removed: pools_to_remove, + }); + + Ok(()) + } + + fn log_if_error( + result: Result<(), DispatchError>, + function_name: &str, + era: EraIndex, + ) -> Result<(), DispatchError> { + if let Err(ref err) = result { + Self::deposit_event(Event::ErrorDataEvent { + detail: format!("Error in {:?} for era {:?}: {:?}", function_name, era, err), + }); + } + result + } + + fn ensure_account_has_ed(account: &T::AccountId) { + let free_balance = T::Currency::free_balance(account); + let ed = T::Currency::minimum_balance(); + if free_balance < ed { + let to_deposit = ed.saturating_sub(free_balance); + let _ = T::Currency::deposit_creating(account, to_deposit); + } + } +} + +impl FusionExt, PoolId> for Pallet { + fn set_fusion_exposures() { + let era = T::StakingFusionDataProvider::active_era(); + let planned_era = era.saturating_add(1); + let mut at_least_one = false; + // Iterate over all pools + for (pool_id, pool) in Pools::::iter() { + // Check if the pool is open, has members, and has targets + if pool.is_active() + && !pool.members.is_empty() + && !pool.targets.is_empty() + && pool.total_staked_points > 0 + { + // Get currency + let Some(currency) = Currencies::::get(pool.currency_id) else { + Self::deposit_event(Event::ErrorDataEvent { + detail: format!("Error while setting exposure for planned_era {:?} and pool {:?} - Could not get related currency.", planned_era, pool_id) + }); + continue; + }; + + // Get total amount in avail + let total_avail_result = pool.points_to_avail( + pool.total_staked_points, + pool.currency_id, + Some(¤cy), + Some(era), + ); + + let Ok(total_avail) = total_avail_result else { + Self::deposit_event(Event::ErrorDataEvent { + detail: format!("Error while setting exposure for planned_era {:?} and pool {:?} - Could not compute avail amount from pool points. - Details: {:?}", planned_era, pool_id, total_avail_result) + }); + continue; + }; + + // Set boost data in the exposure + let (boost_value, boost_total_points, boost_total_avail, boost_members) = + pool.boost_data.as_ref().map_or( + ( + Perbill::zero(), + Points::default(), + BalanceOf::::default(), + BoundedVec::default(), + ), + |data| { + let boost_points = data.elligible_total_points; + let boost_avail = pool + .points_to_avail( + boost_points, + pool.currency_id, + Some(¤cy), + Some(era), + ) + .unwrap_or(BalanceOf::::default()); + ( + data.additional_apy, + boost_points, + boost_avail, + data.elligible_members.clone(), + ) + }, + ); + + // We set the exposure for era + 1 + // The data must be available for the snapshot and next elections + let fusion_exposure = FusionExposure:: { + era: planned_era, + total_avail, + total_points: pool.total_staked_points, + user_points: pool.members.clone(), + targets: pool.targets.clone(), + apy: pool.apy, + native_exposure_data: None, + boost_members, + boost_total_points, + boost_total_avail, + boost_additional_apy: boost_value, + }; + Exposures::::insert(planned_era, pool_id, fusion_exposure); + at_least_one = true; + } + } + if at_least_one { + Self::deposit_event(Event::::ExposuresSet { era: planned_era }); + } + } + + fn handle_end_era(era: EraIndex, era_duration: u64) { + Self::compute_era_rewards(era, era_duration, None); + + let _ = Self::log_if_error(Self::setup_currency_rates(era), "setup_currency_rates", era); + let _ = Self::log_if_error( + Self::clean_history_depth_storages(era), + "clean_history_depth_storages", + era, + ); + } + + fn get_fusion_voters() -> Vec<(T::AccountId, u64, Vec)> { + // We take the planned era here + let era = T::StakingFusionDataProvider::active_era().saturating_add(1); + let mut fusion_voters: Vec<(T::AccountId, u64, Vec)> = Vec::new(); + + let total_issuance = T::Currency::total_issuance(); + + for (pool_id, exposure) in Exposures::::iter_prefix(era) { + if exposure.targets.is_empty() || exposure.total_avail.is_zero() { + continue; + } + let account = Self::get_pool_funds_account(pool_id); + let targets = exposure.targets; + let stake = exposure.total_avail; + let fusion_pool_weight = T::CurrencyToVote::to_vote(stake, total_issuance); + fusion_voters.push((account, fusion_pool_weight, targets.to_vec())); + } + fusion_voters + } + + fn get_active_pool_count() -> usize { + let era = T::StakingFusionDataProvider::active_era().saturating_add(1); + Exposures::::iter_prefix(era).count() + } + + fn get_pool_id_from_funds_account(account: &T::AccountId) -> Option { + PoolsAccountToId::::get(account) + } + + fn update_pool_exposure( + maybe_pool_account: &T::AccountId, + validator: &T::AccountId, + value: BalanceOf, + era: EraIndex, + ) { + let Some(pool_id) = Self::get_pool_id_from_funds_account(maybe_pool_account) else { + return; + }; + + let _ = Exposures::::try_mutate(era, pool_id, |maybe_exposure| -> DispatchResult { + // Ensure rewards are available for the given era and pool + let Some(ref mut exposure) = maybe_exposure else { + return Ok(()); + }; + + let mut native_exposure_data = + exposure.native_exposure_data.clone().unwrap_or_default(); + + if native_exposure_data + .try_push((validator.clone(), value)) + .is_err() + { + Self::deposit_event(Event::ErrorDataEvent { + detail: format!("Could not update fusion exposure for pool {:?} - native_exposure_data limit reached", pool_id) + }); + }; + + let _ = PoolsBackingValidator::::try_mutate( + era, + validator, + |pool_ids| -> DispatchResult { + if pool_ids.try_push(pool_id).is_err() { + Self::deposit_event(Event::ErrorDataEvent { + detail: format!("Could not set fusion pools from validator for pool {pool_id:?} and validator {validator:?} and era {era:?}"), + }); + } + Ok(()) + }, + ); + + exposure.native_exposure_data = Some(native_exposure_data); + + Ok(()) + }); + } + + fn add_fusion_slash( + era: EraIndex, + validator: &T::AccountId, + nominators: &Vec<(T::AccountId, BalanceOf)>, + ) -> Weight { + let mut consummed_weight = Weight::from_parts(0, 0); + + let pool_ids = PoolsBackingValidator::::get(era, validator); + + consummed_weight = consummed_weight.saturating_add(T::DbWeight::get().reads(1)); + + if pool_ids.is_empty() { + return consummed_weight; + } + + let mut pool_funds_accounts: BTreeMap = pool_ids + .iter() + .map(|id| (Self::get_pool_funds_account(*id), *id)) + .collect(); + + let filtered_nominators: Vec<(PoolId, BalanceOf)> = nominators + .iter() + .filter_map(|(nominator_account, balance)| { + pool_funds_accounts + .remove(nominator_account) + .map(|pool_id| (pool_id, *balance)) + }) + .collect(); + + for (pool_id, slashed_amount) in filtered_nominators.iter() { + let result = Pools::::try_mutate(pool_id, |maybe_pool| -> DispatchResult { + let pool = maybe_pool.as_mut().ok_or(Error::::PoolNotFound)?; + consummed_weight = consummed_weight.saturating_add(T::DbWeight::get().reads(1)); + + let exposure = + Exposures::::get(era, pool_id).ok_or(Error::::ExposureNotFound)?; + consummed_weight = consummed_weight.saturating_add(T::DbWeight::get().reads(1)); + + ensure!( + pool.state != FusionPoolState::Destroying, + Error::::PoolIsDestroying + ); + + let exposure_total_avail = exposure.total_avail; + let slash_total_avail = slashed_amount.min(&exposure_total_avail); + let slash_ratio = Perbill::from_rational(*slash_total_avail, exposure_total_avail); + + let new_pending_slash = FusionPendingSlash { + slash_era: era, + slash_ratio, + validator: validator.clone(), + }; + + pool.pending_slashes + .try_push(new_pending_slash) + .map_err(|_| Error::::PendingSlashLimitReached)?; + + HasPendingSlash::::mutate( + era, + (validator, pool.funds_account.clone()), + |count| *count = count.saturating_add(1), + ); + consummed_weight = consummed_weight.saturating_add(T::DbWeight::get().reads(1)); + consummed_weight = consummed_weight.saturating_add(T::DbWeight::get().writes(2)); + + Self::deposit_event(Event::::FusionSlashReported { + pool_id: *pool_id, + slash_era: era, + slash_ratio, + validator: validator.clone(), + }); + + Ok(()) + }); + + if let Err(e) = result { + Self::deposit_event(Event::ErrorDataEvent { + detail: format!("An error occured while trying to add a slash for pool {pool_id:?}, era {era:?} and validator {validator:?} - Error detail: {e:?}"), + }); + } + } + + consummed_weight + } + + fn cancel_fusion_slash(era: EraIndex, slash_indices: Vec) { + // Get the unapplied slashes for the era where the slash should get applied + let native_unapplied_slashes = T::StakingFusionDataProvider::unapplied_slashes(era); + + // Converts the era to the slash era + let era = era + .saturating_sub(T::SlashDeferDuration::get()) + .saturating_sub(1); + + let mut slashes_to_cancel: BTreeMap> = BTreeMap::new(); + let mut slashes_to_cancel_pools: BTreeMap> = BTreeMap::new(); + let mut validators: Vec = Vec::new(); + let mut pool_ids: Vec = Vec::new(); + + for slash_index in slash_indices { + // Get the native unapplied slash + let unapplied_slash = &native_unapplied_slashes[slash_index as usize]; + + // Check if a pool is concerned + let concerned_pool_ids = + PoolsBackingValidator::::get(era, &unapplied_slash.validator); + if concerned_pool_ids.len() == 0 { + continue; + } + + validators.push(unapplied_slash.validator.clone()); + + // We need to handle the case where the validator has multiple slash for the same era (it can happen) + // It means, we need to know which occurence for this validator we need to cancel (if we're cancelling the first, the second, the third, ...) + let mut slash_index_for_this_validator = 0; + for (i, slash) in native_unapplied_slashes.iter().enumerate() { + if slash.validator == unapplied_slash.validator { + if i == slash_index as usize { + break; + } + slash_index_for_this_validator += 1; + } + } + + for pool_id in concerned_pool_ids { + let Some(pool) = Pools::::get(pool_id) else { + Self::deposit_event(Event::ErrorDataEvent { + detail: format!("Pool not found while trying to remove a slash for pool {pool_id:?}, era {era:?}, Slash won't get applied and it will be cleaned after few eras"), + }); + return; + }; + + // Now the pool can be slashed for different validators multiple times for each one of them + // So we need to find the correct occurence using the slash_index_for_this_validator computed just before + let mut occurrence_count = 0; + let mut pool_slash_to_remove_index = None; + for (i, slash) in pool.pending_slashes.iter().enumerate() { + if slash.validator == unapplied_slash.validator { + if occurrence_count == slash_index_for_this_validator { + pool_slash_to_remove_index = Some(i); + break; + } + occurrence_count += 1; + } + } + + let Some(pool_slash_to_remove_index) = pool_slash_to_remove_index else { + Self::deposit_event(Event::ErrorDataEvent { + detail: format!("Slash index not found while trying to remove a slash for pool {pool_id:?}, era {era:?}, Slash won't get applied and it will be cleaned after few eras"), + }); + return; + }; + + slashes_to_cancel + .entry(pool_id) + .or_default() + .push(pool_slash_to_remove_index); + slashes_to_cancel_pools.entry(pool_id).or_insert(pool); + } + } + + for (pool_id, indices_to_remove) in &slashes_to_cancel { + if let Some(pool) = slashes_to_cancel_pools.get_mut(pool_id) { + let mut index = 0; + pool.pending_slashes.retain(|pending_slash| { + if !indices_to_remove.contains(&index) { + index += 1; + true + } else { + HasPendingSlash::::mutate( + era, + (pending_slash.validator.clone(), pool.funds_account.clone()), + |count| { + *count = count.saturating_sub(1); + if *count == 0 { + HasPendingSlash::::remove( + era, + ( + pending_slash.validator.clone(), + pool.funds_account.clone(), + ), + ); + } + }, + ); + index += 1; + false + } + }); + Pools::::insert(pool_id, pool); + pool_ids.push(*pool_id); + } + } + + if !validators.is_empty() { + Self::deposit_event(Event::::FusionSlashCancelled { + pool_ids, + slash_era: era, + validators, + }); + } + } + + fn apply_fusion_slash( + slash_era: EraIndex, + validator: &T::AccountId, + funds_account: &T::AccountId, + ) -> bool { + let slash_era = if T::SlashDeferDuration::get() == 0 { + slash_era + } else { + slash_era.saturating_sub(1) // If we have a defer duration, the slash_era parameter is one era later in the staking pallet + }; + + let Some(pool_id) = Self::get_pool_id_from_funds_account(funds_account) else { + return false; + }; + + if HasPendingSlash::::get(slash_era, (validator, funds_account)) == 0 { + Self::deposit_event(Event::ErrorDataEvent { + detail: format!("Pool {pool_id:?} should have been slashed at era {slash_era:?} for validator {validator:?} but the pending slash was not found in the storage."), + }); + return true; + } + + let result = Pools::::try_mutate(pool_id, |maybe_pool| -> DispatchResult { + let pool = maybe_pool.as_mut().ok_or(Error::::PoolNotFound)?; + + let mut currency = + Currencies::::get(pool.currency_id).ok_or(Error::::CurrencyNotFound)?; + + let maybe_removed_slash = pool + .pending_slashes + .iter() + .position(|slash| slash.slash_era == slash_era && slash.validator == *validator) + .map(|index| pool.pending_slashes.remove(index)); + + if let Some(removed_slash) = maybe_removed_slash { + let mut total_slashed: FusionCurrencyBalance = 0; + let slash_ratio = removed_slash.slash_ratio; + + // Slash the pool + let slashed_amount_from_pool = slash_ratio * pool.total_staked_native; + pool.total_staked_native = pool + .total_staked_native + .saturating_sub(slashed_amount_from_pool); + currency.total_staked_native = currency + .total_staked_native + .saturating_sub(slashed_amount_from_pool); + + total_slashed = total_slashed.saturating_add(slashed_amount_from_pool); + + // Slash the slashable unbonding chunks of the pool + let mut slashed_amount_from_chunks: FusionCurrencyBalance = 0; + + // Iterate over all unbonding chunks for the specified pool + for (unbond_era, chunks) in UnbondingChunks::::iter_prefix(pool_id) { + let mut updated_chunks = BoundedVec::default(); + if unbond_era >= slash_era { + // Iterate over the chunks in the BoundedVec + for (fusion_address, balance) in chunks { + // Calculate the slashed amount for this chunk + let slashed_amount = slash_ratio * balance; + + // Add to the slashed_amount_from_chunks + slashed_amount_from_chunks = + slashed_amount_from_chunks.saturating_add(slashed_amount); + + // Update the remaining balance in the bounded vec + let new_balance = balance.saturating_sub(slashed_amount); + if new_balance > FusionCurrencyBalance::zero() { + updated_chunks + .try_push((fusion_address, new_balance)) + .map_err(|_| Error::::PoolMemberLimitReached)?; + } + } + + if !updated_chunks.is_empty() { + UnbondingChunks::::insert(pool_id, unbond_era, updated_chunks); + } else { + UnbondingChunks::::remove(pool_id, unbond_era); + } + } + } + + total_slashed = total_slashed.saturating_add(slashed_amount_from_chunks); + + pool.total_unbonding_native = pool + .total_unbonding_native + .saturating_sub(slashed_amount_from_chunks); + currency.total_unbonding_native = currency + .total_unbonding_native + .saturating_sub(slashed_amount_from_chunks); + + pool.total_slashed_native = pool.total_slashed_native.saturating_add(total_slashed); + currency.total_slashed_native = + currency.total_slashed_native.saturating_add(total_slashed); + + // Update TVL + // slashed_amount_from_chunks was already deduced from tvl when unbonded + Self::sub_from_tvl(pool.currency_id, ¤cy, slashed_amount_from_pool)?; + + if let Some(slash_destination) = SlashDestination::::get() { + Self::add_to_currency_balance( + slash_destination, + pool.currency_id, + total_slashed, + true, + )?; + } else { + Self::deposit_event(Event::ErrorDataEvent { + detail: format!("No slash destination provided, funds are burned on Avail side. Currency Id: {:?} - Amount: {:?}.", pool.currency_id, total_slashed), + }); + } + + Currencies::::insert(pool.currency_id, currency); + HasPendingSlash::::mutate( + slash_era, + (removed_slash.validator.clone(), funds_account), + |count| { + *count = count.saturating_sub(1); + if *count == 0 { + HasPendingSlash::::remove( + slash_era, + (removed_slash.validator, funds_account), + ); + } + }, + ); + + // If the avail pool is slashed, we remove all boosts cause we cannot compute the correct values anymore + // We can call the permissionless extrinsic to re-optimize the pools boost allocations + if pool_id == AVAIL_POOL_ID { + Self::shutdown_pools_boost(); + } + + Self::deposit_event(Event::::FusionPoolSlashed { + currency_id: pool.currency_id, + pool_id, + slash_era, + amount: total_slashed, + }); + + Ok(()) + } else { + Err(Error::::SlashNotFound.into()) + } + }); + + if let Err(e) = result { + Self::deposit_event(Event::ErrorDataEvent { + detail: format!("An error occured while trying to apply a slash for pool {pool_id:?}, era {slash_era:?}, Slash won't get applied and it will be cleaned after few eras - Error detail: {e:?}"), + }); + } + + true + } +} diff --git a/pallets/fusion/src/mock.rs b/pallets/fusion/src/mock.rs new file mode 100644 index 000000000..3c6424129 --- /dev/null +++ b/pallets/fusion/src/mock.rs @@ -0,0 +1,542 @@ +use crate::{ + self as pallet_fusion, + types::{FusionAddress, PoolId}, + PoolAccountProvider, +}; +use avail_core::currency::AVAIL; +use frame_election_provider_support::{ + bounds::{ElectionBounds, ElectionBoundsBuilder}, + onchain, SequentialPhragmen, +}; +use frame_support::{ + assert_ok, derive_impl, parameter_types, + traits::{FindAuthor, OnFinalize, OnInitialize, OneSessionHandler}, + PalletId, +}; +use frame_system::{EnsureRoot, RawOrigin}; +use pallet_staking::{ErasRewardPoints, ExposureOf, StashOf, UnappliedSlash}; +use sp_core::{ConstU32, ConstU64, H160}; +use sp_runtime::{curve::PiecewiseLinear, testing::UintAuthorityId, BuildStorage, Perbill}; +use sp_staking::{ + offence::{DisableStrategy, OffenceDetails, OnOffenceHandler}, + EraIndex, Exposure, SessionIndex, StakerStatus, +}; + +type Extrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockDaBlock; +type Balance = u128; +type AccountId = u64; + +pub const INIT_TIMESTAMP: u64 = 30_000; +pub const BLOCK_TIME: u64 = 20_000; + +// Accounts used in tests +pub const ALICE: u64 = 1; +pub const POOL_NOMINATOR_ROLE_ACCOUNT: u64 = 10; +pub const VALIDATOR_1: u64 = 100; +pub const VALIDATOR_2: u64 = 200; +pub const VALIDATOR_3: u64 = 300; +pub const NOMINATOR_1: u64 = 400; +pub const NOMINATOR_2: u64 = 500; +pub const NOMINATOR_3: u64 = 600; +pub const REWARD_CLAIMER: u64 = 700; +pub const RANDOM_POT: u64 = 800; +pub const FUSION_STAKER: u64 = 900; +pub const SLASH_DESTINATION: u64 = 1000; + +// IDs and data used in tests +pub const INVALID_ID: u32 = 9999; +pub const BTC_CURRENCY_ID: u32 = 1; +pub const BTC_POOL_ID: u32 = 1; +pub const BTC_DECIMAL: u8 = 8; + +frame_support::construct_runtime!( + pub struct Test { + System: frame_system, + Authorship: pallet_authorship, + Timestamp: pallet_timestamp, + Balances: pallet_balances, + Staking: pallet_staking, + Session: pallet_session, + Historical: pallet_session::historical, + Fusion: pallet_fusion, + } +); + +pub struct DeterministicAuthor; +impl FindAuthor for DeterministicAuthor { + fn find_author<'a, I>(_digests: I) -> Option + where + I: 'a + IntoIterator, + { + let validators = Session::validators(); + if validators.is_empty() { + return None; + } + let current_block = System::block_number(); + let validator_index = (current_block as usize) % validators.len(); + Some(validators[validator_index]) + } +} + +parameter_types! { + pub const BlockHashCount: u32 = 250; + pub static ExistentialDeposit: u128 = 1; + pub static ElectionsBounds: ElectionBounds = ElectionBoundsBuilder::default().build(); +} + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl frame_system::Config for Test { + type AccountData = pallet_balances::AccountData; + type Block = Block; + type BlockHashCount = BlockHashCount; + type HeaderExtensionBuilder = + frame_system::native::hosted_header_builder::da::HeaderExtensionBuilder; + type OnSetCode = (); + type PalletInfo = PalletInfo; + type Randomness = frame_system::test_utils::TestRandomness; + type Extrinsic = Extrinsic; +} + +impl pallet_authorship::Config for Test { + type FindAuthor = DeterministicAuthor; + type EventHandler = (); +} + +impl pallet_timestamp::Config for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = ConstU64<5>; + type WeightInfo = (); +} + +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +impl pallet_balances::Config for Test { + type AccountStore = System; + type Balance = Balance; + type ExistentialDeposit = ExistentialDeposit; +} + +pub struct OtherSessionHandler; +impl OneSessionHandler for OtherSessionHandler { + type Key = UintAuthorityId; + + fn on_genesis_session<'a, I: 'a>(_: I) + where + I: Iterator, + AccountId: 'a, + { + } + + fn on_new_session<'a, I: 'a>(_: bool, _: I, _: I) + where + I: Iterator, + AccountId: 'a, + { + } + + fn on_disabled(_validator_index: u32) {} +} + +impl sp_runtime::BoundToRuntimeAppPublic for OtherSessionHandler { + type Public = UintAuthorityId; +} +sp_runtime::impl_opaque_keys! { + pub struct SessionKeys { + pub other: OtherSessionHandler, + } +} +impl pallet_session::Config for Test { + type SessionManager = pallet_session::historical::NoteHistoricalRoot; + type Keys = SessionKeys; + type ShouldEndSession = pallet_session::PeriodicSessions; + type SessionHandler = (OtherSessionHandler,); + type RuntimeEvent = RuntimeEvent; + type ValidatorId = AccountId; + type ValidatorIdOf = StashOf; + type NextSessionRotation = pallet_session::PeriodicSessions; + type WeightInfo = (); +} +impl pallet_session::historical::Config for Test { + type FullIdentification = Exposure; + type FullIdentificationOf = ExposureOf; +} + +pallet_staking_reward_curve::build! { + const I_NPOS: sp_runtime::curve::PiecewiseLinear<'static> = curve!( + min_inflation: 0_010_000, // minimum_inflation_rate = 1% + max_inflation: 0_050_000, // maximum_inflation_rate = 5% + ideal_stake: 0_500_000, // target_staking_rate = 50% + falloff: 0_050_000, // inflation_decay = 5% + max_piece_count: 40, + test_precision: 0_005_000, + ); +} + +pub struct OnChainSeqPhragmen; +impl onchain::Config for OnChainSeqPhragmen { + type System = Test; + type Solver = SequentialPhragmen; + type DataProvider = Staking; + type WeightInfo = (); + type MaxWinners = ConstU32<100>; + type Bounds = ElectionsBounds; +} + +parameter_types! { + pub const RewardCurve: &'static PiecewiseLinear<'static> = &I_NPOS; + pub static Period: u32 = 2; // Number of blocks per session + pub static Offset: u32 = 0; // Block where session starts + pub static SessionsPerEra: SessionIndex = 3; + pub static SlashDeferDuration: EraIndex = 6; + pub const BondingDuration: EraIndex = 28; + pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(75); +} + +impl pallet_staking::Config for Test { + type Currency = Balances; + type CurrencyBalance = ::Balance; + type UnixTime = pallet_timestamp::Pallet; + type CurrencyToVote = (); + type RewardRemainder = (); + type RuntimeEvent = RuntimeEvent; + type Slash = (); + type Reward = (); + type SessionsPerEra = SessionsPerEra; + type SlashDeferDuration = SlashDeferDuration; + type AdminOrigin = frame_system::EnsureRoot; + type BondingDuration = BondingDuration; + type SessionInterface = (); + type EraPayout = pallet_staking::ConvertCurve; + type NextNewSession = (); + type MaxExposurePageSize = ConstU32<64>; + type OffendingValidatorsThreshold = OffendingValidatorsThreshold; + type ElectionProvider = onchain::OnChainExecution; + type GenesisElectionProvider = Self::ElectionProvider; + type TargetList = pallet_staking::UseValidatorsMap; + type NominationsQuota = pallet_staking::FixedNominationsQuota<16>; + type MaxUnlockingChunks = ConstU32<32>; + type HistoryDepth = ConstU32<84>; + type MaxControllersInDeprecationBatch = ConstU32<100>; + type VoterList = pallet_staking::UseNominatorsAndValidatorsMap; + type EventListeners = (); + type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; + type WeightInfo = (); + type FusionExt = Fusion; +} + +pub struct MockStakingFusionDataProvider; +impl pallet_fusion::StakingFusionDataProvider for MockStakingFusionDataProvider { + fn active_era() -> EraIndex { + pallet_staking::Pallet::::active_era() + .map(|era_info| era_info.index) + .unwrap_or(0) + } + + fn current_era() -> EraIndex { + pallet_staking::Pallet::::current_era().unwrap_or_default() + } + + fn is_valid_validator(account: &AccountId) -> bool { + pallet_staking::Validators::::contains_key(account) + && !pallet_staking::Validators::::get(account).blocked + } + + fn has_earned_era_points(era: EraIndex, accounts: &[AccountId]) -> bool { + let era_points = pallet_staking::ErasRewardPoints::::get(era).individual; + accounts + .iter() + .any(|account| era_points.contains_key(account)) + } + + fn unapplied_slashes(era: EraIndex) -> Vec> { + pallet_staking::UnappliedSlashes::::get(era) + } + + #[cfg(feature = "runtime-benchmarks")] + fn add_dummy_validator(account: AccountId) { + pallet_session::Validators::::mutate(|validators| { + validators.push(account.clone()); + }); + + let default_prefs = pallet_staking::ValidatorPrefs { + commission: Perbill::from_percent(0), + blocked: false, + }; + pallet_staking::Validators::::insert(account.clone(), default_prefs); + } + #[cfg(feature = "runtime-benchmarks")] + fn add_dummy_era_points(validator: AccountId, era: EraIndex) { + pallet_staking::ErasRewardPoints::::mutate(era, |reward_points| { + let points = reward_points + .individual + .entry(validator.clone()) + .or_insert(0); + *points += 100; + }); + } + #[cfg(feature = "runtime-benchmarks")] + fn set_dummy_active_era(era: EraIndex) { + pallet_staking::ActiveEra::::mutate(|active_era| { + *active_era = Some(pallet_staking::ActiveEraInfo { + index: era, + start: None, + }); + }); + } +} + +pub struct MockPoolAccountProvider; +impl PoolAccountProvider for MockPoolAccountProvider { + fn get_pool_funds_account(id: PoolId) -> AccountId { + format!("99991{id}").parse().unwrap() + } + + fn get_pool_claimable_account(id: PoolId) -> AccountId { + format!("99992{id}").parse().unwrap() + } +} + +parameter_types! { + pub const FusionPalletId: PalletId = PalletId(*b"avl/fusi"); + pub const MaxCurrencyNameLength: u32 = 32; + pub const MaxMembersPerPool: u32 = 10; + pub const MaxTargets: u32 = 16; + pub const MaxUnbonding: u32 = 8; + pub const FusionBondingDuration: EraIndex = 7; + pub const HistoryDepth: u32 = 84; + pub const MaxSlashesPerPool: u32 = 100; + pub const MaxPoolsPerValidator: u32 = 100; +} +impl pallet_fusion::Config for Test { + type Currency = Balances; + type CurrencyToVote = (); + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type ApprovedOrigin = EnsureRoot; + type PalletId = FusionPalletId; + type MaxCurrencyNameLength = MaxCurrencyNameLength; + type MaxMembersPerPool = MaxMembersPerPool; + type MaxTargets = MaxTargets; + type MaxUnbonding = MaxUnbonding; + type MaxPoolsPerValidator = MaxPoolsPerValidator; + type MaxSlashesPerPool = MaxSlashesPerPool; + type BondingDuration = FusionBondingDuration; + type SlashDeferDuration = SlashDeferDuration; + type RewardRemainder = (); + type HistoryDepth = HistoryDepth; + type StakingFusionDataProvider = MockStakingFusionDataProvider; + type PoolAccountProvider = MockPoolAccountProvider; + type WeightInfo = (); +} + +fn init_pallet() { + assert_ok!(Fusion::update_max_tvl( + RawOrigin::Root.into(), + 10_000_000 * AVAIL + )); + let slash_destination = FusionAddress::EvmAddress(H160::repeat_byte(0x09)); + assert_ok!(Fusion::set_slash_destination( + RawOrigin::Root.into(), + Some(slash_destination), + Some(SLASH_DESTINATION) + )); + run_to_era(1); +} + +/// Create new externalities for `Fusion` module tests. +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap(); + + pallet_balances::GenesisConfig:: { + balances: vec![ + (VALIDATOR_1, 10_000 * AVAIL), + (VALIDATOR_2, 10_000 * AVAIL), + (VALIDATOR_3, 10_000 * AVAIL), + (NOMINATOR_1, 10_000 * AVAIL), + (NOMINATOR_2, 10_000 * AVAIL), + (NOMINATOR_3, 10_000 * AVAIL), + (REWARD_CLAIMER, 10_000 * AVAIL), + (RANDOM_POT, 10_000 * AVAIL), + (FUSION_STAKER, 10_000 * AVAIL), + (ALICE, 10_000 * AVAIL), + ], + } + .assimilate_storage(&mut t) + .unwrap(); + + let _ = pallet_staking::GenesisConfig:: { + stakers: vec![ + ( + VALIDATOR_1, + VALIDATOR_1, + 11 * AVAIL, + StakerStatus::Validator, + ), + ( + VALIDATOR_2, + VALIDATOR_2, + 10 * AVAIL, + StakerStatus::Validator, + ), + ( + VALIDATOR_3, + VALIDATOR_3, + 1 * AVAIL, // Not enough to be elected + StakerStatus::Validator, + ), + ( + NOMINATOR_1, + NOMINATOR_1, + 1 * AVAIL, + StakerStatus::Nominator(vec![VALIDATOR_1]), + ), + ], + validator_count: 2, + minimum_validator_count: 1, + slash_reward_fraction: Perbill::from_percent(10), + ..Default::default() + } + .assimilate_storage(&mut t) + .unwrap(); + + let _ = pallet_session::GenesisConfig:: { + keys: vec![ + ( + VALIDATOR_1, + VALIDATOR_1, + SessionKeys { + other: UintAuthorityId::from(VALIDATOR_1), + }, + ), + ( + VALIDATOR_2, + VALIDATOR_2, + SessionKeys { + other: UintAuthorityId::from(VALIDATOR_2), + }, + ), + ( + VALIDATOR_3, + VALIDATOR_3, + SessionKeys { + other: UintAuthorityId::from(VALIDATOR_3), + }, + ), + ], + } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + Staking::on_initialize(1); + Session::on_initialize(1); + Fusion::on_initialize(1); + Timestamp::set_timestamp(INIT_TIMESTAMP); + init_pallet() + }); + + ext +} + +pub fn run_to_block(n: u32) { + let mut current_block = System::block_number(); + while current_block < n { + let author = DeterministicAuthor::find_author(None).expect("A valid author should exist."); + + if let Some(active_era) = Staking::active_era() { + let mut reward_points = Staking::eras_reward_points(active_era.index); + *reward_points.individual.entry(author).or_insert(0) += 1; + reward_points.total += 1; + ErasRewardPoints::::insert(active_era.index, reward_points); + } + + // Make validators claims their payouts if we're are at a new era block + 1 + let era_duration = Offset::get() + (Period::get() * SessionsPerEra::get()); + if current_block % era_duration == 0 { + let era = Staking::active_era().unwrap().index; + if era > 1 { + make_all_reward_payment(era.saturating_sub(1)); + } + } + + Balances::on_finalize(current_block); + Authorship::on_finalize(current_block); + Session::on_finalize(current_block); + Staking::on_finalize(current_block); + System::on_finalize(current_block); + current_block += 1; + System::set_block_number(current_block); + System::on_initialize(current_block); + Timestamp::set_timestamp(current_block as u64 * BLOCK_TIME + INIT_TIMESTAMP); + Staking::on_initialize(current_block); + Session::on_initialize(current_block); + Authorship::on_initialize(current_block); + Balances::on_initialize(current_block); + } +} + +// Run to the start of target_era + 1 block +pub fn run_to_era(target_era: u32) { + let end = Offset::get() + (target_era * Period::get() * SessionsPerEra::get()) + 1; + run_to_block(end); + assert_eq!(Staking::active_era().unwrap().index, target_era); +} + +// Run to the end of target_era (target_era + 1 era - 1 block) +pub fn run_to_end_of_era(target_era: u32) { + let end = Offset::get() + ((target_era + 1) * Period::get() * SessionsPerEra::get()) - 1; + run_to_block(end); + assert_eq!(Staking::active_era().unwrap().index, target_era); +} + +/// Make all validator and nominator request their payment +pub fn make_all_reward_payment(era: EraIndex) { + let validators_with_reward = ErasRewardPoints::::get(era) + .individual + .keys() + .cloned() + .collect::>(); + + for validator in validators_with_reward.iter().filter_map(Staking::bonded) { + assert_ok!(Staking::payout_stakers_by_page( + RuntimeOrigin::signed(REWARD_CLAIMER), + validator, + era, + 0 + )); + } +} + +pub fn on_offence_now( + offenders: &[OffenceDetails< + AccountId, + pallet_session::historical::IdentificationTuple, + >], + slash_fraction: &[Perbill], +) { + let now = Staking::active_era().unwrap().index; + let _ = Staking::on_offence( + offenders, + slash_fraction, + Staking::eras_start_session_index(now).unwrap(), + DisableStrategy::WhenSlashed, + ); +} + +pub fn add_slash(who: &AccountId, slash_fraction: Perbill) { + on_offence_now( + &[OffenceDetails { + offender: ( + *who, + Staking::eras_stakers(Staking::active_era().unwrap().index, who), + ), + reporters: vec![], + }], + &[slash_fraction], + ); +} diff --git a/pallets/fusion/src/tests.rs b/pallets/fusion/src/tests.rs new file mode 100644 index 000000000..ae50ce80d --- /dev/null +++ b/pallets/fusion/src/tests.rs @@ -0,0 +1,5513 @@ +use avail_core::currency::AVAIL; +use frame_support::{assert_noop, assert_ok, error::BadOrigin, BoundedVec}; +use frame_system::RawOrigin; +use sp_core::H160; +use sp_runtime::TokenError; + +use crate::{mock::*, *}; + +fn create_avail_currency() -> (types::FusionCurrency, u128, u128) { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let avail_decimal: u8 = 18; + let avail_max: u128 = 1_000_000 * AVAIL; + let avail_min: u128 = 0; + let avail_conversion_rate = AVAIL; + let avail_name: BoundedVec = b"Avail".to_vec().try_into().unwrap(); + assert_ok!(Fusion::create_currency( + root, + AVAIL_CURRENCY_ID, + avail_name, + avail_decimal, + avail_max, + avail_min, + avail_conversion_rate + )); + + let fusion_currency = Currencies::::get(AVAIL_CURRENCY_ID).unwrap(); + + let currency_rate = CurrencyRates::::get( + MockStakingFusionDataProvider::active_era(), + AVAIL_CURRENCY_ID, + ) + .unwrap(); + let currency_rate_change = CurrencyRateChanges::::get(AVAIL_CURRENCY_ID); + (fusion_currency, currency_rate, currency_rate_change) +} + +fn create_avail_pool() -> types::FusionPool { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let currency_id = AVAIL_CURRENCY_ID; + let apy = Perbill::from_percent(5); + let nominator: Option = Some(POOL_NOMINATOR_ROLE_ACCOUNT); + + assert_ok!(Fusion::create_pool( + root.clone(), + AVAIL_POOL_ID, + currency_id, + apy, + nominator + )); + + let valid_targets: BoundedVec = + vec![VALIDATOR_1, VALIDATOR_2].try_into().unwrap(); + assert_ok!(Fusion::nominate(root.clone(), AVAIL_POOL_ID, valid_targets)); + + assert_ok!(Fusion::fill_pool_account( + RawOrigin::Signed(RANDOM_POT).into(), + AVAIL_POOL_ID, + 1_000 * AVAIL + )); + + assert_ok!(Fusion::set_pool( + root, + AVAIL_POOL_ID, + None, + Some(FusionPoolState::Open), + ConfigOp::Noop, + ConfigOp::Noop, + None + )); + + Pools::::get(AVAIL_POOL_ID).unwrap() +} + +fn create_btc_currency() -> (types::FusionCurrency, u128, u128) { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let btc_decimal: u8 = BTC_DECIMAL; + let btc_max: u128 = 10_000_000_000; // 100 BTC + let btc_min: u128 = 1_000_000; // 0.01 BTC + let btc_conversion_rate = 10 * AVAIL; // 1 BTC = 10 Avail + let btc_name: BoundedVec = b"Bitcoin".to_vec().try_into().unwrap(); + assert_ok!(Fusion::create_currency( + root, + BTC_CURRENCY_ID, + btc_name, + btc_decimal, + btc_max, + btc_min, + btc_conversion_rate + )); + + let fusion_currency = Currencies::::get(BTC_CURRENCY_ID).unwrap(); + + let currency_rate = + CurrencyRates::::get(MockStakingFusionDataProvider::active_era(), BTC_CURRENCY_ID) + .unwrap(); + let currency_rate_change = CurrencyRateChanges::::get(BTC_CURRENCY_ID); + (fusion_currency, currency_rate, currency_rate_change) +} + +fn create_btc_pool() -> types::FusionPool { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let currency_id = BTC_CURRENCY_ID; + let apy = Perbill::from_percent(10); + let nominator: Option = Some(POOL_NOMINATOR_ROLE_ACCOUNT); + + assert_ok!(Fusion::create_pool( + root.clone(), + BTC_POOL_ID, + currency_id, + apy, + nominator + )); + + let valid_targets: BoundedVec = + vec![VALIDATOR_1, VALIDATOR_2].try_into().unwrap(); + assert_ok!(Fusion::nominate(root.clone(), BTC_POOL_ID, valid_targets)); + + assert_ok!(Fusion::fill_pool_account( + RawOrigin::Signed(RANDOM_POT).into(), + BTC_POOL_ID, + 1_000 * AVAIL + )); + + assert_ok!(Fusion::set_pool( + root, + BTC_POOL_ID, + None, + Some(FusionPoolState::Open), + ConfigOp::Noop, + ConfigOp::Noop, + None + )); + + Pools::::get(BTC_POOL_ID).unwrap() +} + +mod create_currency { + use super::*; + + #[test] + fn create_currency() { + new_test_ext().execute_with(|| { + let (currency, currency_rate, _) = create_avail_currency(); + let event = RuntimeEvent::Fusion(Event::CurrencyCreated { + currency_id: AVAIL_CURRENCY_ID, + name: currency.name, + nb_decimals: currency.nb_decimals, + min_amount: currency.min_amount, + max_amount: currency.max_amount, + initial_conversion_rate: currency_rate, + }); + System::assert_last_event(event); + }) + } + + #[test] + fn bad_origin() { + new_test_ext().execute_with(|| { + let non_root_origin: RuntimeOrigin = RawOrigin::Signed(ALICE).into(); + let avail_decimal: u8 = 18; + let avail_max: u128 = 1_000_000 * AVAIL; + let avail_min: u128 = 0; + let avail_conversion_rate: u128 = AVAIL; + let avail_name: BoundedVec = + b"Avail".to_vec().try_into().unwrap(); + + assert_noop!( + Fusion::create_currency( + non_root_origin, + AVAIL_CURRENCY_ID, + avail_name, + avail_decimal, + avail_max, + avail_min, + avail_conversion_rate + ), + BadOrigin + ); + }); + } + + #[test] + fn currency_already_exists() { + new_test_ext().execute_with(|| { + create_avail_currency(); + + let root: RuntimeOrigin = RawOrigin::Root.into(); + let avail_decimal: u8 = 18; + let avail_max: u128 = 1_000_000 * AVAIL; + let avail_min: u128 = 0; + let avail_conversion_rate = AVAIL; + let avail_name: BoundedVec = + b"Avail".to_vec().try_into().unwrap(); + + assert_noop!( + Fusion::create_currency( + root, + AVAIL_CURRENCY_ID, + avail_name, + avail_decimal, + avail_max, + avail_min, + avail_conversion_rate + ), + Error::::CurrencyAlreadyExists + ); + }) + } + + #[test] + fn invalid_name() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let avail_decimal: u8 = 18; + let avail_max: u128 = 1_000_000 * AVAIL; + let avail_min: u128 = 0; + let avail_conversion_rate = AVAIL; + let invalid_name: BoundedVec = + b"".to_vec().try_into().unwrap(); + + assert_noop!( + Fusion::create_currency( + root, + AVAIL_CURRENCY_ID, + invalid_name, + avail_decimal, + avail_max, + avail_min, + avail_conversion_rate + ), + Error::::InvalidName + ); + }); + } + + #[test] + fn invalid_number_of_decimals() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let avail_max: u128 = 1_000_000 * AVAIL; + let avail_min: u128 = 0; + let avail_conversion_rate = AVAIL; + let avail_name: BoundedVec = + b"Avail".to_vec().try_into().unwrap(); + + assert_noop!( + Fusion::create_currency( + root, + AVAIL_CURRENCY_ID, + avail_name, + 0, + avail_max, + avail_min, + avail_conversion_rate + ), + Error::::InvalidNumberOfDecimals + ); + }); + } + + #[test] + fn invalid_max_number() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let avail_decimal: u8 = 18; + let avail_max: u128 = 0; + let avail_min: u128 = 1; + let avail_conversion_rate = AVAIL; + let avail_name: BoundedVec = + b"Avail".to_vec().try_into().unwrap(); + + assert_noop!( + Fusion::create_currency( + root, + AVAIL_CURRENCY_ID, + avail_name, + avail_decimal, + avail_max, + avail_min, + avail_conversion_rate + ), + Error::::InvalidMaxNumber + ); + }); + } + + #[test] + fn invalid_conversion_rate() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let avail_decimal: u8 = 18; + let avail_max: u128 = 1_000_000 * AVAIL; + let avail_min: u128 = 0; + let invalid_conversion_rate: u128 = 0; + let avail_name: BoundedVec = + b"Avail".to_vec().try_into().unwrap(); + + assert_noop!( + Fusion::create_currency( + root, + AVAIL_CURRENCY_ID, + avail_name, + avail_decimal, + avail_max, + avail_min, + invalid_conversion_rate + ), + Error::::InvalidConversionRate + ); + }); + } + + #[test] + fn no_min_amount_for_avail_currency() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let avail_decimal: u8 = 18; + let avail_max: u128 = 1_000_000 * AVAIL; + let avail_min: u128 = 1; + let avail_conversion_rate: u128 = AVAIL; + let avail_name: BoundedVec = + b"Avail".to_vec().try_into().unwrap(); + + assert_noop!( + Fusion::create_currency( + root, + AVAIL_CURRENCY_ID, + avail_name, + avail_decimal, + avail_max, + avail_min, + avail_conversion_rate + ), + Error::::NoMinAmountForAvailCurrency + ); + }); + } + + #[test] + fn entity_zero_does_not_exist() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let avail_decimal: u8 = 18; + let avail_max: u128 = 1_000_000 * AVAIL; + let avail_min: u128 = 0; + let avail_conversion_rate = AVAIL; + let avail_name: BoundedVec = + b"Random".to_vec().try_into().unwrap(); + + assert_noop!( + Fusion::create_currency( + root, + 111, + avail_name, + avail_decimal, + avail_max, + avail_min, + avail_conversion_rate + ), + Error::::EntityZeroDoesNotExist + ); + }); + } +} + +mod set_currency { + use super::*; + + #[test] + fn set_currency() { + new_test_ext().execute_with(|| { + let (mut currency, _, _) = create_avail_currency(); + let root: RuntimeOrigin = RawOrigin::Root.into(); + + let new_name: Option> = + Some(b"NewAvail".to_vec().try_into().unwrap()); + let new_max_amount: Option = Some(2_000_000 * AVAIL); + let new_min_amount: Option = Some(0); + + assert_ok!(Fusion::set_currency( + root, + AVAIL_CURRENCY_ID, + new_name.clone(), + new_max_amount, + new_min_amount + )); + + currency.name = new_name.clone().unwrap(); + currency.max_amount = new_max_amount.unwrap(); + currency.min_amount = new_min_amount.unwrap(); + + let updated_currency = Currencies::::get(AVAIL_CURRENCY_ID).unwrap(); + assert_eq!(updated_currency.name, currency.name); + assert_eq!(updated_currency.max_amount, currency.max_amount); + assert_eq!(updated_currency.min_amount, currency.min_amount); + assert_eq!(updated_currency.is_destroyed, currency.is_destroyed); + + System::assert_last_event(RuntimeEvent::Fusion(Event::CurrencySet { + currency_id: AVAIL_CURRENCY_ID, + name: new_name, + min_amount: new_min_amount, + max_amount: new_max_amount, + })); + }); + } + + #[test] + fn bad_origin() { + new_test_ext().execute_with(|| { + create_avail_currency(); + let non_root_origin: RuntimeOrigin = RawOrigin::Signed(ALICE).into(); + let new_name: Option> = + Some(b"NewAvail".to_vec().try_into().unwrap()); + let new_max_amount: Option = Some(2_000_000 * AVAIL); + let new_min_amount: Option = Some(0); + + assert_noop!( + Fusion::set_currency( + non_root_origin, + AVAIL_CURRENCY_ID, + new_name, + new_max_amount, + new_min_amount + ), + BadOrigin + ); + }); + } + + #[test] + fn currency_not_found() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + + let new_name: Option> = + Some(b"NonExistent".to_vec().try_into().unwrap()); + let new_max_amount: Option = Some(2_000_000 * AVAIL); + let new_min_amount: Option = Some(0); + + assert_noop!( + Fusion::set_currency(root, INVALID_ID, new_name, new_max_amount, new_min_amount), + Error::::CurrencyNotFound + ); + }); + } + + #[test] + fn currency_destroyed() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let (mut currency, _, _) = create_avail_currency(); + currency.is_destroyed = true; + Currencies::::insert(AVAIL_CURRENCY_ID, currency); + + let new_name: Option> = + Some(b"DestroyedAvail".to_vec().try_into().unwrap()); + let new_max_amount: Option = Some(2_000_000 * AVAIL); + let new_min_amount: Option = Some(0); + + assert_noop!( + Fusion::set_currency( + root, + AVAIL_CURRENCY_ID, + new_name, + new_max_amount, + new_min_amount + ), + Error::::CurrencyDestroyed + ); + }); + } + + #[test] + fn invalid_name() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + create_avail_currency(); + + let invalid_name: Option> = + Some(b"".to_vec().try_into().unwrap()); + let new_max_amount: Option = Some(2_000_000 * AVAIL); + let new_min_amount: Option = Some(0); + + assert_noop!( + Fusion::set_currency( + root, + AVAIL_CURRENCY_ID, + invalid_name, + new_max_amount, + new_min_amount + ), + Error::::InvalidName + ); + }); + } + + #[test] + fn invalid_max_number() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + create_avail_currency(); + + let new_name: Option> = + Some(b"Avail".to_vec().try_into().unwrap()); + let invalid_max_amount: Option = Some(0); + let new_min_amount: Option = Some(0); + + assert_noop!( + Fusion::set_currency( + root, + AVAIL_CURRENCY_ID, + new_name, + invalid_max_amount, + new_min_amount + ), + Error::::InvalidMaxNumber + ); + }); + } + + #[test] + fn invalid_max_amount() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let (mut currency, _, _) = create_avail_currency(); + currency.total_staked_native = 1_000_000; + currency.total_unbonding_native = 500_000; + Currencies::::insert(AVAIL_CURRENCY_ID, currency); + + let new_name: Option> = + Some(b"Avail".to_vec().try_into().unwrap()); + let invalid_max_amount: Option = Some(1_000_000); + let new_min_amount: Option = Some(0); + + assert_noop!( + Fusion::set_currency( + root, + AVAIL_CURRENCY_ID, + new_name, + invalid_max_amount, + new_min_amount + ), + Error::::InvalidMaxAmount + ); + }); + } + + #[test] + fn invalid_min_amount() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + create_avail_currency(); + + let new_name: Option> = + Some(b"Avail".to_vec().try_into().unwrap()); + let new_max_amount: Option = Some(2_000_000 * AVAIL); + let invalid_min_amount: Option = Some(3_000_000 * AVAIL); + + assert_noop!( + Fusion::set_currency( + root, + AVAIL_CURRENCY_ID, + new_name, + new_max_amount, + invalid_min_amount + ), + Error::::InvalidMinAmount + ); + }); + } + + #[test] + fn no_min_amount_for_avail_currency() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + create_avail_currency(); + + let new_name: Option> = + Some(b"Avail".to_vec().try_into().unwrap()); + let new_max_amount: Option = Some(2_000_000 * AVAIL); + let invalid_min_amount: Option = Some(1); + + assert_noop!( + Fusion::set_currency( + root, + AVAIL_CURRENCY_ID, + new_name, + new_max_amount, + invalid_min_amount + ), + Error::::NoMinAmountForAvailCurrency + ); + }); + } +} + +mod destroy_currency { + use super::*; + + #[test] + fn destroy_currency() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + create_avail_currency(); + create_btc_currency(); + + assert_ok!(Fusion::destroy_currency(root, BTC_CURRENCY_ID)); + + let currency = Currencies::::get(BTC_CURRENCY_ID).unwrap(); + assert!(currency.is_destroyed); + + System::assert_last_event(RuntimeEvent::Fusion(Event::CurrencyDeleted { + currency_id: BTC_CURRENCY_ID, + })); + }); + } + + #[test] + fn bad_origin() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_btc_currency(); + let non_root_origin: RuntimeOrigin = RawOrigin::Signed(ALICE).into(); + + assert_noop!( + Fusion::destroy_currency(non_root_origin, BTC_CURRENCY_ID), + BadOrigin + ); + }); + } + + #[test] + fn pool_exists_for_currency() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let root: RuntimeOrigin = RawOrigin::Root.into(); + + assert_noop!( + Fusion::destroy_currency(root, BTC_CURRENCY_ID), + Error::::PoolExistsForCurrency + ); + }); + } + + #[test] + fn currency_not_found() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + + assert_noop!( + Fusion::destroy_currency(root, INVALID_ID), + Error::::CurrencyNotFound + ); + }); + } + + #[test] + fn currency_destroyed() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + create_avail_currency(); + let (mut currency, _, _) = create_btc_currency(); + + currency.is_destroyed = true; + Currencies::::insert(BTC_CURRENCY_ID, currency); + + assert_noop!( + Fusion::destroy_currency(root, BTC_CURRENCY_ID), + Error::::CurrencyDestroyed + ); + }); + } + + #[test] + fn cannot_destroy_avail_currency() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_btc_currency(); + let root: RuntimeOrigin = RawOrigin::Root.into(); + + assert_noop!( + Fusion::destroy_currency(root, AVAIL_CURRENCY_ID), + Error::::CannotDestroyAvailCurrency + ); + }); + } +} + +mod set_currency_conversion_rate { + use super::*; + + #[test] + fn set_currency_conversion_rate() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + create_avail_currency(); + + let new_conversion_rate: u128 = 2 * AVAIL; + + assert_ok!(Fusion::set_currency_conversion_rate( + root, + AVAIL_CURRENCY_ID, + new_conversion_rate + )); + + let stored_conversion_rate = CurrencyRateChanges::::get(AVAIL_CURRENCY_ID); + assert_eq!(stored_conversion_rate, new_conversion_rate); + + System::assert_last_event(RuntimeEvent::Fusion(Event::CurrencyConversionRateSet { + currency_id: AVAIL_CURRENCY_ID, + conversion_rate: new_conversion_rate, + })); + }); + } + + #[test] + fn bad_origin() { + new_test_ext().execute_with(|| { + create_avail_currency(); + + let non_root_origin: RuntimeOrigin = RawOrigin::Signed(ALICE).into(); + let new_conversion_rate: u128 = 2 * AVAIL; + + assert_noop!( + Fusion::set_currency_conversion_rate( + non_root_origin, + AVAIL_CURRENCY_ID, + new_conversion_rate + ), + BadOrigin + ); + }); + } + + #[test] + fn invalid_conversion_rate() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + create_avail_currency(); + + let invalid_conversion_rate: u128 = 0; + + assert_noop!( + Fusion::set_currency_conversion_rate( + root, + AVAIL_CURRENCY_ID, + invalid_conversion_rate + ), + Error::::InvalidConversionRate + ); + }); + } + + #[test] + fn currency_not_found() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let new_conversion_rate: u128 = 2 * AVAIL; + + assert_noop!( + Fusion::set_currency_conversion_rate(root, INVALID_ID, new_conversion_rate), + Error::::CurrencyNotFound + ); + }); + } + #[test] + fn currency_destroyed() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let (mut currency, _, _) = create_avail_currency(); + currency.is_destroyed = true; + Currencies::::insert(AVAIL_CURRENCY_ID, currency); + + let new_conversion_rate: u128 = 2 * AVAIL; + + assert_noop!( + Fusion::set_currency_conversion_rate(root, AVAIL_CURRENCY_ID, new_conversion_rate), + Error::::CurrencyDestroyed + ); + }); + } +} + +mod create_pool { + use super::*; + + #[test] + fn create_pool() { + new_test_ext().execute_with(|| { + create_avail_currency(); + let pool = create_avail_pool(); + + assert_eq!(pool.currency_id, AVAIL_CURRENCY_ID); + assert_eq!(pool.apy, Perbill::from_percent(5)); + assert_eq!(pool.nominator, Some(POOL_NOMINATOR_ROLE_ACCOUNT)); + assert_eq!(pool.state, FusionPoolState::Open); + + let pool_id_from_funds_account = PoolsAccountToId::::get(&pool.funds_account); + assert_eq!(pool_id_from_funds_account, Some(AVAIL_POOL_ID)); + + System::assert_has_event(RuntimeEvent::Fusion(Event::PoolCreated { + pool_id: AVAIL_POOL_ID, + currency_id: AVAIL_CURRENCY_ID, + apy: Perbill::from_percent(5), + state: FusionPoolState::Paused, + nominator: Some(POOL_NOMINATOR_ROLE_ACCOUNT), + funds_account: pool.funds_account, + claimable_account: pool.claimable_account, + })); + }); + } + + #[test] + fn bad_origin() { + new_test_ext().execute_with(|| { + create_avail_currency(); + + let non_root_origin: RuntimeOrigin = RawOrigin::Signed(ALICE).into(); + let apy = Perbill::from_percent(5); + let nominator: Option = Some(POOL_NOMINATOR_ROLE_ACCOUNT); + + assert_noop!( + Fusion::create_pool( + non_root_origin, + AVAIL_POOL_ID, + AVAIL_CURRENCY_ID, + apy, + nominator + ), + BadOrigin + ); + }); + } + + #[test] + fn pool_already_exists() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let root: RuntimeOrigin = RawOrigin::Root.into(); + let apy = Perbill::from_percent(5); + let nominator: Option = Some(POOL_NOMINATOR_ROLE_ACCOUNT); + + assert_noop!( + Fusion::create_pool(root, AVAIL_POOL_ID, AVAIL_CURRENCY_ID, apy, nominator), + Error::::PoolAlreadyExists + ); + }); + } + + #[test] + fn invalid_apy() { + new_test_ext().execute_with(|| { + create_avail_currency(); + + let root: RuntimeOrigin = RawOrigin::Root.into(); + let apy = Perbill::zero(); + let nominator: Option = Some(POOL_NOMINATOR_ROLE_ACCOUNT); + + assert_noop!( + Fusion::create_pool(root, AVAIL_POOL_ID, AVAIL_CURRENCY_ID, apy, nominator), + Error::::InvalidAPY + ); + }); + } + + #[test] + fn currency_not_found() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let apy = Perbill::from_percent(5); + let nominator: Option = Some(POOL_NOMINATOR_ROLE_ACCOUNT); + + assert_noop!( + Fusion::create_pool(root, AVAIL_POOL_ID, 9999, apy, nominator), + Error::::CurrencyNotFound + ); + }); + } + + #[test] + fn currency_destroyed() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + let (mut currency, _, _) = create_avail_currency(); + currency.is_destroyed = true; + Currencies::::insert(AVAIL_CURRENCY_ID, currency); + + let apy = Perbill::from_percent(5); + let nominator: Option = Some(POOL_NOMINATOR_ROLE_ACCOUNT); + + assert_noop!( + Fusion::create_pool(root, AVAIL_POOL_ID, AVAIL_CURRENCY_ID, apy, nominator), + Error::::CurrencyDestroyed + ); + }); + } + + #[test] + fn entity_zero_does_not_exist() { + new_test_ext().execute_with(|| { + create_avail_currency(); + + let root: RuntimeOrigin = RawOrigin::Root.into(); + let apy = Perbill::from_percent(5); + let nominator: Option = Some(POOL_NOMINATOR_ROLE_ACCOUNT); + + assert_noop!( + Fusion::create_pool(root, BTC_POOL_ID, AVAIL_CURRENCY_ID, apy, nominator), + Error::::EntityZeroDoesNotExist + ); + }); + } +} + +mod set_pool { + use super::*; + + #[test] + fn set_pool() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let root: RuntimeOrigin = RawOrigin::Root.into(); + let new_apy = Some(Perbill::from_percent(8)); + let new_state = Some(FusionPoolState::Paused); + let new_nominator = ConfigOp::Set(ALICE); + let new_boost_data_option = ConfigOp::Set((Perbill::from_percent(2), 1 * AVAIL)); + + assert_ok!(Fusion::set_pool( + root, + AVAIL_POOL_ID, + new_apy, + new_state, + new_nominator.clone(), + new_boost_data_option.clone(), + None + )); + + let pool = Pools::::get(0).unwrap(); + + assert_eq!(pool.apy, new_apy.unwrap()); + assert_eq!(pool.state, new_state.unwrap()); + assert_eq!(pool.nominator, Some(ALICE)); + let new_boost_data = (Perbill::from_percent(2), 1 * AVAIL); + let pool_boost_data = pool.boost_data.unwrap(); + assert_eq!(new_boost_data.0, pool_boost_data.additional_apy); + assert_eq!(new_boost_data.1, pool_boost_data.min_avail_to_earn); + + System::assert_last_event(RuntimeEvent::Fusion(Event::PoolSet { + pool_id: AVAIL_POOL_ID, + apy: new_apy, + state: new_state, + nominator: new_nominator, + boost_data: new_boost_data_option, + })); + }); + } + + #[test] + fn set_pool_retry_rewards_for_eras() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + let pool = create_btc_pool(); + + // We need to make the reward fail so we can try it again + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + // We set apy as something high + assert_ok!(Fusion::set_pool( + RawOrigin::Root.into(), + BTC_POOL_ID, + Some(Perbill::from_percent(100)), + None, + ConfigOp::Noop, + ConfigOp::Noop, + None + )); + + // At end of era 3, reward for era 3 are going to get generated for fusion, so we go at the beginning of the era to make it fail + run_to_era(3); + + // We now set the pool balance to zero + assert_ok!(Balances::force_set_balance( + RawOrigin::Root.into(), + pool.funds_account, + avail_core::currency::Balance::zero(), + )); + + // Now if we go to era 4, pool should be blocked + run_to_era(4); + + // Check that we have the pool paused + let missed_rewards = 38020000000000; + System::assert_has_event(RuntimeEvent::Fusion(Event::RewardSet { + era: 3, + rewarded_pools: vec![], + total_rewarded: 0, + paused_pools: vec![1], + paused_pools_missed_rewards: vec![missed_rewards], + retry: false, + })); + + // We can now retry what we want + assert_ok!(Balances::force_set_balance( + RawOrigin::Root.into(), + pool.funds_account, + 10_000 * AVAIL, + )); + + // We retry generating reward for this era + let retry_rewards_for_eras: BoundedVec> = + vec![3].try_into().unwrap(); + assert_ok!(Fusion::set_pool( + RawOrigin::Root.into(), + BTC_POOL_ID, + None, + Some(FusionPoolState::Open), // Not mandatory to set pool to open to put rewards + ConfigOp::Noop, + ConfigOp::Noop, + Some(retry_rewards_for_eras) + )); + + // We check that the pool was set and the reward too + System::assert_has_event(RuntimeEvent::Fusion(Event::RewardSet { + era: 3, + rewarded_pools: vec![1], + total_rewarded: missed_rewards, + paused_pools: vec![], + paused_pools_missed_rewards: vec![], + retry: true, + })); + System::assert_has_event(RuntimeEvent::Fusion(Event::PoolSet { + pool_id: 1, + apy: None, + state: Some(FusionPoolState::Open), + nominator: ConfigOp::Noop, + boost_data: ConfigOp::Noop, + })); + }); + } + + #[test] + fn set_pool_pausing_pool_works() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + // We need to make the reward fail so we can try it again + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + // Run to some era so rewards get generated + run_to_era(10); + + // Pause de pool + assert_ok!(Fusion::set_pool( + RawOrigin::Root.into(), + BTC_POOL_ID, + None, + Some(FusionPoolState::Paused), + ConfigOp::Noop, + ConfigOp::Noop, + None + )); + + // We should have rewards until era 10 + run_to_era(15); + + for era in 3..=15 { + if era <= 10 { + assert!(EraRewards::::get(era, BTC_POOL_ID).is_some()); + } else { + assert!(EraRewards::::get(era, BTC_POOL_ID).is_none()); + } + } + + // We unpause the pool + assert_ok!(Fusion::set_pool( + RawOrigin::Root.into(), + BTC_POOL_ID, + None, + Some(FusionPoolState::Open), + ConfigOp::Noop, + ConfigOp::Noop, + None + )); + + // Rewards should get generated again after 1 era, so era 17 + run_to_era(51); + for era in 17..=50 { + assert!(EraRewards::::get(era, BTC_POOL_ID).is_some()); + } + }); + } + + #[test] + fn bad_origin() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let non_root_origin: RuntimeOrigin = RawOrigin::Signed(ALICE).into(); + let state = Some(FusionPoolState::Open); + + assert_noop!( + Fusion::set_pool( + non_root_origin, + AVAIL_POOL_ID, + None, + state, + ConfigOp::Noop, + ConfigOp::Noop, + None + ), + BadOrigin + ); + }); + } + + #[test] + fn pool_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + + let root: RuntimeOrigin = RawOrigin::Root.into(); + + let apy = Some(Perbill::from_percent(5)); + let state = Some(FusionPoolState::Open); + let nominator: ConfigOp = ConfigOp::Set(POOL_NOMINATOR_ROLE_ACCOUNT); + let boost_data: ConfigOp<(Perbill, u128)> = ConfigOp::Noop; + + assert_noop!( + Fusion::set_pool(root, INVALID_ID, apy, state, nominator, boost_data, None), + Error::::PoolNotFound + ); + }); + } + + #[test] + fn pool_is_destroying() { + new_test_ext().execute_with(|| { + create_avail_currency(); + let mut pool = create_avail_pool(); + + pool.state = FusionPoolState::Destroying; + Pools::::insert(AVAIL_POOL_ID, pool); + + let root: RuntimeOrigin = RawOrigin::Root.into(); + let apy = Some(Perbill::from_percent(5)); + let state = Some(FusionPoolState::Open); + let nominator: ConfigOp = ConfigOp::Set(POOL_NOMINATOR_ROLE_ACCOUNT); + let boost_data: ConfigOp<(Perbill, u128)> = ConfigOp::Noop; + + assert_noop!( + Fusion::set_pool(root, AVAIL_POOL_ID, apy, state, nominator, boost_data, None), + Error::::PoolIsDestroying + ); + }); + } + + #[test] + fn invalid_apy() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let root: RuntimeOrigin = RawOrigin::Root.into(); + let invalid_apy = Some(Perbill::zero()); + let state = Some(FusionPoolState::Open); + let nominator: ConfigOp = ConfigOp::Set(POOL_NOMINATOR_ROLE_ACCOUNT); + let boost_data: ConfigOp<(Perbill, u128)> = ConfigOp::Noop; + + assert_noop!( + Fusion::set_pool( + root, + AVAIL_POOL_ID, + invalid_apy, + state, + nominator, + boost_data, + None + ), + Error::::InvalidAPY + ); + }); + } + + #[test] + fn cannot_set_pool_to_destroying() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let root: RuntimeOrigin = RawOrigin::Root.into(); + let apy = Some(Perbill::from_percent(5)); + let state = Some(FusionPoolState::Destroying); + let nominator: ConfigOp = ConfigOp::Set(POOL_NOMINATOR_ROLE_ACCOUNT); + let boost_data: ConfigOp<(Perbill, u128)> = ConfigOp::Noop; + + assert_noop!( + Fusion::set_pool(root, AVAIL_POOL_ID, apy, state, nominator, boost_data, None), + Error::::CannotSetPoolToDestroying + ); + }); + } + + #[test] + fn pool_is_not_nominating() { + new_test_ext().execute_with(|| { + create_avail_currency(); + let mut pool = create_avail_pool(); + + pool.targets.clear(); + Pools::::insert(AVAIL_POOL_ID, pool); + + let root: RuntimeOrigin = RawOrigin::Root.into(); + let apy = Some(Perbill::from_percent(5)); + let state = Some(FusionPoolState::Open); + let nominator: ConfigOp = ConfigOp::Set(POOL_NOMINATOR_ROLE_ACCOUNT); + let boost_data: ConfigOp<(Perbill, u128)> = ConfigOp::Noop; + + assert_noop!( + Fusion::set_pool(root, AVAIL_POOL_ID, apy, state, nominator, boost_data, None), + Error::::PoolIsNotNominating + ); + }); + } + + #[test] + fn currency_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + let root: RuntimeOrigin = RawOrigin::Root.into(); + + let apy = Some(Perbill::from_percent(5)); + let state = Some(FusionPoolState::Open); + let nominator: ConfigOp = ConfigOp::Set(POOL_NOMINATOR_ROLE_ACCOUNT); + let boost_data: ConfigOp<(Perbill, u128)> = ConfigOp::Noop; + + Currencies::::remove(AVAIL_CURRENCY_ID); + + assert_noop!( + Fusion::set_pool(root, AVAIL_POOL_ID, apy, state, nominator, boost_data, None), + Error::::CurrencyNotFound + ); + }); + } + + #[test] + fn currency_destroyed() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + let mut currency = Currencies::::get(AVAIL_CURRENCY_ID).unwrap(); + + currency.is_destroyed = true; + Currencies::::insert(AVAIL_CURRENCY_ID, currency); + + let root: RuntimeOrigin = RawOrigin::Root.into(); + let apy = Some(Perbill::from_percent(5)); + let state = Some(FusionPoolState::Open); + let nominator: ConfigOp = ConfigOp::Set(POOL_NOMINATOR_ROLE_ACCOUNT); + let boost_data: ConfigOp<(Perbill, u128)> = ConfigOp::Noop; + + assert_noop!( + Fusion::set_pool(root, AVAIL_POOL_ID, apy, state, nominator, boost_data, None), + Error::::CurrencyDestroyed + ); + }); + } + + #[test] + fn setting_boost_work_as_intended() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + + // No boost are set, check that if we set boost to none, nothing changes + assert_ok!(Fusion::set_pool( + RawOrigin::Root.into(), + BTC_POOL_ID, + None, + None, + ConfigOp::Noop, + ConfigOp::Remove, + None + )); + + assert!(Pools::::get(BTC_POOL_ID) + .unwrap() + .boost_data + .is_none()); + assert!(!HasBoost::::get(BTC_POOL_ID, fusion_address)); + assert!(PoolsWithBoost::::get(BTC_POOL_ID).is_none()); + + // No boost are set, we add a boost, see that data is correct, no user should have boost ofc + assert_ok!(Fusion::set_pool( + RawOrigin::Root.into(), + BTC_POOL_ID, + None, + None, + ConfigOp::Noop, + ConfigOp::Set((Perbill::from_percent(2), 1 * AVAIL)), + None + )); + let boost_data = BoostData:: { + additional_apy: Perbill::from_percent(2), + min_avail_to_earn: 1 * AVAIL, + elligible_total_points: 0, + elligible_members: BoundedVec::default(), + }; + let new_pool = Pools::::get(BTC_POOL_ID).unwrap(); + let new_pool_boost = new_pool.boost_data.unwrap(); + assert_eq!(boost_data.additional_apy, new_pool_boost.additional_apy); + assert_eq!( + boost_data.min_avail_to_earn, + new_pool_boost.min_avail_to_earn + ); + assert_eq!( + boost_data.elligible_total_points, + new_pool_boost.elligible_total_points + ); + assert_eq!( + boost_data.elligible_members, + new_pool_boost.elligible_members + ); + assert!(!HasBoost::::get(BTC_POOL_ID, fusion_address)); + assert_eq!(PoolsWithBoost::::get(BTC_POOL_ID).unwrap(), 1 * AVAIL); + + // Now we add a user to a pool with boost, we set the boost for the user and we set the boost to something else. + // It should not change a thing as we cannot remove non-boost-elligible members on-chain + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + // Now we add 1 Avail in the user balance and we stake it + Fusion::add_to_currency_balance(fusion_address, AVAIL_CURRENCY_ID, 1 * AVAIL, false) + .unwrap(); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + AVAIL_POOL_ID, + 1 * AVAIL + )); + + // Now the user join the pool boost + assert_ok!(Fusion::set_pool_boost_allocations( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BoundedVec::try_from(vec![BTC_POOL_ID]).unwrap(), + )); + // And we can change the boost + assert_ok!(Fusion::set_pool( + RawOrigin::Root.into(), + BTC_POOL_ID, + None, + None, + ConfigOp::Noop, + ConfigOp::Set((Perbill::from_percent(2), 1_000_000 * AVAIL)), + None + )); + // And we check that user still has boost, cause we was part of it before + let new_pool = Pools::::get(BTC_POOL_ID).unwrap(); + let new_pool_boost = new_pool.boost_data.unwrap(); + assert_eq!(new_pool_boost.additional_apy, Perbill::from_percent(2)); + assert_eq!( + new_pool_boost.elligible_total_points, + 1_000_000_000_000_000_000 + ); + assert_eq!(new_pool_boost.elligible_members, vec![fusion_address]); + assert_eq!(new_pool_boost.min_avail_to_earn, 1_000_000 * AVAIL); + assert!(HasBoost::::get(BTC_POOL_ID, fusion_address)); + assert_eq!( + PoolsWithBoost::::get(BTC_POOL_ID).unwrap(), + 1_000_000 * AVAIL + ); + + // Now we can remove the boost and check that everything is fine + assert_ok!(Fusion::set_pool( + RawOrigin::Root.into(), + BTC_POOL_ID, + None, + None, + ConfigOp::Noop, + ConfigOp::Remove, + None + )); + assert!(Pools::::get(BTC_POOL_ID) + .unwrap() + .boost_data + .is_none()); + assert!(!HasBoost::::get(BTC_POOL_ID, fusion_address)); + assert!(PoolsWithBoost::::get(BTC_POOL_ID).is_none()); + }) + } +} + +mod destroy_pool { + use super::*; + + #[test] + fn destroy_pool_set_to_destroying() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + assert_ok!(Fusion::destroy_pool( + RawOrigin::Root.into(), + AVAIL_POOL_ID, + None + )); + + let pool = Pools::::get(AVAIL_POOL_ID).unwrap(); + assert_eq!(pool.state, FusionPoolState::Destroying); + + System::assert_last_event(RuntimeEvent::Fusion(Event::PoolDestroying { + pool_id: AVAIL_POOL_ID, + })); + }); + } + + #[test] + fn destroy_pool_actually_destroyed() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + // Before setting to destroying we will use a user to stake + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + // Let's progress to an advanced era so some rewards get generated + run_to_era(5); + + // We set destroying to true + assert_ok!(Fusion::destroy_pool( + RawOrigin::Root.into(), + BTC_POOL_ID, + None + )); + let pool = Pools::::get(BTC_POOL_ID).unwrap(); + assert_eq!(pool.state, FusionPoolState::Destroying); + + // Now we do the cleanups before calling destroy again to actually delete it + // We need to unbond, remove members, claim all rewards for the pool + // Now that the pool is destroying, we can call permissionless extrinsic to clean + assert_ok!(Fusion::unbond_currency_other( + RawOrigin::Signed(POOL_NOMINATOR_ROLE_ACCOUNT).into(), + fusion_address, + BTC_POOL_ID + )); + + let era = Staking::active_era().unwrap().index; + let unbonding_period = FusionBondingDuration::get(); + run_to_era(era + unbonding_period); + + let pool = Pools::::get(BTC_POOL_ID).unwrap(); + assert_eq!(pool.state, FusionPoolState::Destroying); + + assert_ok!(Fusion::withdraw_unbonded_currency_other( + RawOrigin::Signed(POOL_NOMINATOR_ROLE_ACCOUNT).into(), + fusion_address, + BTC_POOL_ID + )); + + // Now that there is not user left, we need to claim all additional rewards + let era = Staking::active_era().unwrap().index; + let history_depth = HistoryDepth::get(); + let start_era = era.saturating_sub(history_depth); + for era in start_era..era { + if let Some(reward) = EraRewards::::get(era, BTC_POOL_ID) { + if reward.rewards != reward.claimed_rewards + || reward.additional_rewards != reward.additional_claimed_rewards + { + // This means we have additional rewards to claim, we need to claim for each user + if let Some(exposure) = Exposures::::get(era, BTC_POOL_ID) { + for user_points in exposure.user_points { + let fusion_address = user_points.0; + let has_already_claimed_for_era = + ClaimedRewards::::contains_key( + era, + (BTC_POOL_ID, fusion_address), + ); + if !has_already_claimed_for_era { + assert_ok!(Fusion::claim_rewards( + RawOrigin::Signed(POOL_NOMINATOR_ROLE_ACCOUNT).into(), + era, + BTC_POOL_ID, + fusion_address + )); + } + } + } + } + } + } + + // Now we can actually destroy the pool + assert_ok!(Fusion::destroy_pool( + RawOrigin::Root.into(), + BTC_POOL_ID, + Some(RANDOM_POT) + )); + + assert!(Pools::::get(BTC_POOL_ID).is_none()); + System::assert_has_event(RuntimeEvent::Fusion(Event::PoolDeleted { + pool_id: BTC_POOL_ID, + leftover: 1000004677160839005423, + })); + }); + } + + #[test] + fn bad_origin() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + assert_noop!( + Fusion::destroy_pool(RawOrigin::Signed(ALICE).into(), AVAIL_POOL_ID, None), + BadOrigin + ); + }); + } + + #[test] + fn destroy_pool_not_found() { + new_test_ext().execute_with(|| { + let root: RuntimeOrigin = RawOrigin::Root.into(); + + assert_noop!( + Fusion::destroy_pool(root, INVALID_ID, Some(RANDOM_POT)), + Error::::PoolNotFound + ); + }); + } + + #[test] + fn pool_cannot_be_cleaned_due_to_members() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let root: RuntimeOrigin = RawOrigin::Root.into(); + + assert_ok!(Fusion::destroy_pool(root.clone(), AVAIL_POOL_ID, None)); + + let mut pool = Pools::::get(AVAIL_POOL_ID).unwrap(); + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + pool.members.try_push((fusion_address, 1)).unwrap(); + Pools::::insert(AVAIL_POOL_ID, pool); + + assert_noop!( + Fusion::destroy_pool(root, AVAIL_POOL_ID, Some(RANDOM_POT)), + Error::::PoolCannotBeCleaned + ); + }); + } + + #[test] + fn pool_cannot_be_cleaned_due_to_unclaimed_rewards() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let root: RuntimeOrigin = RawOrigin::Root.into(); + assert_ok!(Fusion::destroy_pool(root.clone(), AVAIL_POOL_ID, None)); + run_to_era(2); + + EraRewards::::insert( + 1, + AVAIL_POOL_ID, + EraReward { + rewards: 100, + claimed_rewards: 50, + additional_rewards: 50, + additional_claimed_rewards: 25, + }, + ); + + assert_noop!( + Fusion::destroy_pool(root, AVAIL_POOL_ID, Some(RANDOM_POT)), + Error::::PoolCannotBeCleaned + ); + }); + } + + #[test] + fn no_leftover_destination_provided() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let root: RuntimeOrigin = RawOrigin::Root.into(); + + assert_ok!(Fusion::destroy_pool(root.clone(), AVAIL_POOL_ID, None)); + + let mut pool = Pools::::get(AVAIL_POOL_ID).unwrap(); + pool.total_staked_points = 0; + pool.total_staked_native = 0; + pool.total_unbonding_native = 0; + pool.members.clear(); + Pools::::insert(AVAIL_POOL_ID, pool); + + assert_noop!( + Fusion::destroy_pool(root, AVAIL_POOL_ID, None), + Error::::NoLeftoverDestinationProvided + ); + }); + } + + #[test] + fn other_pools_exist() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + let root: RuntimeOrigin = RawOrigin::Root.into(); + + assert_noop!( + Fusion::destroy_pool(root, AVAIL_POOL_ID, Some(RANDOM_POT)), + Error::::OtherPoolsExist + ); + }); + } +} + +mod fill_pool_account { + use super::*; + + #[test] + fn fill_pool_account() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let pool_funds_account = Fusion::get_pool_funds_account(AVAIL_POOL_ID); + let initial_balance = Balances::free_balance(pool_funds_account); + let amount = 1 * AVAIL; + + assert_ok!(Fusion::fill_pool_account( + RawOrigin::Signed(ALICE).into(), + AVAIL_POOL_ID, + amount + )); + + let final_balance = Balances::free_balance(pool_funds_account); + assert_eq!(final_balance, initial_balance + amount); + + System::assert_last_event(RuntimeEvent::Fusion(Event::FundsAccountFilled { + sender: ALICE, + amount, + })); + }); + } + + #[test] + fn invalid_amount() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let sender = ALICE; + let invalid_amount = 0; + + assert_noop!( + Fusion::fill_pool_account( + RawOrigin::Signed(sender).into(), + AVAIL_POOL_ID, + invalid_amount + ), + Error::::InvalidAmount + ); + }); + } + + #[test] + fn insufficient_balance() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let sender = ALICE; + let amount = 1_000 * AVAIL; + + // Ensure the sender has no balance + assert_ok!(Balances::force_set_balance( + RawOrigin::Root.into(), + sender, + 1 * AVAIL, + )); + assert_eq!(Balances::free_balance(sender), 1 * AVAIL); + + assert_noop!( + Fusion::fill_pool_account(RawOrigin::Signed(sender).into(), AVAIL_POOL_ID, amount), + TokenError::FundsUnavailable + ); + }); + } +} + +mod nominate { + use super::*; + + #[test] + fn nominate_from_root() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let root = RawOrigin::Root.into(); + let valid_targets: BoundedVec = + vec![VALIDATOR_1, VALIDATOR_2].try_into().unwrap(); + + assert_ok!(Fusion::nominate(root, AVAIL_POOL_ID, valid_targets.clone())); + + let pool = Pools::::get(AVAIL_POOL_ID).unwrap(); + assert_eq!(pool.targets, valid_targets); + + System::assert_last_event(RuntimeEvent::Fusion(Event::Nominated { + pool_id: AVAIL_POOL_ID, + targets: valid_targets, + })); + }); + } + + #[test] + fn nominate_from_nominator() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let nominator = RawOrigin::Signed(POOL_NOMINATOR_ROLE_ACCOUNT).into(); + let valid_targets: BoundedVec = + vec![VALIDATOR_1, VALIDATOR_2].try_into().unwrap(); + + assert_ok!(Fusion::nominate( + nominator, + AVAIL_POOL_ID, + valid_targets.clone() + )); + + let pool = Pools::::get(AVAIL_POOL_ID).unwrap(); + assert_eq!(pool.targets, valid_targets); + + System::assert_last_event(RuntimeEvent::Fusion(Event::Nominated { + pool_id: AVAIL_POOL_ID, + targets: valid_targets, + })); + }); + } + + #[test] + fn bad_origin() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let no_origin = RawOrigin::None.into(); + let valid_targets: BoundedVec = + vec![VALIDATOR_1, VALIDATOR_2].try_into().unwrap(); + + assert_noop!( + Fusion::nominate(no_origin, AVAIL_POOL_ID, valid_targets), + BadOrigin + ); + }); + } + + #[test] + fn pool_not_found() { + new_test_ext().execute_with(|| { + let root = RawOrigin::Root.into(); + let valid_targets: BoundedVec = + vec![VALIDATOR_1, VALIDATOR_2].try_into().unwrap(); + + assert_noop!( + Fusion::nominate(root, INVALID_ID, valid_targets), + Error::::PoolNotFound + ); + }); + } + + #[test] + fn not_authorized() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let nominator = RawOrigin::Signed(ALICE).into(); + let valid_targets: BoundedVec = + vec![VALIDATOR_1, VALIDATOR_2].try_into().unwrap(); + + assert_noop!( + Fusion::nominate(nominator, AVAIL_POOL_ID, valid_targets), + Error::::NotAuthorized + ); + }); + } + + #[test] + fn pool_is_destroying() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let valid_targets: BoundedVec = + vec![VALIDATOR_1, VALIDATOR_2].try_into().unwrap(); + + assert_ok!(Fusion::destroy_pool( + RawOrigin::Root.into(), + AVAIL_POOL_ID, + None + )); + + assert_noop!( + Fusion::nominate(RawOrigin::Root.into(), AVAIL_POOL_ID, valid_targets), + Error::::PoolIsDestroying + ); + }); + } + + #[test] + fn active_pool_needs_targets() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let empty_targets: BoundedVec = vec![].try_into().unwrap(); + + assert_noop!( + Fusion::nominate(RawOrigin::Root.into(), AVAIL_POOL_ID, empty_targets), + Error::::ActivePoolNeedsTargets + ); + }); + } + + #[test] + fn no_valid_validators() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let root = RawOrigin::Root.into(); + let invalid_targets: BoundedVec = vec![ALICE].try_into().unwrap(); + + assert_noop!( + Fusion::nominate(root, AVAIL_POOL_ID, invalid_targets), + Error::::NoValidValidators + ); + }); + } +} + +// TODO Commented as the extrinsic is mocked for test +mod set_controller_address { + // use super::*; + + // #[test] + // fn set_controller_from_controller() { + // new_test_ext().execute_with(|| { + // let fusion_address = FusionAddress::EvmAddress(H160::zero()); + // let old_controller = FUSION_STAKER; + // let new_controller = ALICE; + + // FusionAddressToSubstrateAddress::::insert(fusion_address, old_controller); + + // assert_eq!( + // FusionAddressToSubstrateAddress::::get(fusion_address), + // Some(old_controller) + // ); + + // assert_ok!(Fusion::set_controller_address( + // RawOrigin::Signed(old_controller).into(), + // fusion_address, + // Some(new_controller) + // )); + + // assert_eq!( + // FusionAddressToSubstrateAddress::::get(fusion_address), + // Some(new_controller) + // ); + + // System::assert_last_event(RuntimeEvent::Fusion(Event::ControllerAddressSet { + // fusion_address, + // new_controller_address: Some(new_controller), + // })); + // }); + // } + + // #[test] + // fn set_controller_from_root() { + // new_test_ext().execute_with(|| { + // let fusion_address = FusionAddress::EvmAddress(H160::zero()); + // let old_controller = FUSION_STAKER; + + // FusionAddressToSubstrateAddress::::insert(fusion_address, old_controller); + + // assert_eq!( + // FusionAddressToSubstrateAddress::::get(fusion_address), + // Some(old_controller) + // ); + + // assert_ok!(Fusion::set_controller_address( + // RawOrigin::Root.into(), + // fusion_address, + // None + // )); + + // assert_eq!( + // FusionAddressToSubstrateAddress::::get(fusion_address), + // None + // ); + + // System::assert_last_event(RuntimeEvent::Fusion(Event::ControllerAddressSet { + // fusion_address, + // new_controller_address: None, + // })); + // }); + // } + + // #[test] + // fn bad_origin() { + // new_test_ext().execute_with(|| { + // create_avail_currency(); + // create_avail_pool(); + + // let no_origin = RawOrigin::None.into(); + // let fusion_address = FusionAddress::EvmAddress(H160::zero()); + + // assert_noop!( + // Fusion::set_controller_address(no_origin, fusion_address, None), + // BadOrigin + // ); + // }); + // } + + // #[test] + // fn invalid_substrate_address_not_mapped() { + // new_test_ext().execute_with(|| { + // let fusion_address = FusionAddress::EvmAddress(H160::zero()); + // let sender = FUSION_STAKER; + + // assert_noop!( + // Fusion::set_controller_address( + // RawOrigin::Signed(sender).into(), + // fusion_address, + // Some(ALICE) + // ), + // Error::::InvalidSubstrateAddress + // ); + // }); + // } + + // #[test] + // fn invalid_substrate_address_incorrect_controller() { + // new_test_ext().execute_with(|| { + // let fusion_address = FusionAddress::EvmAddress(H160::zero()); + // FusionAddressToSubstrateAddress::::insert(fusion_address, ALICE); + // let sender = FUSION_STAKER; + + // assert_noop!( + // Fusion::set_controller_address( + // RawOrigin::Signed(sender).into(), + // fusion_address, + // Some(ALICE) + // ), + // Error::::InvalidSubstrateAddress + // ); + // }); + // } + + // #[test] + // fn root_can_only_remove_controller() { + // new_test_ext().execute_with(|| { + // let fusion_address = FusionAddress::EvmAddress(H160::zero()); + // FusionAddressToSubstrateAddress::::insert(fusion_address, FUSION_STAKER); + + // assert_noop!( + // Fusion::set_controller_address(RawOrigin::Root.into(), fusion_address, Some(ALICE)), + // Error::::RootCanOnlyRemoveController + // ); + // }); + // } + + // #[test] + // fn cannot_set_controller_for_slash_destination() { + // new_test_ext().execute_with(|| { + // let slash_destination = FusionAddress::EvmAddress(H160::repeat_byte(0x01)); + + // assert_noop!( + // Fusion::set_controller_address( + // RawOrigin::Signed(SLASH_DESTINATION).into(), + // slash_destination, + // Some(ALICE) + // ), + // Error::::CannotSetControllerForSlashDestination + // ); + // }); + // } +} + +mod set_slash_destination { + use super::*; + + #[test] + fn set_slash_destination() { + new_test_ext().execute_with(|| { + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = ALICE; + + assert_ok!(Fusion::set_slash_destination( + RawOrigin::Root.into(), + Some(fusion_address), + Some(controller_address) + )); + + assert_eq!(SlashDestination::::get(), Some(fusion_address)); + assert_eq!( + FusionAddressToSubstrateAddress::::get(fusion_address), + Some(controller_address) + ); + + System::assert_last_event(RuntimeEvent::Fusion(Event::SlashDestinationSet { + fusion_address: Some(fusion_address), + controller_address: Some(controller_address), + })); + + assert_ok!(Fusion::set_slash_destination( + RawOrigin::Root.into(), + None, + None + )); + + assert_eq!(SlashDestination::::get(), None); + assert_eq!( + FusionAddressToSubstrateAddress::::get(fusion_address), + None + ); + + System::assert_last_event(RuntimeEvent::Fusion(Event::SlashDestinationSet { + fusion_address: None, + controller_address: None, + })); + }); + } + + #[test] + fn bad_origin() { + new_test_ext().execute_with(|| { + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = ALICE; + + assert_noop!( + Fusion::set_slash_destination( + RawOrigin::Signed(ALICE).into(), + Some(fusion_address), + Some(controller_address) + ), + BadOrigin + ); + }); + } +} + +mod update_max_tvl { + use super::*; + + #[test] + fn update_max_tvl() { + new_test_ext().execute_with(|| { + let root = RawOrigin::Root.into(); + let initial_tvl = 5_000 * AVAIL; + let new_max_tvl = 10_000 * AVAIL; + + TotalValueLockedData::::put(TVLData { + total_value_locked: initial_tvl, + max_total_value_locked: initial_tvl, + }); + + assert_ok!(Fusion::update_max_tvl(root, new_max_tvl)); + + let tvl_data = TotalValueLockedData::::get(); + assert_eq!(tvl_data.max_total_value_locked, new_max_tvl); + assert_eq!(tvl_data.total_value_locked, initial_tvl); + + System::assert_last_event(RuntimeEvent::Fusion(Event::MaxTVLUpdated(new_max_tvl))); + }); + } + + #[test] + fn bad_origin() { + new_test_ext().execute_with(|| { + let non_root_origin = RawOrigin::Signed(ALICE).into(); + let new_max_tvl = 10_000 * AVAIL; + + assert_noop!( + Fusion::update_max_tvl(non_root_origin, new_max_tvl), + BadOrigin + ); + }); + } + + #[test] + fn max_tvl_reached() { + new_test_ext().execute_with(|| { + let root = RawOrigin::Root.into(); + let initial_tvl = 5_000 * AVAIL; + let new_max_tvl = 4_000 * AVAIL; + + TotalValueLockedData::::put(TVLData { + total_value_locked: initial_tvl, + max_total_value_locked: initial_tvl, + }); + + assert_noop!( + Fusion::update_max_tvl(root, new_max_tvl), + Error::::MaxTVLReached + ); + }); + } +} + +mod set_compounding { + use super::*; + + #[test] + fn set_compounding() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + assert_ok!(Fusion::set_compounding( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + false, + )); + + assert!( + !Memberships::::get(fusion_address, BTC_POOL_ID) + .unwrap() + .is_compounding, + ); + + System::assert_last_event(RuntimeEvent::Fusion(Event::CompoundingSet { + fusion_address, + pool_id: BTC_POOL_ID, + compound: false, + })); + + assert_ok!(Fusion::set_compounding( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + true, + )); + + assert!( + Memberships::::get(fusion_address, BTC_POOL_ID) + .unwrap() + .is_compounding, + ); + + System::assert_last_event(RuntimeEvent::Fusion(Event::CompoundingSet { + fusion_address, + pool_id: BTC_POOL_ID, + compound: true, + })); + }); + } + + #[test] + fn invalid_substrate_address() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + FusionAddressToSubstrateAddress::::remove(fusion_address); + assert_noop!( + Fusion::set_compounding( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + false, + ), + Error::::InvalidSubstrateAddress + ); + }); + } + + #[test] + fn membership_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + assert_noop!( + Fusion::set_compounding( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + false, + ), + Error::::MembershipNotFound + ); + }); + } + + #[test] + fn pool_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + Pools::::remove(BTC_POOL_ID); + + assert_noop!( + Fusion::set_compounding( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + false, + ), + Error::::PoolNotFound + ); + }); + } + + #[test] + fn currency_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + Currencies::::remove(BTC_CURRENCY_ID); + + assert_noop!( + Fusion::set_compounding( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + false, + ), + Error::::CurrencyNotFound + ); + }); + } + + #[test] + fn cannot_set_compounding_with_less_than_minimum() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + let mut membership = Memberships::::get(fusion_address, BTC_POOL_ID).unwrap(); + membership.active_points = 0; + Memberships::::insert(fusion_address, BTC_POOL_ID, membership); + + assert_ok!(Fusion::set_compounding( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + false, + )); + }); + } +} + +mod stake { + use super::*; + + #[test] + fn stake() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 200_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + System::assert_last_event(RuntimeEvent::Fusion(Event::PoolJoined { + fusion_address, + pool_id: BTC_POOL_ID, + currency_id: BTC_POOL_ID, + amount: 100_000_000, + points: 1_000_000_000_000_000_000, + })); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + System::assert_last_event(RuntimeEvent::Fusion(Event::PoolBondExtra { + fusion_address, + pool_id: BTC_POOL_ID, + currency_id: BTC_POOL_ID, + amount: 100_000_000, + points: 1_000_000_000_000_000_000, + })); + }); + } + + #[test] + fn invalid_substrate_address() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_noop!( + Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + ), + Error::::InvalidSubstrateAddress + ); + }); + } + + #[test] + fn pool_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_noop!( + Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + INVALID_ID, + 100_000_000 + ), + Error::::PoolNotFound + ); + }); + } + + #[test] + fn currency_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + Currencies::::remove(BTC_CURRENCY_ID); + + assert_noop!( + Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + ), + Error::::CurrencyNotFound + ); + }); + } + + #[test] + fn invalid_amount() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_noop!( + Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 0 + ), + Error::::InvalidAmount + ); + }); + } + + #[test] + fn pool_not_open() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + let mut pool = Pools::::get(BTC_POOL_ID).unwrap(); + pool.state = FusionPoolState::Paused; + Pools::::insert(BTC_POOL_ID, pool); + + assert_noop!( + Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 10_000_000 + ), + Error::::PoolNotOpen + ); + + let mut pool = Pools::::get(BTC_POOL_ID).unwrap(); + pool.state = FusionPoolState::Blocked; + Pools::::insert(BTC_POOL_ID, pool); + + assert_noop!( + Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 10_000_000 + ), + Error::::PoolNotOpen + ); + + let mut pool = Pools::::get(BTC_POOL_ID).unwrap(); + pool.state = FusionPoolState::Destroying; + Pools::::insert(BTC_POOL_ID, pool); + + assert_noop!( + Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 10_000_000 + ), + Error::::PoolNotOpen + ); + }); + } + + #[test] + fn currency_destroyed() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + let mut currency = Currencies::::get(BTC_CURRENCY_ID).unwrap(); + currency.is_destroyed = true; + Currencies::::insert(BTC_CURRENCY_ID, currency); + + assert_noop!( + Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 10_000_000 + ), + Error::::CurrencyDestroyed + ); + }); + } + + #[test] + fn bond_would_exceed_max_for_currency() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance( + fusion_address, + BTC_CURRENCY_ID, + 100_000_000_000, + false, + ) + .unwrap(); + + assert_noop!( + Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000_000 + ), + Error::::BondWouldExceedMaxForCurrency + ); + }); + } + + #[test] + fn no_currency_balance_for_user() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + + assert_noop!( + Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 10_000_000 + ), + Error::::NoCurrencyBalanceForUser + ); + }); + } + + #[test] + fn not_enough_currency_balance_for_user() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 10_000_000, false) + .unwrap(); + + assert_noop!( + Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 10_000_001 + ), + Error::::NotEnoughCurrencyBalanceForUser + ); + }); + } + + #[test] + fn bond_amount_too_low() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000, false) + .unwrap(); + + assert_noop!( + Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000 + ), + Error::::BondAmoundTooLow + ); + }); + } + + #[test] + fn pool_membership_limit_reached() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + let random_address = FusionAddress::EvmAddress(H160::repeat_byte(0x01)); + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 10_000_000, false) + .unwrap(); + + let mut pool = Pools::::get(BTC_POOL_ID).unwrap(); + for _ in 0..MaxMembersPerPool::get() { + pool.members.try_push((random_address, 0)).unwrap(); + } + Pools::::insert(BTC_POOL_ID, pool); + + assert_noop!( + Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 10_000_000 + ), + Error::::PoolMemberLimitReached + ); + }); + } + + #[test] + fn bond_extra_bond_amount_too_low() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 200_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + System::assert_last_event(RuntimeEvent::Fusion(Event::PoolJoined { + fusion_address, + pool_id: BTC_POOL_ID, + currency_id: BTC_POOL_ID, + amount: 100_000_000, + points: 1_000_000_000_000_000_000, + })); + + let mut membership = Memberships::::get(fusion_address, BTC_POOL_ID).unwrap(); + membership.active_points = 0; + Memberships::::insert(fusion_address, BTC_POOL_ID, membership); + + assert_noop!( + Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 1 + ), + Error::::BondAmoundTooLow + ); + }); + } + + #[test] + fn max_tvl_reached() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance( + fusion_address, + BTC_CURRENCY_ID, + 1_000_000_000_000_000, + false, + ) + .unwrap(); + + assert_ok!(Fusion::set_currency( + RawOrigin::Root.into(), + BTC_CURRENCY_ID, + None, + Some(1_000_000_000_000_000), + None + )); + + assert_noop!( + Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 1_000_000_000_000_000 + ), + Error::::MaxTVLReached + ); + }); + } +} + +mod claim_rewards { + use super::*; + + #[test] + fn claim_rewards() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + let pool = create_btc_pool(); + let staked_amount = 100_000_000; + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + let era_to_run = 4; + run_to_era(era_to_run); + let era_to_reward = era_to_run - 1; + + assert_ok!(Fusion::claim_rewards( + RawOrigin::Signed(controller_address).into(), + era_to_reward, + BTC_POOL_ID, + fusion_address, + )); + + let reward = 3802000000000; + + let era_duration: u128 = EraDurations::::get(era_to_reward).unwrap().into(); + let user_points = Memberships::::get(fusion_address, BTC_POOL_ID) + .unwrap() + .active_points; + let staked_amount_in_avail: u128 = pool + .points_to_avail(user_points, BTC_POOL_ID, None, None) + .unwrap(); + let milliseconds_per_year: u128 = 1000 * 3600 * 24 * 36525 / 100; + + let expected_reward_for_a_year = pool.apy * staked_amount_in_avail; + let fraction_of_year = Perbill::from_rational(era_duration, milliseconds_per_year); + let expected_reward = fraction_of_year * expected_reward_for_a_year; + + // When we claim, it also compounds the reward amount to the avail pool + System::assert_has_event(RuntimeEvent::Fusion(Event::PoolJoined { + fusion_address, + currency_id: AVAIL_CURRENCY_ID, + pool_id: AVAIL_POOL_ID, + amount: reward, + points: reward, + })); + + System::assert_last_event(RuntimeEvent::Fusion(Event::RewardClaimed { + fusion_address, + pool_id: BTC_POOL_ID, + era: era_to_reward, + reward, + })); + + assert_eq!(reward, expected_reward); + + // Now let's add a boost to the pool, join the boost and claim boosted rewards + assert_ok!(Fusion::set_pool( + RawOrigin::Root.into(), + BTC_POOL_ID, + None, + None, + ConfigOp::Noop, + ConfigOp::Set((Perbill::from_percent(10), 0)), + None + )); + assert_ok!(Fusion::set_pool_boost_allocations( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BoundedVec::try_from(vec![BTC_POOL_ID]).unwrap() + )); + + let era_to_run = era_to_run + 3; // Boost will take effect in reward 2 eras later so 3 to get rewards + run_to_era(era_to_run); + let era_to_reward = era_to_run - 1; + + // We now claim boosted rewards + assert_ok!(Fusion::claim_rewards( + RawOrigin::Signed(controller_address).into(), + era_to_reward, + BTC_POOL_ID, + fusion_address, + )); + + let reward = 7604000000000; + let pool = Pools::::get(BTC_POOL_ID).unwrap(); + let era_duration: u128 = EraDurations::::get(era_to_reward).unwrap().into(); + let user_points = Memberships::::get(fusion_address, BTC_POOL_ID) + .unwrap() + .active_points; + let staked_amount_in_avail: u128 = pool + .points_to_avail(user_points, BTC_POOL_ID, None, None) + .unwrap(); + let milliseconds_per_year: u128 = 1000 * 3600 * 24 * 36525 / 100; + + let expected_reward_for_a_year = + (pool.apy + pool.boost_data.unwrap().additional_apy) * staked_amount_in_avail; + let fraction_of_year = Perbill::from_rational(era_duration, milliseconds_per_year); + let expected_reward = fraction_of_year * expected_reward_for_a_year; + + // When we claim, it also compounds the reward amount to the avail pool, now we should add extra + System::assert_has_event(RuntimeEvent::Fusion(Event::PoolBondExtra { + fusion_address, + currency_id: AVAIL_CURRENCY_ID, + pool_id: AVAIL_POOL_ID, + amount: reward, + points: reward, + })); + + System::assert_last_event(RuntimeEvent::Fusion(Event::RewardClaimed { + fusion_address, + pool_id: BTC_POOL_ID, + era: era_to_reward, + reward, + })); + + assert_eq!(reward, expected_reward); + }); + } + + #[test] + fn claim_rewards_clears_era_rewards() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + let staked_amount = 100_000_000; + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + let fusion_address2 = FusionAddress::EvmAddress(H160::repeat_byte(0x01)); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address2, controller_address); + Fusion::add_to_currency_balance(fusion_address2, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address2, + BTC_POOL_ID, + staked_amount + )); + + let era_to_run = 4; + run_to_era(era_to_run); + let era_to_reward = era_to_run - 1; + + assert_ok!(Fusion::claim_rewards( + RawOrigin::Signed(controller_address).into(), + era_to_reward, + BTC_POOL_ID, + fusion_address, + )); + assert_ok!(Fusion::claim_rewards( + RawOrigin::Signed(controller_address).into(), + era_to_reward, + BTC_POOL_ID, + fusion_address2, + )); + + let era_rewards = EraRewards::::get(era_to_reward, BTC_POOL_ID).unwrap(); + assert_eq!(era_rewards.rewards, era_rewards.claimed_rewards); + assert_eq!( + era_rewards.additional_rewards, + era_rewards.additional_claimed_rewards + ); + }); + } + + #[test] + fn exposure_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + + assert_noop!( + Fusion::claim_rewards( + RawOrigin::Signed(controller_address).into(), + 1, + BTC_POOL_ID, + fusion_address, + ), + Error::::ExposureNotFound + ); + }); + } + + #[test] + fn no_rewards_for_era() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + run_to_era(3); + + assert_noop!( + Fusion::claim_rewards( + RawOrigin::Signed(controller_address).into(), + 3, + BTC_POOL_ID, + fusion_address, + ), + Error::::NoRewardsForEra + ); + }); + } + + #[test] + fn already_claimed() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + run_to_era(4); + + assert_ok!(Fusion::claim_rewards( + RawOrigin::Signed(controller_address).into(), + 3, + BTC_POOL_ID, + fusion_address, + )); + + assert_noop!( + Fusion::claim_rewards( + RawOrigin::Signed(controller_address).into(), + 3, + BTC_POOL_ID, + fusion_address, + ), + Error::::AlreadyClaimed + ); + }); + } + + #[test] + fn user_not_found_in_exposure() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address_1 = FusionAddress::EvmAddress(H160::repeat_byte(0x01)); + let controller_address_1 = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address_1, controller_address_1); + Fusion::add_to_currency_balance(fusion_address_1, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address_1).into(), + fusion_address_1, + BTC_POOL_ID, + 100_000_000 + )); + + let fusion_address_2 = FusionAddress::EvmAddress(H160::repeat_byte(0x02)); + let controller_address_2 = RANDOM_POT; + FusionAddressToSubstrateAddress::::insert(fusion_address_2, controller_address_2); + + run_to_era(4); + + assert_noop!( + Fusion::claim_rewards( + RawOrigin::Signed(controller_address_2).into(), + 3, + BTC_POOL_ID, + fusion_address_2 + ), + Error::::UserNotFoundInExposure + ); + }); + } + + #[test] + fn no_rewards_to_claim() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::repeat_byte(0x01)); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + let era_to_run = 4; + run_to_era(era_to_run); + let era_to_reward = era_to_run - 1; + + EraRewards::::insert( + era_to_reward, + BTC_POOL_ID, + EraReward { + rewards: 0, + claimed_rewards: 0, + additional_rewards: 0, + additional_claimed_rewards: 0, + }, + ); + + assert_noop!( + Fusion::claim_rewards( + RawOrigin::Signed(controller_address).into(), + era_to_reward, + BTC_POOL_ID, + fusion_address + ), + Error::::NoRewardsToClaim + ); + }); + } + + #[test] + fn currency_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::repeat_byte(0x01)); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + run_to_era(4); + + Currencies::::remove(AVAIL_CURRENCY_ID); // Used to convert avail_to_currency + + assert_noop!( + Fusion::claim_rewards( + RawOrigin::Signed(controller_address).into(), + 3, + BTC_POOL_ID, + fusion_address + ), + Error::::CurrencyNotFound + ); + }); + } + + #[test] + fn not_enough_claimable_balance_in_pool() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::repeat_byte(0x01)); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + run_to_era(4); + + let pool_claimable_account = Fusion::get_pool_claimable_account(BTC_POOL_ID); + assert_ok!(Balances::force_set_balance( + RawOrigin::Root.into(), + pool_claimable_account, + avail_core::currency::Balance::zero(), + )); + + assert_noop!( + Fusion::claim_rewards( + RawOrigin::Signed(controller_address).into(), + 3, + BTC_POOL_ID, + fusion_address + ), + Error::::NotEnoughClaimableBalanceInPool + ); + }); + } + + #[test] + fn pool_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::repeat_byte(0x01)); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + run_to_era(4); + + Pools::::remove(AVAIL_POOL_ID); + + assert_noop!( + Fusion::claim_rewards( + RawOrigin::Signed(controller_address).into(), + 3, + BTC_POOL_ID, + fusion_address + ), + Error::::PoolNotFound + ); + }); + } +} + +mod unbond_currency { + use super::*; + + #[test] + fn unbond_currency() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + let pool = create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + let staked_amount = 100_000_000; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + run_to_era(4); + + let partial_unbond_amount = 50_000_000; + assert_ok!(Fusion::unbond_currency( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + Some(partial_unbond_amount) + )); + + let membership = Memberships::::get(fusion_address, BTC_POOL_ID).unwrap(); + assert_eq!( + membership.active_points, + pool.currency_to_points(partial_unbond_amount, None) + .unwrap() + ); + + System::assert_has_event(RuntimeEvent::Fusion(Event::CurrencyUnbonded { + fusion_address, + pool_id: BTC_POOL_ID, + currency_id: BTC_CURRENCY_ID, + unbonded_amount: partial_unbond_amount, + points: pool + .currency_to_points(partial_unbond_amount, None) + .unwrap(), + era: 4, + })); + + assert_ok!(Fusion::unbond_currency( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + None + )); + + let membership = Memberships::::get(fusion_address, BTC_POOL_ID).unwrap(); + assert_eq!(membership.active_points, 0); + + System::assert_last_event(RuntimeEvent::Fusion(Event::CurrencyUnbonded { + fusion_address, + pool_id: BTC_POOL_ID, + currency_id: BTC_CURRENCY_ID, + unbonded_amount: 50_000_000, + points: pool.currency_to_points(50_000_000, None).unwrap(), + era: 4, + })); + }); + } + + #[test] + fn invalid_substrate_address() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let staked_amount = 100_000_000; + + FusionAddressToSubstrateAddress::::insert(fusion_address, FUSION_STAKER); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + let unbond_amount = 50_000_000; + let incorrect_controller_address = ALICE; + assert_noop!( + Fusion::unbond_currency( + RawOrigin::Signed(incorrect_controller_address).into(), + fusion_address, + BTC_POOL_ID, + Some(unbond_amount) + ), + Error::::InvalidSubstrateAddress + ); + }); + } + + #[test] + fn membership_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let staked_amount = 100_000_000; + FusionAddressToSubstrateAddress::::insert(fusion_address, FUSION_STAKER); + + assert_noop!( + Fusion::unbond_currency( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + Some(staked_amount) + ), + Error::::MembershipNotFound + ); + }); + } + + #[test] + fn no_active_points_to_unbond() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + FusionAddressToSubstrateAddress::::insert(fusion_address, FUSION_STAKER); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + assert_ok!(Fusion::unbond_currency( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + Some(100_000_000) + )); + + assert_noop!( + Fusion::unbond_currency( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + Some(50_000_000) + ), + Error::::NoActivePointsToUnbond + ); + }); + } + + #[test] + fn pool_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + FusionAddressToSubstrateAddress::::insert(fusion_address, FUSION_STAKER); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + Pools::::remove(BTC_POOL_ID); + + assert_noop!( + Fusion::unbond_currency( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + Some(50_000_000) + ), + Error::::PoolNotFound + ); + }); + } + + #[test] + fn currency_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + FusionAddressToSubstrateAddress::::insert(fusion_address, FUSION_STAKER); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + Currencies::::remove(BTC_CURRENCY_ID); + + assert_noop!( + Fusion::unbond_currency( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + Some(50_000_000) + ), + Error::::CurrencyNotFound + ); + }); + } + + #[test] + fn pool_is_not_destroying() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + FusionAddressToSubstrateAddress::::insert(fusion_address, FUSION_STAKER); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + assert_noop!( + Fusion::do_unbond(fusion_address, BTC_POOL_ID, Some(50_000_000), true), + Error::::PoolIsNotDestroying + ); + }); + } + + #[test] + fn invalid_amount() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + FusionAddressToSubstrateAddress::::insert(fusion_address, FUSION_STAKER); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + assert_noop!( + Fusion::unbond_currency( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + Some(0) + ), + Error::::InvalidAmount + ); + }); + } + + #[test] + fn invalid_unbond_amount() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + FusionAddressToSubstrateAddress::::insert(fusion_address, FUSION_STAKER); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + assert_noop!( + Fusion::unbond_currency( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + Some(200_000_000) + ), + Error::::InvalidUnbondAmount + ); + }); + } + + #[test] + fn amount_will_go_below_minimum() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + FusionAddressToSubstrateAddress::::insert(fusion_address, FUSION_STAKER); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + Currencies::::mutate(BTC_CURRENCY_ID, |currency| { + if let Some(c) = currency { + c.min_amount = 50_000_000; + } + }); + + assert_noop!( + Fusion::unbond_currency( + RawOrigin::Signed(FUSION_STAKER).into(), + fusion_address, + BTC_POOL_ID, + Some(75_000_000) + ), + Error::::AmountWillGoBelowMinimum + ); + }); + } + + #[test] + fn pool_member_limit_reached() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + let staked_amount = 100_000_000; + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + run_to_era(4); + + for i in 1..(1 + MaxMembersPerPool::get()) { + let extra_address = FusionAddress::EvmAddress(H160::repeat_byte(i as u8)); + UnbondingChunks::::mutate(BTC_POOL_ID, 4, |chunks| { + chunks.try_push((extra_address, 1)).unwrap(); + }); + } + + assert_noop!( + Fusion::unbond_currency( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + Some(50_000_000) + ), + Error::::PoolMemberLimitReached + ); + }); + } + + #[test] + fn max_unbonding_chunks_exceeded() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + let staked_amount = 100_000_000; + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + run_to_era(4); + + Memberships::::mutate(fusion_address, BTC_POOL_ID, |membership| { + if let Some(membership) = membership { + for era in 100..(100 + MaxUnbonding::get()) { + membership.unbonding_eras.try_push(era).unwrap(); + } + } + }); + + assert_noop!( + Fusion::unbond_currency( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + Some(50_000_000) + ), + Error::::MaxUnbondingChunksExceeded + ); + }); + } +} + +mod withdraw_unbonded_currency { + use super::*; + + #[test] + fn withdraw_unbonded_currency() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + let staked_amount = 100_000_000; + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + assert_ok!(Fusion::unbond_currency( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + Some(staked_amount) + )); + + let bonding_duration = FusionBondingDuration::get(); + let active_era = Staking::active_era().unwrap().index; + run_to_era(active_era + bonding_duration + 1); + + assert_ok!(Fusion::withdraw_unbonded_currency( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID + )); + + System::assert_has_event(RuntimeEvent::Fusion(Event::CurrencyWithdrawn { + fusion_address, + pool_id: BTC_POOL_ID, + currency_id: BTC_CURRENCY_ID, + amount: staked_amount, + })); + System::assert_has_event(RuntimeEvent::Fusion(Event::PoolMembershipRemoved { + fusion_address, + pool_id: BTC_POOL_ID, + })); + }); + } + + #[test] + fn membership_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + + assert_noop!( + Fusion::withdraw_unbonded_currency( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID + ), + Error::::MembershipNotFound + ); + }); + } + + #[test] + fn pool_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + let staked_amount = 100_000_000; + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + Pools::::remove(BTC_POOL_ID); + + assert_noop!( + Fusion::withdraw_unbonded_currency( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID + ), + Error::::PoolNotFound + ); + }); + } + + #[test] + fn currency_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + let staked_amount = 100_000_000; + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + Currencies::::remove(BTC_CURRENCY_ID); + + assert_noop!( + Fusion::withdraw_unbonded_currency( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID + ), + Error::::CurrencyNotFound + ); + }); + } + + #[test] + fn pool_is_not_destroying() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + let staked_amount = 100_000_000; + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + assert_noop!( + Fusion::do_withdraw_unbonded_currency(fusion_address, BTC_POOL_ID, true), + Error::::PoolIsNotDestroying + ); + }); + } + + #[test] + fn no_funds_to_withdraw() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + let staked_amount = 100_000_000; + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + let bonding_duration = FusionBondingDuration::get(); + let active_era = Staking::active_era().unwrap().index; + run_to_era(active_era + bonding_duration + 1); + + assert_noop!( + Fusion::withdraw_unbonded_currency( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID + ), + Error::::NoFundsToWithdraw + ); + }); + } + + #[test] + fn invalid_substrate_address() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + let staked_amount = 100_000_000; + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let incorrect_controller_address = NOMINATOR_1; + FusionAddressToSubstrateAddress::::insert(fusion_address, FUSION_STAKER); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_noop!( + Fusion::withdraw_unbonded_currency( + RawOrigin::Signed(incorrect_controller_address).into(), + fusion_address, + BTC_POOL_ID + ), + Error::::InvalidSubstrateAddress + ); + }); + } + + #[test] + fn no_funds_to_withdraw_bonding_duration_not_passed() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + let staked_amount = 100_000_000; + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + assert_ok!(Fusion::unbond_currency( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + Some(staked_amount) + )); + + run_to_era(3); + + assert_noop!( + Fusion::withdraw_unbonded_currency( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID + ), + Error::::NoFundsToWithdraw + ); + }); + } +} + +mod unbond_currency_other { + use super::*; + + #[test] + fn unbond_currency_other() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let staked_amount = 100_000_000; + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + let mut pool = Pools::::get(BTC_POOL_ID).unwrap(); + pool.state = FusionPoolState::Destroying; + Pools::::insert(BTC_POOL_ID, pool); + + let other_address = ALICE; + assert_ok!(Fusion::unbond_currency_other( + RawOrigin::Signed(other_address).into(), + fusion_address, + BTC_POOL_ID + )); + + let unbonding_chunks = UnbondingChunks::::get(BTC_POOL_ID, 1); + assert_eq!(unbonding_chunks.len(), 1); + assert_eq!(unbonding_chunks[0].0, fusion_address); + assert_eq!(unbonding_chunks[0].1, staked_amount); + }); + } +} + +mod withdraw_unbonded_currency_other { + use super::*; + + #[test] + fn withdraw_unbonded_currency_other() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let staked_amount = 100_000_000; + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + assert_ok!(Fusion::unbond_currency( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + Some(staked_amount) + )); + + let bonding_duration = FusionBondingDuration::get(); + let active_era = Staking::active_era().unwrap().index; + run_to_era(active_era + bonding_duration); + + let mut pool = Pools::::get(BTC_POOL_ID).unwrap(); + pool.state = FusionPoolState::Destroying; + Pools::::insert(BTC_POOL_ID, pool); + + let other_address = ALICE; + assert_ok!(Fusion::withdraw_unbonded_currency_other( + RawOrigin::Signed(other_address).into(), + fusion_address, + BTC_POOL_ID + )); + + let balance = Fusion::user_currency_balances(fusion_address, BTC_CURRENCY_ID).unwrap(); + assert_eq!(balance.amount, staked_amount); + }); + } +} + +mod withdraw_avail_to_controller { + use super::*; + + #[test] + fn withdraw_avail_to_controller() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let staked_amount = 100_000_000; + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + assert_ok!(Fusion::set_compounding( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + false + )); + + run_to_era(4); + + assert_ok!(Fusion::claim_rewards( + RawOrigin::Signed(controller_address).into(), + 3, + BTC_POOL_ID, + fusion_address + )); + + let controller_balance_before = Balances::free_balance(controller_address); + + let avail_currency_balance = + UserCurrencyBalances::::get(fusion_address, AVAIL_CURRENCY_ID) + .unwrap() + .amount; + + // Full withdraw + assert_ok!(Fusion::withdraw_avail_to_controller( + RawOrigin::Signed(controller_address).into(), + fusion_address, + avail_currency_balance + )); + + let controller_balance_after = Balances::free_balance(controller_address); + + assert!(controller_balance_after == controller_balance_before + avail_currency_balance); + + System::assert_last_event(RuntimeEvent::Fusion(Event::AvailWithdrawnToController { + fusion_address, + controller: controller_address, + amount: avail_currency_balance, + })); + + // Partial withdraw + Fusion::add_to_currency_balance( + fusion_address, + AVAIL_CURRENCY_ID, + 1500000000000000000, + false, + ) + .unwrap(); + Balances::force_set_balance( + RawOrigin::Root.into(), + Fusion::avail_account(), + 10 * AVAIL, + ) + .unwrap(); + assert_ok!(Fusion::withdraw_avail_to_controller( + RawOrigin::Signed(controller_address).into(), + fusion_address, + 500000000000000000 + )); + System::assert_last_event(RuntimeEvent::Fusion(Event::AvailWithdrawnToController { + fusion_address, + controller: controller_address, + amount: 500000000000000000, + })); + }); + } + + #[test] + fn invalid_substrate_address() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + + assert_noop!( + Fusion::withdraw_avail_to_controller( + RawOrigin::Signed(controller_address).into(), + fusion_address, + 1, + ), + Error::::InvalidSubstrateAddress + ); + }); + } + + #[test] + fn invalid_amount() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + + assert_noop!( + Fusion::withdraw_avail_to_controller( + RawOrigin::Signed(controller_address).into(), + fusion_address, + 0, + ), + Error::::InvalidAmount + ); + }); + } + + #[test] + fn currency_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let staked_amount = 100_000_000; + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance( + fusion_address, + AVAIL_CURRENCY_ID, + staked_amount, + false, + ) + .unwrap(); + + Currencies::::remove(AVAIL_CURRENCY_ID); + + assert_noop!( + Fusion::withdraw_avail_to_controller( + RawOrigin::Signed(controller_address).into(), + fusion_address, + 1 + ), + Error::::CurrencyNotFound + ); + }); + } + + #[test] + fn no_controller_address_for_user() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let staked_amount = 100_000_000; + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + + Fusion::add_to_currency_balance( + fusion_address, + AVAIL_CURRENCY_ID, + staked_amount, + false, + ) + .unwrap(); + + assert_noop!( + Fusion::do_withdraw_avail_to_controller(fusion_address, 1), + Error::::NoControllerAddressForUser, + ); + }); + } + + #[test] + fn no_currency_balance_for_user() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + + assert_noop!( + Fusion::withdraw_avail_to_controller( + RawOrigin::Signed(controller_address).into(), + fusion_address, + 1 + ), + Error::::NoCurrencyBalanceForUser + ); + }); + } + + #[test] + fn no_funds_to_withdraw() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, AVAIL_CURRENCY_ID, 0, false).unwrap(); + + assert_noop!( + Fusion::withdraw_avail_to_controller( + RawOrigin::Signed(controller_address).into(), + fusion_address, + 1, + ), + Error::::NoFundsToWithdraw + ); + }); + } + + #[test] + fn not_enough_currency_balance_for_user() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, AVAIL_CURRENCY_ID, 1, false).unwrap(); + + assert_noop!( + Fusion::withdraw_avail_to_controller( + RawOrigin::Signed(controller_address).into(), + fusion_address, + 2, + ), + Error::::NotEnoughCurrencyBalanceForUser + ); + }); + } + + #[test] + fn amount_will_go_below_minimum() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, AVAIL_CURRENCY_ID, AVAIL, false) + .unwrap(); + + assert_noop!( + Fusion::withdraw_avail_to_controller( + RawOrigin::Signed(controller_address).into(), + fusion_address, + 1, + ), + Error::::AmountWillGoBelowMinimum + ); + }); + } +} + +mod set_pool_boost_allocations { + use super::*; + + #[test] + fn set_pool_boost_allocations() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + assert_ok!(Fusion::set_pool( + RawOrigin::Root.into(), + BTC_POOL_ID, + None, + None, + ConfigOp::Noop, + ConfigOp::Set((Perbill::from_percent(5), 1 * AVAIL)), + None + )); + assert_ok!(Fusion::set_pool( + RawOrigin::Root.into(), + AVAIL_POOL_ID, + None, + None, + ConfigOp::Noop, + ConfigOp::Set((Perbill::from_percent(5), 2 * AVAIL)), + None + )); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + Fusion::add_to_currency_balance(fusion_address, AVAIL_CURRENCY_ID, 3 * AVAIL, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + AVAIL_POOL_ID, + 3 * AVAIL + )); + + assert_ok!(Fusion::set_pool_boost_allocations( + RawOrigin::Root.into(), + fusion_address, + BoundedVec::try_from(vec![BTC_POOL_ID]).unwrap() + )); + System::assert_last_event(RuntimeEvent::Fusion(Event::UserBoostAllocationsOptimized { + fusion_address, + pools_added: vec![BTC_POOL_ID], + pools_removed: vec![], + })); + + assert_ok!(Fusion::set_pool_boost_allocations( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BoundedVec::try_from(vec![BTC_POOL_ID, AVAIL_POOL_ID]).unwrap() + )); + System::assert_last_event(RuntimeEvent::Fusion(Event::UserBoostAllocationsOptimized { + fusion_address, + pools_added: vec![AVAIL_POOL_ID], + pools_removed: vec![], + })); + }); + } + + #[test] + fn not_authorized() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + assert_ok!(Fusion::set_pool( + RawOrigin::Root.into(), + AVAIL_POOL_ID, + None, + None, + ConfigOp::Noop, + ConfigOp::Set((Perbill::from_percent(5), 1 * AVAIL)), + None + )); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, AVAIL_CURRENCY_ID, 1 * AVAIL, false) + .unwrap(); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + AVAIL_POOL_ID, + 1 * AVAIL + )); + + assert_ok!(Fusion::set_pool_boost_allocations( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BoundedVec::try_from(vec![AVAIL_POOL_ID]).unwrap() + )); + + assert_noop!( + Fusion::set_pool_boost_allocations( + RawOrigin::Root.into(), + fusion_address, + BoundedVec::try_from(vec![BTC_POOL_ID]).unwrap() + ), + Error::::NotAuthorized + ); + }); + } + + #[test] + fn no_avail_membership() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, AVAIL_CURRENCY_ID, 1 * AVAIL, false) + .unwrap(); + + assert_noop!( + Fusion::set_pool_boost_allocations( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BoundedVec::try_from(vec![BTC_POOL_ID]).unwrap() + ), + Error::::NoAvailMembership + ); + }); + } + + #[test] + fn currency_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + assert_ok!(Fusion::set_pool( + RawOrigin::Root.into(), + BTC_POOL_ID, + None, + None, + ConfigOp::Noop, + ConfigOp::Set((Perbill::from_percent(5), 1 * AVAIL)), + None + )); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, AVAIL_CURRENCY_ID, 1 * AVAIL, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + AVAIL_POOL_ID, + 1 * AVAIL + )); + + Currencies::::remove(AVAIL_CURRENCY_ID); + + assert_noop!( + Fusion::set_pool_boost_allocations( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BoundedVec::try_from(vec![BTC_POOL_ID]).unwrap() + ), + Error::::CurrencyNotFound + ); + }); + } + + #[test] + fn pool_not_found() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, AVAIL_CURRENCY_ID, 1 * AVAIL, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + AVAIL_POOL_ID, + 1 * AVAIL + )); + + Pools::::remove(AVAIL_POOL_ID); + + assert_noop!( + Fusion::set_pool_boost_allocations( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BoundedVec::try_from(vec![BTC_POOL_ID]).unwrap() + ), + Error::::PoolNotFound + ); + }); + } + + #[test] + fn pool_has_no_boost() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_POOL_ID, 10_000_000, false) + .unwrap(); + Fusion::add_to_currency_balance(fusion_address, AVAIL_POOL_ID, 1 * AVAIL, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 10_000_000 + )); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + AVAIL_POOL_ID, + 1 * AVAIL + )); + + assert_noop!( + Fusion::set_pool_boost_allocations( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BoundedVec::try_from(vec![BTC_POOL_ID]).unwrap() + ), + Error::::PoolHasNoBoost + ); + }); + } + + #[test] + fn not_enough_avail_for_boost() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + assert_ok!(Fusion::set_pool( + RawOrigin::Root.into(), + BTC_POOL_ID, + None, + None, + ConfigOp::Noop, + ConfigOp::Set((Perbill::from_percent(5), 2 * AVAIL)), + None + )); + assert_ok!(Fusion::set_pool( + RawOrigin::Root.into(), + AVAIL_POOL_ID, + None, + None, + ConfigOp::Noop, + ConfigOp::Set((Perbill::from_percent(5), 1 * AVAIL)), + None + )); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 10_000_000, false) + .unwrap(); + Fusion::add_to_currency_balance(fusion_address, AVAIL_CURRENCY_ID, 1 * AVAIL, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_CURRENCY_ID, + 10_000_000 + )); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + AVAIL_POOL_ID, + 1 * AVAIL + )); + + assert_noop!( + Fusion::set_pool_boost_allocations( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BoundedVec::try_from(vec![BTC_POOL_ID, AVAIL_POOL_ID]).unwrap() + ), + Error::::NotEnoughAvailForBoost + ); + }); + } +} + +mod withdraw_pool_account { + use super::*; + + #[test] + fn withdraw_pool_account() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let dest_account = ALICE; + let withdraw_amount = 1 * AVAIL; + let initial_amount = Balances::free_balance(&dest_account); + + let mut pool = Pools::::get(AVAIL_POOL_ID).unwrap(); + pool.funds_account = Fusion::get_pool_funds_account(AVAIL_POOL_ID); + Balances::make_free_balance_be(&pool.funds_account, 2 * AVAIL); + + Pools::::insert(AVAIL_POOL_ID, pool); + + assert_ok!(Fusion::withdraw_pool_account( + RawOrigin::Root.into(), + AVAIL_POOL_ID, + withdraw_amount, + dest_account + )); + + assert_eq!( + Balances::free_balance(&dest_account), + initial_amount + withdraw_amount + ); + + System::assert_last_event(RuntimeEvent::Fusion(Event::FundsAccountWithdrawn { + recipient: dest_account, + amount: withdraw_amount, + })); + }); + } + + #[test] + fn bad_origin() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let dest_account = ALICE; + + assert_noop!( + Fusion::withdraw_pool_account( + RawOrigin::Signed(ALICE).into(), + AVAIL_POOL_ID, + 1 * AVAIL, + dest_account + ), + BadOrigin + ); + }); + } + + #[test] + fn invalid_amount() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let dest_account = ALICE; + + assert_noop!( + Fusion::withdraw_pool_account( + RawOrigin::Root.into(), + AVAIL_POOL_ID, + 0, + dest_account + ), + Error::::InvalidAmount + ); + }); + } + + #[test] + fn insufficient_balance() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + + let dest_account = ALICE; + let withdraw_amount = 1 * AVAIL; + + let mut pool = Pools::::get(AVAIL_POOL_ID).unwrap(); + pool.funds_account = Fusion::get_pool_funds_account(AVAIL_POOL_ID); + Balances::make_free_balance_be(&pool.funds_account, withdraw_amount / 2); + + Pools::::insert(AVAIL_POOL_ID, pool); + + assert_noop!( + Fusion::withdraw_pool_account( + RawOrigin::Root.into(), + AVAIL_POOL_ID, + withdraw_amount, + dest_account + ), + TokenError::FundsUnavailable + ); + }); + } +} + +mod sanity_checks { + use super::*; + + #[test] + fn era_progresses_and_native_rewards_are_generated() { + new_test_ext().execute_with(|| { + // Get balance before payout + let init_balance = Balances::free_balance(VALIDATOR_1); + + // Progress to the start of era 5 + run_to_era(5); + + // Check the active era + assert_eq!(Staking::active_era().unwrap().index, 5); + assert_eq!(Session::validators(), vec![VALIDATOR_1, VALIDATOR_2]); + + // Log staking-related storages + for era in 1..=4 { + assert!(Staking::eras_total_stake(era) > avail_core::currency::Balance::zero()); + let reward_points = Staking::eras_reward_points(era); + let validators_with_reward = pallet_staking::ErasRewardPoints::::get(era) + .individual + .keys() + .cloned() + .collect::>(); + assert!(reward_points.total > 0); + assert!(validators_with_reward.len() > 0); + assert!( + Staking::eras_stakers(era, &VALIDATOR_1).total + > avail_core::currency::Balance::zero() + ); + assert!( + Staking::eras_stakers(era, &VALIDATOR_2).total + > avail_core::currency::Balance::zero() + ); + } + + // Check that rewards are correctly generated + let new_balance = Balances::free_balance(VALIDATOR_1); + assert!(new_balance > init_balance); + }); + } + + #[test] + fn pool_receives_staking_rewards() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + let pool = create_btc_pool(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + assert_ok!(Fusion::set_compounding( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + false, + )); + + // Era 1 - We start fusion staking + // Era 2 - Fusion snapshot is done for Era 3 native snapshot + // Era 3 - Native snapshot contains fusion stake + // Era 4 - Fusion user can claim their rewards and pool receives actual staking rewards + // We check that the pool account has received funds + let init_balance = Balances::free_balance(pool.funds_account); + run_to_era(4); + let new_balance = Balances::free_balance(pool.funds_account); + assert!(new_balance > init_balance); + + // Now we check that the fusion user can claim (the checks on numbers are done elsewhere) + let init_fusion_balance = + UserCurrencyBalances::::get(fusion_address, AVAIL_CURRENCY_ID); + assert_ok!(Fusion::claim_rewards( + RawOrigin::Signed(controller_address).into(), + 3, + BTC_POOL_ID, + fusion_address, + )); + let new_fusion_balance = + UserCurrencyBalances::::get(fusion_address, AVAIL_CURRENCY_ID); + + assert!(init_fusion_balance.is_none()); + assert!(new_fusion_balance.is_some()); + }); + } + + #[test] + fn validator_gets_elected_with_fusion_stake() { + new_test_ext().execute_with(|| { + assert_eq!(Session::validators(), vec![VALIDATOR_1, VALIDATOR_2]); + + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + + // Elect only validator 3 + assert_ok!(Fusion::nominate( + RawOrigin::Root.into(), + BTC_POOL_ID, + vec![VALIDATOR_3].try_into().unwrap() + )); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, 100_000_000, false) + .unwrap(); + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + 100_000_000 + )); + + // Validator 3 should be elected during era 3 + run_to_era(3); + assert_eq!(Session::validators(), vec![VALIDATOR_1, VALIDATOR_3]); + + run_to_era(10); + assert_eq!(Session::validators(), vec![VALIDATOR_1, VALIDATOR_3]); + }); + } +} + +mod currency_conversion { + use super::*; + + #[test] + fn currency_to_avail() { + new_test_ext().execute_with(|| { + let (currency, _, _) = create_avail_currency(); + let era = Staking::active_era().unwrap().index; + let avail_in_fusion_currency: FusionCurrencyBalance = 1_000_000_000_000_000_000; + + assert!(matches!( + currency.currency_to_avail(AVAIL_CURRENCY_ID, avail_in_fusion_currency, None), + Ok(AVAIL) + )); + + CurrencyRates::::remove(era, AVAIL_CURRENCY_ID); + assert!(matches!( + currency.currency_to_avail(AVAIL_CURRENCY_ID, avail_in_fusion_currency, None), + Err(Error::::CurrencyRateNotFound) + )); + }) + } + + #[test] + fn avail_to_currency() { + new_test_ext().execute_with(|| { + let (currency, _, _) = create_avail_currency(); + let era = Staking::active_era().unwrap().index; + + assert!(matches!( + currency.avail_to_currency(AVAIL_CURRENCY_ID, AVAIL, None), + Ok(1_000_000_000_000_000_000) + )); + + CurrencyRates::::remove(era, AVAIL_CURRENCY_ID); + assert!(matches!( + currency.currency_to_avail(AVAIL_CURRENCY_ID, AVAIL, None), + Err(Error::::CurrencyRateNotFound) + )); + }) + } + + #[test] + fn points_to_currency() { + new_test_ext().execute_with(|| { + let (currency, _, _) = create_avail_currency(); + let mut pool = create_avail_pool(); + + let one_point: Points = 1_000_000_000_000_000_000; + let amount: FusionCurrencyBalance = 1_000_000_000_000_000_000; + + assert_eq!( + pool.points_to_currency(one_point, Some(¤cy)).unwrap(), + amount + ); + + Currencies::::remove(AVAIL_CURRENCY_ID); + + assert!(matches!( + pool.points_to_currency(one_point, None), + Err(Error::::CurrencyNotFound) + )); + + Currencies::::insert(AVAIL_CURRENCY_ID, currency); + + pool.total_staked_native = amount; + pool.total_staked_points = one_point; + Pools::::insert(AVAIL_POOL_ID, pool); + + let pool = Pools::::get(AVAIL_POOL_ID).unwrap(); + let currency = Currencies::::get(AVAIL_CURRENCY_ID).unwrap(); + + assert_eq!( + pool.points_to_currency(one_point, Some(¤cy)).unwrap(), + amount + ) + }) + } + + #[test] + fn currency_to_points() { + new_test_ext().execute_with(|| { + let (currency, _, _) = create_avail_currency(); + let mut pool = create_avail_pool(); + + let one_point: Points = 1_000_000_000_000_000_000; + let amount: FusionCurrencyBalance = 1_000_000_000_000_000_000; + + assert_eq!( + pool.currency_to_points(amount, Some(¤cy)).unwrap(), + one_point + ); + + Currencies::::remove(AVAIL_CURRENCY_ID); + + assert!(matches!( + pool.currency_to_points(amount, None), + Err(Error::::CurrencyNotFound) + )); + + Currencies::::insert(AVAIL_CURRENCY_ID, currency); + + pool.total_staked_native = amount; + pool.total_staked_points = one_point; + Pools::::insert(AVAIL_POOL_ID, pool); + + let pool = Pools::::get(AVAIL_POOL_ID).unwrap(); + let currency = Currencies::::get(AVAIL_CURRENCY_ID).unwrap(); + + assert_eq!( + pool.currency_to_points(amount, Some(¤cy)).unwrap(), + one_point + ) + }) + } + + #[test] + fn points_to_avail() { + new_test_ext().execute_with(|| { + let (currency, _, _) = create_avail_currency(); + let mut pool = create_avail_pool(); + + let one_point: Points = 1_000_000_000_000_000_000; + let amount: FusionCurrencyBalance = 1_000_000_000_000_000_000; + + assert_eq!( + pool.points_to_avail(one_point, AVAIL_CURRENCY_ID, None, None) + .unwrap(), + AVAIL + ); + + Currencies::::remove(AVAIL_CURRENCY_ID); + + assert!(matches!( + pool.points_to_avail(one_point, AVAIL_CURRENCY_ID, None, None), + Err(Error::::CurrencyNotFound) + )); + + Currencies::::insert(AVAIL_CURRENCY_ID, currency); + + pool.total_staked_native = amount; + pool.total_staked_points = one_point; + Pools::::insert(AVAIL_POOL_ID, pool); + + let pool = Pools::::get(AVAIL_POOL_ID).unwrap(); + + assert_eq!( + pool.points_to_avail(one_point, AVAIL_CURRENCY_ID, None, None) + .unwrap(), + amount + ) + }) + } + + #[test] + fn avail_to_points() { + new_test_ext().execute_with(|| { + let (currency, _, _) = create_avail_currency(); + let mut pool = create_avail_pool(); + + let one_point: Points = 1_000_000_000_000_000_000; + let amount: FusionCurrencyBalance = 1_000_000_000_000_000_000; + + assert_eq!( + pool.avail_to_points(AVAIL, AVAIL_CURRENCY_ID, None, None) + .unwrap(), + AVAIL + ); + + Currencies::::remove(AVAIL_CURRENCY_ID); + + assert!(matches!( + pool.avail_to_points(AVAIL, AVAIL_CURRENCY_ID, None, None), + Err(Error::::CurrencyNotFound) + )); + + Currencies::::insert(AVAIL_CURRENCY_ID, currency); + + pool.total_staked_native = amount; + pool.total_staked_points = one_point; + Pools::::insert(AVAIL_POOL_ID, pool); + + let pool = Pools::::get(AVAIL_POOL_ID).unwrap(); + + assert_eq!( + pool.avail_to_points(AVAIL, AVAIL_CURRENCY_ID, None, None) + .unwrap(), + amount + ) + }) + } +} + +mod slashing { + use super::*; + + #[test] + fn fusion_slashing_works() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + let staked_amount = 100_000_000; + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + let era_to_run = 4; + run_to_end_of_era(era_to_run); + + // Add a slash + add_slash(&VALIDATOR_1, Perbill::from_percent(10)); + System::assert_has_event(RuntimeEvent::Fusion(Event::FusionSlashReported { + pool_id: BTC_POOL_ID, + slash_era: era_to_run, + slash_ratio: Perbill::from_parts(62_504_462), + validator: 100, + })); + + // Add a slash with bigger fraction, should add a new slash + add_slash(&VALIDATOR_1, Perbill::from_percent(90)); + System::assert_has_event(RuntimeEvent::Fusion(Event::FusionSlashReported { + pool_id: BTC_POOL_ID, + slash_era: era_to_run, + slash_ratio: Perbill::from_parts(500_035_701), + validator: 100, + })); + + let pool = Pools::::get(BTC_POOL_ID).unwrap(); + assert!(pool.total_slashed_native == 0); + assert!(pool.pending_slashes.len() == 2); + assert!( + HasPendingSlash::::get(era_to_run, (VALIDATOR_1, pool.funds_account)) == 2 + ); + + let apply_era = SlashDeferDuration::get() + era_to_run + 1; + + assert_ok!(Staking::cancel_deferred_slash( + RawOrigin::Root.into(), + apply_era, + vec![0] + )); + + System::assert_has_event(RuntimeEvent::Fusion(Event::FusionSlashCancelled { + pool_ids: [BTC_POOL_ID].to_vec(), + slash_era: era_to_run, + validators: [100].to_vec(), + })); + + // Check that the slash is indeed canceled + let pool = Pools::::get(BTC_POOL_ID).unwrap(); + assert!(pool.total_slashed_native == 0); + assert_eq!(pool.pending_slashes.len(), 1); + assert!( + HasPendingSlash::::get(era_to_run, (VALIDATOR_1, pool.funds_account)) == 1 + ); + + // Go to the apply era, remaining slash should get applied + run_to_era(SlashDeferDuration::get() + era_to_run + 1); + + System::assert_has_event(RuntimeEvent::Fusion(Event::FusionPoolSlashed { + currency_id: BTC_CURRENCY_ID, + pool_id: BTC_POOL_ID, + slash_era: era_to_run, + amount: 50003570, + })); + + let pool = Pools::::get(BTC_POOL_ID).unwrap(); + assert!(pool.total_slashed_native == 50003570); + assert!(pool.pending_slashes.len() == 0); + assert!( + HasPendingSlash::::get(era_to_run, (VALIDATOR_1, pool.funds_account)) == 0 + ); + }) + } + + #[test] + fn fusion_slashing_works_on_unbonding_funds() { + new_test_ext().execute_with(|| { + create_avail_currency(); + create_avail_pool(); + create_btc_currency(); + create_btc_pool(); + let staked_amount = 100_000_000; + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller_address = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller_address); + Fusion::add_to_currency_balance(fusion_address, BTC_CURRENCY_ID, staked_amount, false) + .unwrap(); + + assert_ok!(Fusion::stake( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + staked_amount + )); + + let era_to_run = 4; + run_to_era(4); + assert_ok!(Fusion::unbond_currency( + RawOrigin::Signed(controller_address).into(), + fusion_address, + BTC_POOL_ID, + Some(staked_amount) + )); + let pool = Pools::::get(BTC_POOL_ID).unwrap(); + let old_unbonding_amount = pool.total_unbonding_native; + + run_to_end_of_era(era_to_run); + add_slash(&VALIDATOR_1, Perbill::from_percent(10)); + run_to_era(SlashDeferDuration::get() + era_to_run + 1); + + let pool = Pools::::get(BTC_POOL_ID).unwrap(); + let new_unbonding_amount = pool.total_unbonding_native; + assert!(old_unbonding_amount > new_unbonding_amount); + }) + } +} + +mod deposit_avail_to_fusion { + use super::*; + + #[test] + fn deposit_avail() { + new_test_ext().execute_with(|| { + create_avail_currency(); + + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller); + + let amount = 10 * AVAIL; + + assert_ok!(Fusion::deposit_avail_to_fusion( + RawOrigin::Signed(controller).into(), + fusion_address, + amount, + )); + + let balance = UserCurrencyBalances::::get(fusion_address, AVAIL_CURRENCY_ID) + .expect("should have a balance entry"); + assert_eq!(balance.amount, amount); + + System::assert_last_event(RuntimeEvent::Fusion(Event::CurrencyDeposited { + fusion_address, + currency_id: AVAIL_CURRENCY_ID, + amount, + })); + }); + } + + #[test] + fn bad_origin() { + new_test_ext().execute_with(|| { + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + assert_noop!( + Fusion::deposit_avail_to_fusion(RawOrigin::None.into(), fusion_address, AVAIL), + BadOrigin + ); + }); + } + + #[test] + fn invalid_amount() { + new_test_ext().execute_with(|| { + create_avail_currency(); + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller); + + assert_noop!( + Fusion::deposit_avail_to_fusion( + RawOrigin::Signed(controller).into(), + fusion_address, + 0 + ), + Error::::InvalidAmount + ); + }); + } + + #[test] + fn currency_not_found() { + new_test_ext().execute_with(|| { + // Don't create the currency + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller); + + assert_noop!( + Fusion::deposit_avail_to_fusion( + RawOrigin::Signed(controller).into(), + fusion_address, + AVAIL + ), + Error::::CurrencyNotFound + ); + }); + } + + #[test] + fn invalid_substrate_address() { + new_test_ext().execute_with(|| { + create_avail_currency(); + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller = FUSION_STAKER; + + assert_noop!( + Fusion::deposit_avail_to_fusion( + RawOrigin::Signed(controller).into(), + fusion_address, + AVAIL + ), + Error::::InvalidSubstrateAddress + ); + }); + } + + #[test] + fn insufficient_balance() { + new_test_ext().execute_with(|| { + create_avail_currency(); + let fusion_address = FusionAddress::EvmAddress(H160::zero()); + let controller = FUSION_STAKER; + FusionAddressToSubstrateAddress::::insert(fusion_address, controller); + + // Send balance to zero for the controller account. + assert_ok!(Balances::force_set_balance( + RawOrigin::Root.into(), + controller, + 0, + )); + + assert_noop!( + Fusion::deposit_avail_to_fusion( + RawOrigin::Signed(controller).into(), + fusion_address, + AVAIL + ), + TokenError::FundsUnavailable + ); + }); + } +} diff --git a/pallets/fusion/src/traits.rs b/pallets/fusion/src/traits.rs new file mode 100644 index 000000000..0823d1547 --- /dev/null +++ b/pallets/fusion/src/traits.rs @@ -0,0 +1,71 @@ +use crate::*; +use pallet_staking::UnappliedSlash; +use sp_staking::EraIndex; + +// A trait that provides data from the staking pallet. +pub trait StakingFusionDataProvider { + /// Returns the active era. + fn active_era() -> EraIndex; + /// Returns the currently planned era. + fn current_era() -> EraIndex; + /// Checks if an account is a validator. + fn is_valid_validator(account: &T::AccountId) -> bool; + /// Checks if a validator has earned era points for an era (meaning he'll get rewards). + fn has_earned_era_points(era: EraIndex, accounts: &[T::AccountId]) -> bool; + /// Gets the unapplied slashes for an era + fn unapplied_slashes(era: EraIndex) -> Vec>>; + /// Adds a dummy validator to both the Session and Staking pallets. + #[cfg(feature = "runtime-benchmarks")] + fn add_dummy_validator(account: T::AccountId); + /// Adds dummy era point for a validator and an era + #[cfg(feature = "runtime-benchmarks")] + fn add_dummy_era_points(validator: T::AccountId, era: EraIndex); + /// Set the active era + #[cfg(feature = "runtime-benchmarks")] + fn set_dummy_active_era(era: EraIndex); +} +impl StakingFusionDataProvider for () { + fn active_era() -> EraIndex { + 0 + } + fn current_era() -> EraIndex { + 0 + } + fn is_valid_validator(_account: &T::AccountId) -> bool { + false + } + fn has_earned_era_points(_era: EraIndex, _accounts: &[T::AccountId]) -> bool { + false + } + fn unapplied_slashes(_era: EraIndex) -> Vec>> { + Vec::new() + } + #[cfg(feature = "runtime-benchmarks")] + fn add_dummy_validator(_account: T::AccountId) { + () + } + #[cfg(feature = "runtime-benchmarks")] + fn add_dummy_era_points(_validator: T::AccountId, _era: EraIndex) { + () + } + #[cfg(feature = "runtime-benchmarks")] + fn set_dummy_active_era(_era: EraIndex) { + () + } +} + +pub trait PoolAccountProvider { + /// Return the pool funds account + fn get_pool_funds_account(id: PoolId) -> T::AccountId; + /// Return the pool claimable account + fn get_pool_claimable_account(id: PoolId) -> T::AccountId; +} +impl PoolAccountProvider for () { + fn get_pool_funds_account(id: PoolId) -> T::AccountId { + T::PalletId::get().into_sub_account_truncating((FusionAccountType::PoolFundsAccount, id)) + } + fn get_pool_claimable_account(id: PoolId) -> T::AccountId { + T::PalletId::get() + .into_sub_account_truncating((FusionAccountType::PoolClaimableAccount, id)) + } +} diff --git a/pallets/fusion/src/types.rs b/pallets/fusion/src/types.rs new file mode 100644 index 000000000..ec643ab79 --- /dev/null +++ b/pallets/fusion/src/types.rs @@ -0,0 +1,488 @@ +use codec::Codec; +use frame_support::pallet_prelude::*; +use sp_core::{H160, H256, H512}; +use sp_runtime::Perbill; +use sp_staking::EraIndex; + +use crate::*; + +/// Type representing a fusion address (for now we use H160 as it's EVM compatible) +#[derive(Clone, Copy, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub enum FusionAddress { + EvmAddress(H160), // 20-byte Ethereum-like address + SolanaAddress(H256), // 32-byte Solana address + Other(H512), // 64-byte general-purpose identifier +} +impl FusionAddress { + /// Create a new Evm Address + pub fn new_evm(address: H160) -> Self { + FusionAddress::EvmAddress(address) + } + /// Create a new Solana Address + pub fn new_solana(address: H256) -> Self { + FusionAddress::SolanaAddress(address) + } + /// Create a new Other address + pub fn new_other(address: H512) -> Self { + FusionAddress::Other(address) + } +} + +/// Type representing a balance for external currency +pub type FusionCurrencyBalance = u128; + +/// Type to represent points +pub type Points = u128; + +/// Type of the currency id +pub type CurrencyId = u32; + +/// Type of the pool id +pub type PoolId = u32; + +/// Possible operations on the configuration values of this pallet. +#[derive(TypeInfo, Debug, Clone, Encode, Decode, PartialEq)] +pub enum ConfigOp { + /// Don't change. + Noop, + /// Set the given value. + Set(T), + /// Remove the value. + Remove, +} + +/// The type of account being created. +#[derive(Encode, Decode)] +pub enum FusionAccountType { + AvailCurrency, + PoolFundsAccount, + PoolClaimableAccount, +} + +/// State of the pool +#[derive(Clone, Copy, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub enum FusionPoolState { + /// Anyone can join, the pool is earning rewards + Open, + /// Nobody can join, the pool is earning rewards + Blocked, + /// Nobody can join, the pool is not earning rewards + Paused, + /// Pool is getting deleted, nobody can join, the pool is not earning rewards + Destroying, +} + +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[scale_info(skip_type_params(T))] +pub struct FusionCurrency { + /// Name of the currency (e.g., "AVAIL", "ETH", "wBTC") + pub name: BoundedVec, + /// Number of decimals to represent 1 unit of the currency (e.g., 8 for wBTC, 18 for ETH) + pub nb_decimals: u8, + /// The amount staked in native form + pub total_staked_native: FusionCurrencyBalance, + /// The amount slashed in native form + pub total_slashed_native: FusionCurrencyBalance, + /// The amount unbonding in native form + pub total_unbonding_native: FusionCurrencyBalance, + /// Maximum allowable stake for this currency (overall) + pub max_amount: FusionCurrencyBalance, + /// Minimum amount to join a pool of this currency + pub min_amount: FusionCurrencyBalance, + /// State of the currency + pub is_destroyed: bool, +} + +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[scale_info(skip_type_params(T))] +pub struct FusionPool { + /// Id of the currency this pool uses + pub currency_id: CurrencyId, + /// Percentage representing annual yield for this pool + pub apy: Perbill, + /// The account used during snapshot and for Phragmen, this account will receive rewards, this account can be topped up + pub funds_account: T::AccountId, + /// The account used to store claimable avail + pub claimable_account: T::AccountId, + /// Optional nominator of the pool, mandate can always manage + pub nominator: Option, + /// The Fusion addresses of members of the pool + pub members: BoundedVec<(FusionAddress, Points), T::MaxMembersPerPool>, + /// The target validators to be nominated by this pool + pub targets: BoundedVec, + /// The amount staked in native form + pub total_staked_native: FusionCurrencyBalance, + /// The amount staked in points + pub total_staked_points: Points, + /// The amount slashed in this pool + pub total_slashed_native: FusionCurrencyBalance, + /// The total amount unbonding in this pool, conversion happens at unbonding + pub total_unbonding_native: FusionCurrencyBalance, + /// State of the pool + pub state: FusionPoolState, + /// Vector of pending slashes + pub pending_slashes: BoundedVec, T::MaxSlashesPerPool>, + /// Data about boost + pub boost_data: Option>, +} + +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[scale_info(skip_type_params(T))] +pub struct BoostData { + /// The additional apy on the pool + pub additional_apy: Perbill, + /// The minimum avail that needs to be allocated to this pool to earn boost + pub min_avail_to_earn: FusionCurrencyBalance, + /// The amount of points in the pool getting boost + pub elligible_total_points: Points, + /// Vector with elligible members + pub elligible_members: BoundedVec, +} + +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[scale_info(skip_type_params(T))] +pub struct FusionMembership { + /// Fusion address of the user + pub fusion_address: FusionAddress, + /// Era where the membership was created + pub joined_era: EraIndex, + /// The stake of the user represented by points + pub active_points: Points, + /// Unbonding eras of the user + pub unbonding_eras: BoundedVec, + /// If true, rewards will go to the AVAIL pool + pub is_compounding: bool, +} + +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct FusionUserCurrencyBalance { + /// Fusion address of the user + pub fusion_address: FusionAddress, + /// Id of the idle currency this pool uses + pub currency_id: CurrencyId, + /// Amount of currency available, for AVAIL, it's the amount you can compound + pub amount: FusionCurrencyBalance, +} + +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[scale_info(skip_type_params(T))] +pub struct FusionExposure { + /// Era of the exposure to compute rewards + pub era: EraIndex, + /// The APY when the exposure was taken + pub apy: Perbill, + /// The total in avail + pub total_avail: BalanceOf, + /// The total points in the pool + pub total_points: Points, + /// The users points in the pool + pub user_points: BoundedVec<(FusionAddress, Points), T::MaxMembersPerPool>, + /// The nominations of the pool at the time of setting the exposure + pub targets: BoundedVec, + /// Used to store the validator(s) actually backed alongside the amount + /// This is populated when exposure are collected + #[allow(clippy::type_complexity)] + pub native_exposure_data: Option), T::MaxTargets>>, + /// Boost additional APY + pub boost_additional_apy: Perbill, + /// The members having boost + pub boost_members: BoundedVec, + /// The total points elligible to boost + pub boost_total_points: Points, + /// The avail equivalent of boost_total_points + pub boost_total_avail: BalanceOf, +} + +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[scale_info(skip_type_params(T))] +pub struct EraReward { + /// The total rewards + pub rewards: BalanceOf, + /// The actual amount of reward claimed + pub claimed_rewards: BalanceOf, + /// The total rewards from boost + pub additional_rewards: BalanceOf, + /// The actual amount of reward claimed from boost + pub additional_claimed_rewards: BalanceOf, +} + +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[scale_info(skip_type_params(T))] +pub struct FusionPendingSlash { + /// Era when the slash happened + pub slash_era: EraIndex, + /// Percentage of the pool funds that got slashed + pub slash_ratio: Perbill, + /// The validator that got slashed + pub validator: T::AccountId, +} + +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[scale_info(skip_type_params(T))] +pub struct TVLData { + /// The total value locked in Fusion from users (in avail) + pub total_value_locked: BalanceOf, + /// The max total allowed values locked in Fusion (when changing conversion rates or staking new currency, this will be checked) + pub max_total_value_locked: BalanceOf, +} + +impl FusionCurrency { + /// Converts a given amount of this external currency to its equivalent in AVAIL. + pub fn currency_to_avail( + &self, + currency_id: CurrencyId, + amount: FusionCurrencyBalance, + era: Option, + ) -> Result, Error> { + let rate = CurrencyRates::::get( + era.unwrap_or_else(T::StakingFusionDataProvider::active_era), + currency_id, + ) + .ok_or(Error::::CurrencyRateNotFound)?; + + let rate = Pallet::::u256(rate.try_into().map_err(|_| Error::::ArithmeticError)?); + let amount = Pallet::::u256(amount); + let divisor = Pallet::::u256(10u128.pow(self.nb_decimals as u32)); + + let avail_value = rate + .saturating_mul(amount) + .checked_div(divisor) + .ok_or(Error::::ArithmeticError)?; + + Ok(Pallet::::balance(avail_value)) + } + + /// Converts a given amount of AVAIL to its equivalent in this external currency. + pub fn avail_to_currency( + &self, + currency_id: CurrencyId, + avail_amount: BalanceOf, + era: Option, + ) -> Result> { + let era = era.unwrap_or_else(T::StakingFusionDataProvider::active_era); + + let rate = + CurrencyRates::::get(era, currency_id).ok_or(Error::::CurrencyRateNotFound)?; + + let rate = Pallet::::u256(rate.try_into().map_err(|_| Error::::ArithmeticError)?); + let avail_amount = Pallet::::u256( + avail_amount + .try_into() + .map_err(|_| Error::::ArithmeticError)?, + ); + let multiplier = Pallet::::u256(10u128.pow(self.nb_decimals as u32)); + + let currency_value = avail_amount + .saturating_mul(multiplier) + .checked_div(rate) + .ok_or(Error::::ArithmeticError)?; + + Ok(Pallet::::fusion_currency(currency_value)) + } +} + +impl FusionPool { + /// Helper to check if the pool is in Open state + pub fn is_active(&self) -> bool { + self.state == FusionPoolState::Open || self.state == FusionPoolState::Blocked + } + /// Converts a given amount of points to its equivalent in external currency. + pub fn points_to_currency( + &self, + points: Points, + currency: Option<&FusionCurrency>, + ) -> Result> { + if self.total_staked_native == 0 && self.total_staked_points == 0 { + let currency_decimals = if let Some(c) = currency { + c.nb_decimals + } else { + let stored_currency = + Currencies::::get(self.currency_id).ok_or(Error::::CurrencyNotFound)?; + stored_currency.nb_decimals + }; + + let divisor = Pallet::::u256(10u128.pow(18 - currency_decimals as u32)); + let points = Pallet::::u256(points); + + let currency_value = points + .checked_div(divisor) + .ok_or(Error::::ArithmeticPointsError)?; + + Ok(Pallet::::fusion_currency(currency_value)) + } else { + ensure!( + self.total_staked_points > 0, + Error::::ArithmeticPointsError + ); + + let points = Pallet::::u256(points); + let total_staked_native = Pallet::::u256(self.total_staked_native); + let total_staked_points = Pallet::::u256(self.total_staked_points); + + let currency_value = points + .saturating_mul(total_staked_native) + .checked_div(total_staked_points) + .ok_or(Error::::ArithmeticPointsError)?; + + Ok(Pallet::::fusion_currency(currency_value)) + } + } + /// Converts a given amount of external currency to its equivalent in points. + pub fn currency_to_points( + &self, + currency_amount: FusionCurrencyBalance, + currency: Option<&FusionCurrency>, + ) -> Result> { + if self.total_staked_native == 0 && self.total_staked_points == 0 { + let currency_decimals = if let Some(c) = currency { + c.nb_decimals + } else { + let currency = + Currencies::::get(self.currency_id).ok_or(Error::::CurrencyNotFound)?; + currency.nb_decimals + }; + let multiplier = Pallet::::u256(10u128.pow(18 - currency_decimals as u32)); + let currency_amount = Pallet::::u256(currency_amount); + + let points = currency_amount.saturating_mul(multiplier); + + Ok(Pallet::::points(points)) + } else { + ensure!( + self.total_staked_native > 0, + Error::::ArithmeticPointsError + ); + + let currency_amount = Pallet::::u256(currency_amount); + let total_staked_native = Pallet::::u256(self.total_staked_native); + let total_staked_points = Pallet::::u256(self.total_staked_points); + + let points = currency_amount + .saturating_mul(total_staked_points) + .checked_div(total_staked_native) + .ok_or(Error::::ArithmeticPointsError)?; + + Ok(Pallet::::points(points)) + } + } + /// Converts a given amount of points to its equivalent in AVAIL. + pub fn points_to_avail( + &self, + points: Points, + currency_id: CurrencyId, + currency: Option<&FusionCurrency>, + era: Option, + ) -> Result, Error> { + let currency_value = self.points_to_currency(points, currency)?; + + let avail_value = if let Some(currency) = currency { + currency.currency_to_avail(currency_id, currency_value, era)? + } else { + let currency = + Currencies::::get(self.currency_id).ok_or(Error::::CurrencyNotFound)?; + currency.currency_to_avail(currency_id, currency_value, era)? + }; + + Ok(avail_value) + } + /// Converts a given amount of AVAIL to its equivalent in points. + pub fn avail_to_points( + &self, + avail_amount: BalanceOf, + currency_id: CurrencyId, + currency: Option<&FusionCurrency>, + era: Option, + ) -> Result> { + let currency_value = if let Some(currency) = currency { + currency.avail_to_currency(currency_id, avail_amount, era)? + } else { + let currency = Currencies::::get(currency_id).ok_or(Error::::CurrencyNotFound)?; + currency.avail_to_currency(currency_id, avail_amount, era)? + }; + + let points = self.currency_to_points(currency_value, currency)?; + Ok(points) + } + + pub fn set_boost( + &mut self, + pool_id: PoolId, + boost_data: Option<(Perbill, FusionCurrencyBalance)>, + ) -> DispatchResult { + match (&self.boost_data, boost_data) { + (None, None) => { + // There is no current boost, nothing to do + }, + (Some(_old_boost), None) => { + // There is some boost, we remove it + // We remove the pool id from the storage of pools with boost + PoolsWithBoost::::remove(pool_id); + + // We remove all the users for this pool in HasBoost + let _ = HasBoost::::clear_prefix(pool_id, u32::MAX, None); + + // We update the pool + self.boost_data = None + }, + (None, Some((apy, min_to_earn))) => { + // There is no current boost, we add it + // We add the pool the to vec of pools having boost + PoolsWithBoost::::insert(pool_id, min_to_earn); + + // We update the pool + self.boost_data = Some(BoostData { + additional_apy: apy, + min_avail_to_earn: min_to_earn, + elligible_total_points: 0, + elligible_members: BoundedVec::default(), + }); + }, + (Some(old_boost), Some((apy, min_to_earn))) => { + // There is already a boost, we update it + PoolsWithBoost::::insert(pool_id, min_to_earn); + + // For each users having boost, + // we need to check if they still belong. + // But it's too expensive to do onchain so we leave them in. + // If we need to clean it, we can remove the boost + // and call the permissionless extrinsic to optimize + self.boost_data = Some(BoostData { + additional_apy: apy, + min_avail_to_earn: min_to_earn, + elligible_total_points: old_boost.elligible_total_points, + elligible_members: old_boost.elligible_members.clone(), + }); + }, + }; + Ok(()) + } +} + +impl Default for TVLData { + fn default() -> Self { + Self { + total_value_locked: BalanceOf::::default(), + max_total_value_locked: BalanceOf::::default(), + } + } +} + +impl TVLData { + /// Checks if adding `amount` to `total_value_locked` is within `max_total_value_locked`. + pub fn can_add(&self, amount: BalanceOf) -> bool { + self.total_value_locked.saturating_add(amount) <= self.max_total_value_locked + } + + /// Adds `amount` to `total_value_locked` if it doesn't exceed `max_total_value_locked`. + /// Returns `Ok(())` if successful, or an error if the addition exceeds the max value. + pub fn add(&mut self, amount: BalanceOf) -> Result<(), Error> { + ensure!(self.can_add(amount), Error::::MaxTVLReached); + self.total_value_locked = self.total_value_locked.saturating_add(amount); + Ok(()) + } + + /// Substract `amount` to `total_value_locked`. + pub fn sub(&mut self, amount: BalanceOf) { + self.total_value_locked = self.total_value_locked.saturating_sub(amount); + } +} diff --git a/pallets/fusion/src/weights.rs b/pallets/fusion/src/weights.rs new file mode 100644 index 000000000..438562603 --- /dev/null +++ b/pallets/fusion/src/weights.rs @@ -0,0 +1,848 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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_fusion` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-12-19, STEPS: `10`, REPEAT: `5`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `DESKTOP-PAL18UV`, CPU: `AMD Ryzen 5 5600X 6-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` + +// Executed Command: +// ./target/release/avail-node +// benchmark +// pallet +// --chain=dev +// --steps=10 +// --repeat=5 +// --pallet=pallet_fusion +// --extrinsic=* +// --heap-pages=4096 +// --header=./HEADER-APACHE2 +// --output=./pallets/weights.rs +// --template +// ./.maintain/frame-weight-template.hbs + +#![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_fusion`. +pub trait WeightInfo { + fn create_currency() -> Weight; + fn set_currency() -> Weight; + fn destroy_currency() -> Weight; + fn set_currency_conversion_rate() -> Weight; + fn create_pool() -> Weight; + fn set_pool() -> Weight; + fn set_pool_with_retry(e: u32) -> Weight; + fn destroy_pool() -> Weight; + fn fill_pool_account() -> Weight; + fn nominate() -> Weight; + fn set_controller_address() -> Weight; + fn set_slash_destination() -> Weight; + fn update_max_tvl() -> Weight; + fn set_compounding() -> Weight; + fn stake() -> Weight; + fn claim_rewards() -> Weight; + fn unbond_currency() -> Weight; + fn withdraw_unbonded_currency() -> Weight; + fn withdraw_avail_to_controller() -> Weight; + fn set_pool_boost_allocations() -> Weight; + fn withdraw_pool_account() -> Weight; + fn deposit_avail_to_fusion() -> Weight; +} + +/// Weights for `pallet_fusion` using the Avail node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRates` (r:0 w:1) + /// Proof: `Fusion::CurrencyRates` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRateChanges` (r:0 w:1) + /// Proof: `Fusion::CurrencyRateChanges` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn create_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `746` + // Estimated: `3592` + // Minimum execution time: 23_073_000 picoseconds. + Weight::from_parts(23_224_000, 3592) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + fn set_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `370` + // Estimated: `3592` + // Minimum execution time: 13_215_000 picoseconds. + Weight::from_parts(16_260_000, 3592) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:0) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRateChanges` (r:0 w:1) + /// Proof: `Fusion::CurrencyRateChanges` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn destroy_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `370` + // Estimated: `14608207` + // Minimum execution time: 18_896_000 picoseconds. + Weight::from_parts(21_140_000, 14608207) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRateChanges` (r:0 w:1) + /// Proof: `Fusion::CurrencyRateChanges` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn set_currency_conversion_rate() -> Weight { + // Proof Size summary in bytes: + // Measured: `370` + // Estimated: `3592` + // Minimum execution time: 13_976_000 picoseconds. + Weight::from_parts(14_607_000, 3592) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsAccountToId` (r:0 w:1) + /// Proof: `Fusion::PoolsAccountToId` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn create_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `370` + // Estimated: `14608207` + // Minimum execution time: 19_125_000 picoseconds. + Weight::from_parts(21_581_000, 14608207) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsWithBoost` (r:0 w:1) + /// Proof: `Fusion::PoolsWithBoost` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn set_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `647` + // Estimated: `14608207` + // Minimum execution time: 28_333_000 picoseconds. + Weight::from_parts(30_467_000, 14608207) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::EraDurations` (r:10 w:0) + /// Proof: `Fusion::EraDurations` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Exposures` (r:20 w:0) + /// Proof: `Fusion::Exposures` (`max_values`: None, `max_size`: Some(14601391), added: 14603866, mode: `MaxEncodedLen`) + /// Storage: `Fusion::EraRewards` (r:10 w:10) + /// Proof: `Fusion::EraRewards` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsWithBoost` (r:0 w:1) + /// Proof: `Fusion::PoolsWithBoost` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// The range of component `e` is `[0, 10]`. + fn set_pool_with_retry(e: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1850730 + e * (2900322 ±0)` + // Estimated: `14608207 + e * (29207732 ±0)` + // Minimum execution time: 72_618_800_000 picoseconds. + Weight::from_parts(73_665_302_277, 0) + .saturating_add(Weight::from_parts(0, 14608207)) + // Standard Error: 226_110_695 + .saturating_add(Weight::from_parts(170_480_782_933, 0).saturating_mul(e.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(e.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(e.into()))) + .saturating_add(Weight::from_parts(0, 29207732).saturating_mul(e.into())) + } + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Fusion::EraRewards` (r:1 w:0) + /// Proof: `Fusion::EraRewards` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Exposures` (r:1 w:0) + /// Proof: `Fusion::Exposures` (`max_values`: None, `max_size`: Some(14601391), added: 14603866, mode: `MaxEncodedLen`) + /// Storage: `Fusion::ClaimedRewards` (r:1 w:0) + /// Proof: `Fusion::ClaimedRewards` (`max_values`: None, `max_size`: Some(105), added: 2580, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsAccountToId` (r:0 w:1) + /// Proof: `Fusion::PoolsAccountToId` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsWithBoost` (r:0 w:1) + /// Proof: `Fusion::PoolsWithBoost` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn destroy_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `1587` + // Estimated: `14608207` + // Minimum execution time: 84_318_000 picoseconds. + Weight::from_parts(87_634_000, 14608207) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn fill_pool_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `280` + // Estimated: `6196` + // Minimum execution time: 45_595_000 picoseconds. + Weight::from_parts(46_417_000, 6196) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + fn nominate() -> Weight { + // Proof Size summary in bytes: + // Measured: `1141` + // Estimated: `14608207` + // Minimum execution time: 22_803_000 picoseconds. + Weight::from_parts(23_324_000, 14608207) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:1) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::SlashDestination` (r:1 w:0) + /// Proof: `Fusion::SlashDestination` (`max_values`: Some(1), `max_size`: Some(65), added: 560, mode: `MaxEncodedLen`) + fn set_controller_address() -> Weight { + // Proof Size summary in bytes: + // Measured: `285` + // Estimated: `3578` + // Minimum execution time: 17_183_000 picoseconds. + Weight::from_parts(18_514_000, 3578) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::SlashDestination` (r:0 w:1) + /// Proof: `Fusion::SlashDestination` (`max_values`: Some(1), `max_size`: Some(65), added: 560, mode: `MaxEncodedLen`) + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:0 w:1) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + fn set_slash_destination() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 16_350_000 picoseconds. + Weight::from_parts(22_652_000, 0) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Fusion::TotalValueLockedData` (r:1 w:1) + /// Proof: `Fusion::TotalValueLockedData` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + fn update_max_tvl() -> Weight { + // Proof Size summary in bytes: + // Measured: `200` + // Estimated: `1517` + // Minimum execution time: 10_960_000 picoseconds. + Weight::from_parts(11_651_000, 1517) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:1 w:1) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Pools` (r:1 w:0) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + fn set_compounding() -> Weight { + // Proof Size summary in bytes: + // Measured: `974` + // Estimated: `14608207` + // Minimum execution time: 29_916_000 picoseconds. + Weight::from_parts(30_547_000, 14608207) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:1 w:1) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UserCurrencyBalances` (r:1 w:1) + /// Proof: `Fusion::UserCurrencyBalances` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) + /// Storage: `Fusion::TotalValueLockedData` (r:1 w:1) + /// Proof: `Fusion::TotalValueLockedData` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRates` (r:1 w:0) + /// Proof: `Fusion::CurrencyRates` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn stake() -> Weight { + // Proof Size summary in bytes: + // Measured: `1851587` + // Estimated: `14608207` + // Minimum execution time: 10_128_085_000 picoseconds. + Weight::from_parts(10_401_957_000, 14608207) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Fusion::Exposures` (r:1 w:0) + /// Proof: `Fusion::Exposures` (`max_values`: None, `max_size`: Some(14601391), added: 14603866, mode: `MaxEncodedLen`) + /// Storage: `Fusion::EraRewards` (r:1 w:1) + /// Proof: `Fusion::EraRewards` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Fusion::ClaimedRewards` (r:1 w:1) + /// Proof: `Fusion::ClaimedRewards` (`max_values`: None, `max_size`: Some(105), added: 2580, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRates` (r:1 w:0) + /// Proof: `Fusion::CurrencyRates` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UserCurrencyBalances` (r:1 w:1) + /// Proof: `Fusion::UserCurrencyBalances` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:1 w:0) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + fn claim_rewards() -> Weight { + // Proof Size summary in bytes: + // Measured: `2901240` + // Estimated: `14604856` + // Minimum execution time: 5_073_252_000 picoseconds. + Weight::from_parts(5_971_633_000, 14604856) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:1 w:1) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UnbondingChunks` (r:1 w:1) + /// Proof: `Fusion::UnbondingChunks` (`max_values`: None, `max_size`: Some(8100028), added: 8102503, mode: `MaxEncodedLen`) + /// Storage: `Fusion::HasBoost` (r:1 w:0) + /// Proof: `Fusion::HasBoost` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) + /// Storage: `Fusion::TotalValueLockedData` (r:1 w:1) + /// Proof: `Fusion::TotalValueLockedData` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRates` (r:1 w:0) + /// Proof: `Fusion::CurrencyRates` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + fn unbond_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `1851914` + // Estimated: `14608207` + // Minimum execution time: 10_508_795_000 picoseconds. + Weight::from_parts(10_727_236_000, 14608207) + .saturating_add(T::DbWeight::get().reads(10_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:1 w:1) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UnbondingChunks` (r:1 w:1) + /// Proof: `Fusion::UnbondingChunks` (`max_values`: None, `max_size`: Some(8100028), added: 8102503, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UserCurrencyBalances` (r:1 w:1) + /// Proof: `Fusion::UserCurrencyBalances` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) + /// Storage: `Fusion::HasBoost` (r:1 w:1) + /// Proof: `Fusion::HasBoost` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) + fn withdraw_unbonded_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `1851890` + // Estimated: `14608207` + // Minimum execution time: 10_233_589_000 picoseconds. + Weight::from_parts(10_510_839_000, 14608207) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UserCurrencyBalances` (r:1 w:1) + /// Proof: `Fusion::UserCurrencyBalances` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRates` (r:1 w:0) + /// Proof: `Fusion::CurrencyRates` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn withdraw_avail_to_controller() -> Weight { + // Proof Size summary in bytes: + // Measured: `1498` + // Estimated: `6196` + // Minimum execution time: 76_934_000 picoseconds. + Weight::from_parts(77_445_000, 6196) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:3 w:0) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + /// Storage: `Fusion::HasBoost` (r:2 w:0) + /// Proof: `Fusion::HasBoost` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Pools` (r:1 w:0) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsWithBoost` (r:2 w:0) + /// Proof: `Fusion::PoolsWithBoost` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn set_pool_boost_allocations() -> Weight { + // Proof Size summary in bytes: + // Measured: `1851275` + // Estimated: `14608207` + // Minimum execution time: 3_011_833_000 picoseconds. + Weight::from_parts(3_204_744_000, 14608207) + .saturating_add(T::DbWeight::get().reads(10_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:0) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn withdraw_pool_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `837` + // Estimated: `14608207` + // Minimum execution time: 51_737_000 picoseconds. + Weight::from_parts(61_595_000, 14608207) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + fn deposit_avail_to_fusion() -> Weight { + Weight::from_parts(10_000_000, 5000) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRates` (r:0 w:1) + /// Proof: `Fusion::CurrencyRates` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRateChanges` (r:0 w:1) + /// Proof: `Fusion::CurrencyRateChanges` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn create_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `746` + // Estimated: `3592` + // Minimum execution time: 23_073_000 picoseconds. + Weight::from_parts(23_224_000, 3592) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + } + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + fn set_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `370` + // Estimated: `3592` + // Minimum execution time: 13_215_000 picoseconds. + Weight::from_parts(16_260_000, 3592) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:0) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRateChanges` (r:0 w:1) + /// Proof: `Fusion::CurrencyRateChanges` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn destroy_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `370` + // Estimated: `14608207` + // Minimum execution time: 18_896_000 picoseconds. + Weight::from_parts(21_140_000, 14608207) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRateChanges` (r:0 w:1) + /// Proof: `Fusion::CurrencyRateChanges` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn set_currency_conversion_rate() -> Weight { + // Proof Size summary in bytes: + // Measured: `370` + // Estimated: `3592` + // Minimum execution time: 13_976_000 picoseconds. + Weight::from_parts(14_607_000, 3592) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsAccountToId` (r:0 w:1) + /// Proof: `Fusion::PoolsAccountToId` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn create_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `370` + // Estimated: `14608207` + // Minimum execution time: 19_125_000 picoseconds. + Weight::from_parts(21_581_000, 14608207) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsWithBoost` (r:0 w:1) + /// Proof: `Fusion::PoolsWithBoost` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn set_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `647` + // Estimated: `14608207` + // Minimum execution time: 28_333_000 picoseconds. + Weight::from_parts(30_467_000, 14608207) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::EraDurations` (r:10 w:0) + /// Proof: `Fusion::EraDurations` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Exposures` (r:20 w:0) + /// Proof: `Fusion::Exposures` (`max_values`: None, `max_size`: Some(14601391), added: 14603866, mode: `MaxEncodedLen`) + /// Storage: `Fusion::EraRewards` (r:10 w:10) + /// Proof: `Fusion::EraRewards` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsWithBoost` (r:0 w:1) + /// Proof: `Fusion::PoolsWithBoost` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// The range of component `e` is `[0, 10]`. + fn set_pool_with_retry(e: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1850730 + e * (2900322 ±0)` + // Estimated: `14608207 + e * (29207732 ±0)` + // Minimum execution time: 72_618_800_000 picoseconds. + Weight::from_parts(73_665_302_277, 0) + .saturating_add(Weight::from_parts(0, 14608207)) + // Standard Error: 226_110_695 + .saturating_add(Weight::from_parts(170_480_782_933, 0).saturating_mul(e.into())) + .saturating_add(RocksDbWeight::get().reads(2)) + .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(e.into()))) + .saturating_add(RocksDbWeight::get().writes(2)) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(e.into()))) + .saturating_add(Weight::from_parts(0, 29207732).saturating_mul(e.into())) + } + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Fusion::EraRewards` (r:1 w:0) + /// Proof: `Fusion::EraRewards` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Exposures` (r:1 w:0) + /// Proof: `Fusion::Exposures` (`max_values`: None, `max_size`: Some(14601391), added: 14603866, mode: `MaxEncodedLen`) + /// Storage: `Fusion::ClaimedRewards` (r:1 w:0) + /// Proof: `Fusion::ClaimedRewards` (`max_values`: None, `max_size`: Some(105), added: 2580, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsAccountToId` (r:0 w:1) + /// Proof: `Fusion::PoolsAccountToId` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsWithBoost` (r:0 w:1) + /// Proof: `Fusion::PoolsWithBoost` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn destroy_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `1587` + // Estimated: `14608207` + // Minimum execution time: 84_318_000 picoseconds. + Weight::from_parts(87_634_000, 14608207) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) + } + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn fill_pool_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `280` + // Estimated: `6196` + // Minimum execution time: 45_595_000 picoseconds. + Weight::from_parts(46_417_000, 6196) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + fn nominate() -> Weight { + // Proof Size summary in bytes: + // Measured: `1141` + // Estimated: `14608207` + // Minimum execution time: 22_803_000 picoseconds. + Weight::from_parts(23_324_000, 14608207) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:1) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::SlashDestination` (r:1 w:0) + /// Proof: `Fusion::SlashDestination` (`max_values`: Some(1), `max_size`: Some(65), added: 560, mode: `MaxEncodedLen`) + fn set_controller_address() -> Weight { + // Proof Size summary in bytes: + // Measured: `285` + // Estimated: `3578` + // Minimum execution time: 17_183_000 picoseconds. + Weight::from_parts(18_514_000, 3578) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::SlashDestination` (r:0 w:1) + /// Proof: `Fusion::SlashDestination` (`max_values`: Some(1), `max_size`: Some(65), added: 560, mode: `MaxEncodedLen`) + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:0 w:1) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + fn set_slash_destination() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 16_350_000 picoseconds. + Weight::from_parts(22_652_000, 0) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Fusion::TotalValueLockedData` (r:1 w:1) + /// Proof: `Fusion::TotalValueLockedData` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + fn update_max_tvl() -> Weight { + // Proof Size summary in bytes: + // Measured: `200` + // Estimated: `1517` + // Minimum execution time: 10_960_000 picoseconds. + Weight::from_parts(11_651_000, 1517) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:1 w:1) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Pools` (r:1 w:0) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + fn set_compounding() -> Weight { + // Proof Size summary in bytes: + // Measured: `974` + // Estimated: `14608207` + // Minimum execution time: 29_916_000 picoseconds. + Weight::from_parts(30_547_000, 14608207) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:1 w:1) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UserCurrencyBalances` (r:1 w:1) + /// Proof: `Fusion::UserCurrencyBalances` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) + /// Storage: `Fusion::TotalValueLockedData` (r:1 w:1) + /// Proof: `Fusion::TotalValueLockedData` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRates` (r:1 w:0) + /// Proof: `Fusion::CurrencyRates` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn stake() -> Weight { + // Proof Size summary in bytes: + // Measured: `1851587` + // Estimated: `14608207` + // Minimum execution time: 10_128_085_000 picoseconds. + Weight::from_parts(10_401_957_000, 14608207) + .saturating_add(RocksDbWeight::get().reads(9_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) + } + /// Storage: `Fusion::Exposures` (r:1 w:0) + /// Proof: `Fusion::Exposures` (`max_values`: None, `max_size`: Some(14601391), added: 14603866, mode: `MaxEncodedLen`) + /// Storage: `Fusion::EraRewards` (r:1 w:1) + /// Proof: `Fusion::EraRewards` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Fusion::ClaimedRewards` (r:1 w:1) + /// Proof: `Fusion::ClaimedRewards` (`max_values`: None, `max_size`: Some(105), added: 2580, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRates` (r:1 w:0) + /// Proof: `Fusion::CurrencyRates` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UserCurrencyBalances` (r:1 w:1) + /// Proof: `Fusion::UserCurrencyBalances` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:1 w:0) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + fn claim_rewards() -> Weight { + // Proof Size summary in bytes: + // Measured: `2901240` + // Estimated: `14604856` + // Minimum execution time: 5_073_252_000 picoseconds. + Weight::from_parts(5_971_633_000, 14604856) + .saturating_add(RocksDbWeight::get().reads(9_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:1 w:1) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UnbondingChunks` (r:1 w:1) + /// Proof: `Fusion::UnbondingChunks` (`max_values`: None, `max_size`: Some(8100028), added: 8102503, mode: `MaxEncodedLen`) + /// Storage: `Fusion::HasBoost` (r:1 w:0) + /// Proof: `Fusion::HasBoost` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) + /// Storage: `Fusion::TotalValueLockedData` (r:1 w:1) + /// Proof: `Fusion::TotalValueLockedData` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRates` (r:1 w:0) + /// Proof: `Fusion::CurrencyRates` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + fn unbond_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `1851914` + // Estimated: `14608207` + // Minimum execution time: 10_508_795_000 picoseconds. + Weight::from_parts(10_727_236_000, 14608207) + .saturating_add(RocksDbWeight::get().reads(10_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:1 w:1) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UnbondingChunks` (r:1 w:1) + /// Proof: `Fusion::UnbondingChunks` (`max_values`: None, `max_size`: Some(8100028), added: 8102503, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UserCurrencyBalances` (r:1 w:1) + /// Proof: `Fusion::UserCurrencyBalances` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) + /// Storage: `Fusion::HasBoost` (r:1 w:1) + /// Proof: `Fusion::HasBoost` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) + fn withdraw_unbonded_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `1851890` + // Estimated: `14608207` + // Minimum execution time: 10_233_589_000 picoseconds. + Weight::from_parts(10_510_839_000, 14608207) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UserCurrencyBalances` (r:1 w:1) + /// Proof: `Fusion::UserCurrencyBalances` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRates` (r:1 w:0) + /// Proof: `Fusion::CurrencyRates` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn withdraw_avail_to_controller() -> Weight { + // Proof Size summary in bytes: + // Measured: `1498` + // Estimated: `6196` + // Minimum execution time: 76_934_000 picoseconds. + Weight::from_parts(77_445_000, 6196) + .saturating_add(RocksDbWeight::get().reads(7_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:3 w:0) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + /// Storage: `Fusion::HasBoost` (r:2 w:0) + /// Proof: `Fusion::HasBoost` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Pools` (r:1 w:0) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsWithBoost` (r:2 w:0) + /// Proof: `Fusion::PoolsWithBoost` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn set_pool_boost_allocations() -> Weight { + // Proof Size summary in bytes: + // Measured: `1851275` + // Estimated: `14608207` + // Minimum execution time: 3_011_833_000 picoseconds. + Weight::from_parts(3_204_744_000, 14608207) + .saturating_add(RocksDbWeight::get().reads(10_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:0) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn withdraw_pool_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `837` + // Estimated: `14608207` + // Minimum execution time: 51_737_000 picoseconds. + Weight::from_parts(61_595_000, 14608207) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + fn deposit_avail_to_fusion() -> Weight { + Weight::from_parts(10_000_000, 5000) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1u64)) + } +} \ No newline at end of file diff --git a/pallets/mandate/Cargo.toml b/pallets/mandate/Cargo.toml index de57c6f79..e9207bf4b 100644 --- a/pallets/mandate/Cargo.toml +++ b/pallets/mandate/Cargo.toml @@ -10,7 +10,7 @@ targets = ["x86_64-unknown-linux-gnu"] frame-system = { workspace = true, default-features = false } # Substrate -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { workspace = true, features = ["derive"] } scale-info = { workspace = true, default-features = false } frame-support = { workspace = true, default-features = false } sp-io = { workspace = true, default-features = false } diff --git a/pallets/mocked_runtime/Cargo.toml b/pallets/mocked_runtime/Cargo.toml index 11a5609c7..add5ae2dc 100644 --- a/pallets/mocked_runtime/Cargo.toml +++ b/pallets/mocked_runtime/Cargo.toml @@ -14,7 +14,7 @@ kate = { workspace = true, default-features = false } da-control = { workspace = true, default-features = false } scale-info = { workspace = true, features = ["derive"], default-features = false } -codec = { package = "parity-scale-codec", version = "3", features = ["derive"], default-features = false } +codec = { workspace = true, default-features = false, features = ["derive"] } parity-util-mem.workspace = true derive_more.workspace = true serde.workspace = true diff --git a/pallets/system/Cargo.toml b/pallets/system/Cargo.toml index 718c3bd93..a4d81a07e 100644 --- a/pallets/system/Cargo.toml +++ b/pallets/system/Cargo.toml @@ -32,7 +32,7 @@ itertools = { workspace = true, default-features = false } thiserror-no-std.workspace = true # Substrate -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ "derive"] } +codec = { workspace = true, default-features = false, features = [ "derive"] } scale-info = { workspace = true, default-features = false, features = ["derive", "serde"] } serde = { workspace = true, default-features = false, features = ["alloc", "derive"] } frame-support = { workspace = true, default-features = false } diff --git a/pallets/system/benchmarking/Cargo.toml b/pallets/system/benchmarking/Cargo.toml index 0fc86d05f..7d035837e 100644 --- a/pallets/system/benchmarking/Cargo.toml +++ b/pallets/system/benchmarking/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # Substrate -codec = { package = "parity-scale-codec", version = "3", default-features = false } +codec = { workspace = true, default-features = false } frame-benchmarking = { workspace = true, default-features = false } frame-support = { workspace = true, default-features = false } frame-system = { path = "../", default-features = false } diff --git a/pallets/system/src/tests.rs b/pallets/system/src/tests.rs index 94ce2c4a2..515c46a1d 100644 --- a/pallets/system/src/tests.rs +++ b/pallets/system/src/tests.rs @@ -19,7 +19,7 @@ use crate::*; use frame_support::{ assert_noop, assert_ok, dispatch::{Pays, PostDispatchInfo, WithPostDispatchInfo}, - traits::{OnRuntimeUpgrade, WhitelistedStorageKeys}, + traits::WhitelistedStorageKeys, }; use std::collections::BTreeSet; @@ -865,21 +865,22 @@ pub fn from_post_weight_info(ref_time: Option, pays_fee: Pays) -> PostDispa fn last_runtime_upgrade_spec_version_usage() { #[allow(dead_code)] struct Migration; - - impl OnRuntimeUpgrade for Migration { - fn on_runtime_upgrade() -> Weight { - // Ensure to compare the spec version against some static version to prevent applying - // the same migration multiple times. - // - // `1337` here is the spec version of the runtime running on chain. If there is maybe - // a runtime upgrade in the pipeline of being applied, you should use the spec version - // of this upgrade. - if System::last_runtime_upgrade_spec_version() > 1337 { - return Weight::zero(); - } - - // Do the migration. - Weight::zero() - } - } } + +// impl OnRuntimeUpgrade for Migration { +// fn on_runtime_upgrade() -> Weight { +// // Ensure to compare the spec version against some static version to prevent applying +// // the same migration multiple times. +// // +// // `1337` here is the spec version of the runtime running on chain. If there is maybe +// // a runtime upgrade in the pipeline of being applied, you should use the spec version +// // of this upgrade. +// if System::last_runtime_upgrade_spec_version() > 1337 { +// return Weight::zero(); +// } + +// // Do the migration. +// Weight::zero() +// } +// } +// } diff --git a/pallets/vector/Cargo.toml b/pallets/vector/Cargo.toml index b9f792f7b..6d91a59d3 100644 --- a/pallets/vector/Cargo.toml +++ b/pallets/vector/Cargo.toml @@ -12,7 +12,7 @@ avail-core = { workspace = true, default-features = false, features = ["runtime" avail-base = { workspace = true, default-features = false } patricia-merkle-trie = { workspace = true, default-features = false } -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { workspace = true, default-features = false, features = ["derive"] } scale-info.workspace = true frame-support = { workspace = true, default-features = false } sp-io = { workspace = true, default-features = false } diff --git a/patricia-merkle-trie/Cargo.toml b/patricia-merkle-trie/Cargo.toml index d62afead6..8b4be5884 100644 --- a/patricia-merkle-trie/Cargo.toml +++ b/patricia-merkle-trie/Cargo.toml @@ -6,7 +6,7 @@ edition.workspace = true repository.workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { workspace = true, default-features = false, features = ["derive"] } trie-db = { workspace = true, default-features = false } hash-db = { workspace = true, default-features = false } diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index ddf91edcc..f96fed8ab 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -19,6 +19,7 @@ avail-core = { workspace = true, default-features = false } kate = { workspace = true, default-features = false } da-control = { workspace = true, default-features = false } +pallet-fusion = { workspace = true, default-features = false } pallet-mandate = { workspace = true, default-features = false } pallet-vector = { workspace = true, default-features = false } @@ -33,7 +34,7 @@ derive_more.workspace = true # Substrate scale-info = { workspace = true, default-features = false, features = [ "derive" ] } -codec = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive", ] } +codec = { workspace = true, default-features = false, features = [ "derive", ] } binary-merkle-tree = { workspace = true, default-features = false } ## primitives @@ -162,6 +163,7 @@ std = [ "pallet-balances/std", "pallet-collective/std", "pallet-election-provider-multi-phase/std", + "pallet-fusion/std", "pallet-grandpa/std", "pallet-identity/std", "pallet-im-online/std", @@ -218,6 +220,7 @@ runtime-benchmarks = [ "pallet-balances/runtime-benchmarks", "pallet-collective/runtime-benchmarks", "pallet-election-provider-multi-phase/runtime-benchmarks", + "pallet-fusion/runtime-benchmarks", "pallet-grandpa/runtime-benchmarks", "pallet-identity/runtime-benchmarks", "pallet-im-online/runtime-benchmarks", @@ -251,6 +254,7 @@ try-runtime = [ "pallet-balances/try-runtime", "pallet-collective/try-runtime", "pallet-election-provider-multi-phase/try-runtime", + "pallet-fusion/try-runtime", "pallet-grandpa/try-runtime", "pallet-identity/try-runtime", "pallet-im-online/try-runtime", diff --git a/runtime/fuzz/Cargo.toml b/runtime/fuzz/Cargo.toml index e60ffd4ef..d494bbf1d 100644 --- a/runtime/fuzz/Cargo.toml +++ b/runtime/fuzz/Cargo.toml @@ -22,9 +22,7 @@ rand = "0.8.5" afl = { version = "0.15.2", optional = true } libfuzzer-sys = { version = "0.4", optional = true } -codec = { package = "parity-scale-codec", version = "3", default-features = false, features = [ - "derive", -] } +codec = { workspace = true, default-features = false, features = ["derive"] } frame-support = { workspace = true, default-features = false } frame-system = { path = "../../pallets/system", default-features = false } pallet-transaction-payment = { workspace = true, default-features = false } @@ -40,10 +38,10 @@ da-control = { path = "../../pallets/dactr", default-features = false } da-runtime = { path = "../", default-features = false } [features] -default = [ "std", "use_fuzzer" ] +default = ["std", "use_fuzzer"] # default = [ "std", "use_afl" ] -use_fuzzer = [ "libfuzzer-sys" ] -use_afl = [ "afl" ] +use_fuzzer = ["libfuzzer-sys"] +use_afl = ["afl"] std = [ "da-control/std", "da-runtime/std", diff --git a/runtime/src/apis.rs b/runtime/src/apis.rs index fe5b6457a..1b1fef8d6 100644 --- a/runtime/src/apis.rs +++ b/runtime/src/apis.rs @@ -33,6 +33,7 @@ use sp_runtime::{ transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, }; +use sp_staking::{EraIndex, Page}; use sp_std::{borrow::Cow, vec::Vec}; use sp_version::RuntimeVersion; @@ -373,7 +374,7 @@ impl_runtime_apis! { fn check_if_extrinsic_is_post_inherent(uxt: &::Extrinsic) -> bool { use frame_support::traits::ExtrinsicCall; - let Ok(xt) = TryInto::<&RTExtrinsic>::try_into(uxt); + let Ok(xt) = TryInto::<&RTExtrinsic>::try_into(uxt); let vector_pallet_call = match xt.call() { RuntimeCall::Vector(call) => call, @@ -472,7 +473,7 @@ impl_runtime_apis! { Staking::api_nominations_quota(balance) } - fn eras_stakers_page_count(era: sp_staking::EraIndex, account: AccountId) -> sp_staking::Page { + fn eras_stakers_page_count(era: EraIndex, account: AccountId) -> Page { Staking::api_eras_stakers_page_count(era, account) } } diff --git a/runtime/src/constants.rs b/runtime/src/constants.rs index d2479276e..6e8fae1fa 100644 --- a/runtime/src/constants.rs +++ b/runtime/src/constants.rs @@ -234,14 +234,17 @@ pub mod staking { parameter_types! { pub const SessionsPerEra: sp_staking::SessionIndex = 1; pub const BondingDuration: sp_staking::EraIndex = 2; // 2 eras - pub const SlashDeferDuration: sp_staking::EraIndex = BondingDuration::get() - 1; + pub const FusionBondingDuration: sp_staking::EraIndex = 2; // 2 eras + pub const SlashDeferDuration: sp_staking::EraIndex = FusionBondingDuration::get() - 1; } #[cfg(not(feature = "fast-runtime"))] parameter_types! { pub const SessionsPerEra: sp_staking::SessionIndex = 6; pub const BondingDuration: sp_staking::EraIndex = 28; // 28 days - pub const SlashDeferDuration: sp_staking::EraIndex = BondingDuration::get() - 1; // 27 Days + pub const FusionBondingDuration: sp_staking::EraIndex = 7; // 2 days + // SlashDeferDuration should be the lowest between FusionBondingDuration and BondingDuration + pub const SlashDeferDuration: sp_staking::EraIndex = FusionBondingDuration::get() - 1; } parameter_types! { @@ -267,7 +270,7 @@ pub mod staking { pub SolutionImprovementThreshold: Perbill = Perbill::from_rational(1u32, 10_000); // miner configs /// We prioritize im-online heartbeats over election solution submission. - pub const StakingUnsignedPriority: TransactionPriority = TransactionPriority::max_value() / 2; + pub const StakingUnsignedPriority: TransactionPriority = TransactionPriority::MAX / 2; pub const MultiPhaseUnsignedPriority: TransactionPriority = StakingUnsignedPriority::get() - 1u64; pub MinerMaxWeight: Weight = system::RuntimeBlockWeights::get() .get(DispatchClass::Normal) @@ -325,7 +328,7 @@ pub mod im { use super::*; parameter_types! { - pub const ImOnlineUnsignedPriority: TransactionPriority = TransactionPriority::max_value(); + pub const ImOnlineUnsignedPriority: TransactionPriority = TransactionPriority::MAX; } diff --git a/runtime/src/impls.rs b/runtime/src/impls.rs index bacb699cf..e09418b50 100644 --- a/runtime/src/impls.rs +++ b/runtime/src/impls.rs @@ -1,17 +1,19 @@ use crate::{ constants, prod_or_fast, voter_bags, weights, AccountId, AccountIndex, Babe, Balances, Block, - BlockNumber, ElectionProviderMultiPhase, Everything, Hash, Header, Historical, ImOnline, - ImOnlineId, Index, Indices, Moment, NominationPools, Offences, OriginCaller, PalletInfo, - Preimage, ReserveIdentifier, Runtime, RuntimeCall, RuntimeEvent, RuntimeFreezeReason, - RuntimeHoldReason, RuntimeOrigin, RuntimeVersion, Session, SessionKeys, Signature, - SignedPayload, Staking, System, Timestamp, TransactionPayment, Treasury, TxPause, + BlockNumber, ElectionProviderMultiPhase, Everything, Fusion, Hash, Header, Historical, + ImOnline, ImOnlineId, Index, Indices, Moment, NominationPools, Offences, OriginCaller, + PalletInfo, Preimage, ReserveIdentifier, Runtime, RuntimeCall, RuntimeEvent, + RuntimeFreezeReason, RuntimeHoldReason, RuntimeOrigin, RuntimeVersion, Session, SessionKeys, + Signature, SignedPayload, Staking, System, Timestamp, TransactionPayment, Treasury, TxPause, UncheckedExtrinsic, VoterList, MINUTES, SLOT_DURATION, VERSION, }; use avail_core::{ currency::{Balance, AVAIL, CENTS, NANO_AVAIL, PICO_AVAIL}, AppId, NORMAL_DISPATCH_RATIO, }; +use pallet_staking::UnappliedSlash; +use crate::Vec; use codec::{Decode, Encode, MaxEncodedLen}; use constants::time::DAYS; use frame_election_provider_support::{ @@ -44,6 +46,7 @@ use sp_runtime::{ traits::{self, BlakeTwo256, Bounded, Convert, IdentityLookup, OpaqueKeys}, FixedPointNumber, FixedU128, Perbill, Permill, Perquintill, }; +use sp_staking::EraIndex; pub type NegativeImbalance = as Currency< ::AccountId, @@ -139,6 +142,96 @@ impl pallet_authority_discovery::Config for Runtime { type MaxAuthorities = constants::MaxAuthorities; } +parameter_types! { + pub const FusionPalletId: PalletId = PalletId(*b"avl/fusi"); + pub const MaxCurrencyNameLength: u32 = 32; + pub const MaxMembersPerPool: u32 = 100_000; + pub const MaxTargets: u32 = 16; + pub const MaxUnbonding: u32 = 8; + pub const HistoryDepth: u32 = 84; + pub const MaxSlashesPerPool: u32 = 100; // If we have 100 slashes during 27 eras, we have bigger problems + pub const MaxPoolsPerValidator: u32 = 100; +} +impl pallet_fusion::Config for Runtime { + type Currency = Balances; + type CurrencyToVote = sp_staking::currency_to_vote::U128CurrencyToVote; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type ApprovedOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, + >; + type PalletId = FusionPalletId; + type MaxCurrencyNameLength = MaxCurrencyNameLength; + type MaxMembersPerPool = MaxMembersPerPool; + type MaxTargets = MaxTargets; + type MaxUnbonding = MaxUnbonding; + type MaxSlashesPerPool = MaxSlashesPerPool; + type MaxPoolsPerValidator = MaxPoolsPerValidator; + type BondingDuration = constants::staking::FusionBondingDuration; + type SlashDeferDuration = constants::staking::SlashDeferDuration; + type RewardRemainder = Treasury; + type HistoryDepth = HistoryDepth; + type StakingFusionDataProvider = Self; + type PoolAccountProvider = (); + type WeightInfo = weights::pallet_fusion::WeightInfo; +} + +impl pallet_fusion::StakingFusionDataProvider for Runtime { + fn active_era() -> EraIndex { + pallet_staking::Pallet::::active_era() + .map(|era_info| era_info.index) + .unwrap_or(0) + } + fn current_era() -> EraIndex { + pallet_staking::Pallet::::current_era().unwrap_or_default() + } + fn is_valid_validator(account: &AccountId) -> bool { + pallet_staking::Validators::::contains_key(account) + && !pallet_staking::Validators::::get(account).blocked + } + fn has_earned_era_points(era: EraIndex, accounts: &[AccountId]) -> bool { + let era_points = pallet_staking::ErasRewardPoints::::get(era).individual; + accounts + .iter() + .any(|account| era_points.contains_key(account)) + } + fn unapplied_slashes(era: EraIndex) -> Vec> { + pallet_staking::UnappliedSlashes::::get(era) + } + #[cfg(feature = "runtime-benchmarks")] + fn add_dummy_validator(account: AccountId) { + pallet_session::Validators::::mutate(|validators| { + validators.push(account.clone()); + }); + + let default_prefs = pallet_staking::ValidatorPrefs { + commission: Perbill::from_percent(0), + blocked: false, + }; + pallet_staking::Validators::::insert(account.clone(), default_prefs); + } + #[cfg(feature = "runtime-benchmarks")] + fn add_dummy_era_points(validator: AccountId, era: EraIndex) { + pallet_staking::ErasRewardPoints::::mutate(era, |reward_points| { + let points = reward_points + .individual + .entry(validator.clone()) + .or_insert(0); + *points += 100; + }); + } + #[cfg(feature = "runtime-benchmarks")] + fn set_dummy_active_era(era: EraIndex) { + pallet_staking::ActiveEra::::mutate(|active_era| { + *active_era = Some(pallet_staking::ActiveEraInfo { + index: era, + start: None, + }); + }); + } +} + parameter_types! { pub const ProposalBond: Permill = Permill::from_percent(50); pub const ProposalBondMinimum: Balance = 100 * AVAIL; @@ -504,13 +597,13 @@ impl pallet_staking::Config for Runtime { type NominationsQuota = pallet_staking::FixedNominationsQuota<{ constants::staking::MaxNominations::get() }>; type OffendingValidatorsThreshold = constants::staking::OffendingValidatorsThreshold; - // send the slashed funds to the treasury. type Reward = (); type RewardRemainder = Treasury; type RuntimeEvent = RuntimeEvent; type SessionInterface = Self; // rewards are minted from the void type SessionsPerEra = constants::staking::SessionsPerEra; + // send the slashed funds to the treasury. type Slash = Treasury; type SlashDeferDuration = constants::staking::SlashDeferDuration; // This a placeholder, to be introduced in the next PR as an instance of bags-list @@ -518,6 +611,7 @@ impl pallet_staking::Config for Runtime { type UnixTime = Timestamp; type VoterList = VoterList; type WeightInfo = weights::pallet_staking::WeightInfo; + type FusionExt = Fusion; } /// The numbers configured here could always be more than the maximum limits of staking pallet @@ -612,7 +706,7 @@ pub struct U256ToBalance; impl Convert for U256ToBalance { fn convert(n: sp_core::U256) -> Balance { - n.try_into().unwrap_or(Balance::max_value()) + n.try_into().unwrap_or(Balance::MAX) } } @@ -635,7 +729,7 @@ impl pallet_nomination_pools::Config for Runtime { parameter_types! { pub const SpendPayoutPeriod: BlockNumber = 30 * DAYS; pub TreasuryAccount: AccountId = Treasury::account_id(); - pub const MaxBalance: Balance = Balance::max_value(); + pub const MaxBalance: Balance = Balance::MAX; pub const MaxTreasurySpend: Balance = 10_000_000 * AVAIL; // 10 Million AVAILs } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 2c1922cb0..5a85b9257 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -149,6 +149,7 @@ construct_runtime!( Proxy: pallet_proxy = 40, TxPause: pallet_tx_pause = 41, TreasuryCommittee: pallet_collective:: = 42, + Fusion: pallet_fusion = 43, } ); @@ -193,6 +194,7 @@ mod benches { [pallet_proxy, crate::Proxy] [pallet_tx_pause, crate::TxPause] [pallet_collective, crate::TreasuryCommittee] + [pallet_fusion, crate::Fusion] ); } @@ -263,6 +265,7 @@ mod tests { as TryState>::try_state(block, All)?; as TryState>::try_state(block, All)?; as TryState>::try_state(block, All)?; + as TryState>::try_state(block, All)?; Ok(()) } diff --git a/runtime/src/weights/mod.rs b/runtime/src/weights/mod.rs index ef60d993f..6547c3720 100644 --- a/runtime/src/weights/mod.rs +++ b/runtime/src/weights/mod.rs @@ -2,6 +2,7 @@ pub mod frame_system; pub mod pallet_balances; pub mod pallet_collective; pub mod pallet_dactr; +pub mod pallet_fusion; pub mod pallet_identity; pub mod pallet_im_online; pub mod pallet_indices; diff --git a/runtime/src/weights/pallet_fusion.rs b/runtime/src/weights/pallet_fusion.rs new file mode 100644 index 000000000..054efa241 --- /dev/null +++ b/runtime/src/weights/pallet_fusion.rs @@ -0,0 +1,436 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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_fusion` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-172-31-12-189`, CPU: `Intel(R) Xeon(R) Platinum 8175M CPU @ 2.50GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/avail-node +// benchmark +// pallet +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_fusion +// --extrinsic=* +// --heap-pages=4096 +// --header=./HEADER-APACHE2 +// --log=warn +// --output +// ./output/pallet_fusion.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_fusion`. +pub struct WeightInfo(PhantomData); +impl pallet_fusion::WeightInfo for WeightInfo { + + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRates` (r:0 w:1) + /// Proof: `Fusion::CurrencyRates` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRateChanges` (r:0 w:1) + /// Proof: `Fusion::CurrencyRateChanges` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn create_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `746` + // Estimated: `3592` + // Minimum execution time: 23_073_000 picoseconds. + Weight::from_parts(23_224_000, 3592) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + fn set_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `370` + // Estimated: `3592` + // Minimum execution time: 13_215_000 picoseconds. + Weight::from_parts(16_260_000, 3592) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:0) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRateChanges` (r:0 w:1) + /// Proof: `Fusion::CurrencyRateChanges` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn destroy_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `370` + // Estimated: `14608207` + // Minimum execution time: 18_896_000 picoseconds. + Weight::from_parts(21_140_000, 14608207) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRateChanges` (r:0 w:1) + /// Proof: `Fusion::CurrencyRateChanges` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn set_currency_conversion_rate() -> Weight { + // Proof Size summary in bytes: + // Measured: `370` + // Estimated: `3592` + // Minimum execution time: 13_976_000 picoseconds. + Weight::from_parts(14_607_000, 3592) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsAccountToId` (r:0 w:1) + /// Proof: `Fusion::PoolsAccountToId` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn create_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `370` + // Estimated: `14608207` + // Minimum execution time: 19_125_000 picoseconds. + Weight::from_parts(21_581_000, 14608207) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsWithBoost` (r:0 w:1) + /// Proof: `Fusion::PoolsWithBoost` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn set_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `647` + // Estimated: `14608207` + // Minimum execution time: 28_333_000 picoseconds. + Weight::from_parts(30_467_000, 14608207) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::EraDurations` (r:10 w:0) + /// Proof: `Fusion::EraDurations` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Exposures` (r:20 w:0) + /// Proof: `Fusion::Exposures` (`max_values`: None, `max_size`: Some(14601391), added: 14603866, mode: `MaxEncodedLen`) + /// Storage: `Fusion::EraRewards` (r:10 w:10) + /// Proof: `Fusion::EraRewards` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsWithBoost` (r:0 w:1) + /// Proof: `Fusion::PoolsWithBoost` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// The range of component `e` is `[0, 10]`. + fn set_pool_with_retry(e: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1850730 + e * (2900322 ±0)` + // Estimated: `14608207 + e * (29207732 ±0)` + // Minimum execution time: 72_618_800_000 picoseconds. + Weight::from_parts(73_665_302_277, 0) + .saturating_add(Weight::from_parts(0, 14608207)) + // Standard Error: 226_110_695 + .saturating_add(Weight::from_parts(170_480_782_933, 0).saturating_mul(e.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(e.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(e.into()))) + .saturating_add(Weight::from_parts(0, 29207732).saturating_mul(e.into())) + } + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Fusion::EraRewards` (r:1 w:0) + /// Proof: `Fusion::EraRewards` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Exposures` (r:1 w:0) + /// Proof: `Fusion::Exposures` (`max_values`: None, `max_size`: Some(14601391), added: 14603866, mode: `MaxEncodedLen`) + /// Storage: `Fusion::ClaimedRewards` (r:1 w:0) + /// Proof: `Fusion::ClaimedRewards` (`max_values`: None, `max_size`: Some(105), added: 2580, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsAccountToId` (r:0 w:1) + /// Proof: `Fusion::PoolsAccountToId` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsWithBoost` (r:0 w:1) + /// Proof: `Fusion::PoolsWithBoost` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn destroy_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `1587` + // Estimated: `14608207` + // Minimum execution time: 84_318_000 picoseconds. + Weight::from_parts(87_634_000, 14608207) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn fill_pool_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `280` + // Estimated: `6196` + // Minimum execution time: 45_595_000 picoseconds. + Weight::from_parts(46_417_000, 6196) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + fn nominate() -> Weight { + // Proof Size summary in bytes: + // Measured: `1141` + // Estimated: `14608207` + // Minimum execution time: 22_803_000 picoseconds. + Weight::from_parts(23_324_000, 14608207) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:1) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::SlashDestination` (r:1 w:0) + /// Proof: `Fusion::SlashDestination` (`max_values`: Some(1), `max_size`: Some(65), added: 560, mode: `MaxEncodedLen`) + fn set_controller_address() -> Weight { + // Proof Size summary in bytes: + // Measured: `285` + // Estimated: `3578` + // Minimum execution time: 17_183_000 picoseconds. + Weight::from_parts(18_514_000, 3578) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::SlashDestination` (r:0 w:1) + /// Proof: `Fusion::SlashDestination` (`max_values`: Some(1), `max_size`: Some(65), added: 560, mode: `MaxEncodedLen`) + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:0 w:1) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + fn set_slash_destination() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 16_350_000 picoseconds. + Weight::from_parts(22_652_000, 0) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Fusion::TotalValueLockedData` (r:1 w:1) + /// Proof: `Fusion::TotalValueLockedData` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + fn update_max_tvl() -> Weight { + // Proof Size summary in bytes: + // Measured: `200` + // Estimated: `1517` + // Minimum execution time: 10_960_000 picoseconds. + Weight::from_parts(11_651_000, 1517) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:1 w:1) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Pools` (r:1 w:0) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + fn set_compounding() -> Weight { + // Proof Size summary in bytes: + // Measured: `974` + // Estimated: `14608207` + // Minimum execution time: 29_916_000 picoseconds. + Weight::from_parts(30_547_000, 14608207) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:1 w:1) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UserCurrencyBalances` (r:1 w:1) + /// Proof: `Fusion::UserCurrencyBalances` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) + /// Storage: `Fusion::TotalValueLockedData` (r:1 w:1) + /// Proof: `Fusion::TotalValueLockedData` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRates` (r:1 w:0) + /// Proof: `Fusion::CurrencyRates` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn stake() -> Weight { + // Proof Size summary in bytes: + // Measured: `1851587` + // Estimated: `14608207` + // Minimum execution time: 10_128_085_000 picoseconds. + Weight::from_parts(10_401_957_000, 14608207) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Fusion::Exposures` (r:1 w:0) + /// Proof: `Fusion::Exposures` (`max_values`: None, `max_size`: Some(14601391), added: 14603866, mode: `MaxEncodedLen`) + /// Storage: `Fusion::EraRewards` (r:1 w:1) + /// Proof: `Fusion::EraRewards` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Fusion::ClaimedRewards` (r:1 w:1) + /// Proof: `Fusion::ClaimedRewards` (`max_values`: None, `max_size`: Some(105), added: 2580, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRates` (r:1 w:0) + /// Proof: `Fusion::CurrencyRates` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UserCurrencyBalances` (r:1 w:1) + /// Proof: `Fusion::UserCurrencyBalances` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:1 w:0) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + fn claim_rewards() -> Weight { + // Proof Size summary in bytes: + // Measured: `2901240` + // Estimated: `14604856` + // Minimum execution time: 5_073_252_000 picoseconds. + Weight::from_parts(5_971_633_000, 14604856) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:1 w:1) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UnbondingChunks` (r:1 w:1) + /// Proof: `Fusion::UnbondingChunks` (`max_values`: None, `max_size`: Some(8100028), added: 8102503, mode: `MaxEncodedLen`) + /// Storage: `Fusion::HasBoost` (r:1 w:0) + /// Proof: `Fusion::HasBoost` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) + /// Storage: `Fusion::TotalValueLockedData` (r:1 w:1) + /// Proof: `Fusion::TotalValueLockedData` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRates` (r:1 w:0) + /// Proof: `Fusion::CurrencyRates` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + fn unbond_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `1851914` + // Estimated: `14608207` + // Minimum execution time: 10_508_795_000 picoseconds. + Weight::from_parts(10_727_236_000, 14608207) + .saturating_add(T::DbWeight::get().reads(10_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:1 w:1) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Pools` (r:1 w:1) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:1) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UnbondingChunks` (r:1 w:1) + /// Proof: `Fusion::UnbondingChunks` (`max_values`: None, `max_size`: Some(8100028), added: 8102503, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UserCurrencyBalances` (r:1 w:1) + /// Proof: `Fusion::UserCurrencyBalances` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) + /// Storage: `Fusion::HasBoost` (r:1 w:1) + /// Proof: `Fusion::HasBoost` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) + fn withdraw_unbonded_currency() -> Weight { + // Proof Size summary in bytes: + // Measured: `1851890` + // Estimated: `14608207` + // Minimum execution time: 10_233_589_000 picoseconds. + Weight::from_parts(10_510_839_000, 14608207) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::UserCurrencyBalances` (r:1 w:1) + /// Proof: `Fusion::UserCurrencyBalances` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Fusion::CurrencyRates` (r:1 w:0) + /// Proof: `Fusion::CurrencyRates` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn withdraw_avail_to_controller() -> Weight { + // Proof Size summary in bytes: + // Measured: `1498` + // Estimated: `6196` + // Minimum execution time: 76_934_000 picoseconds. + Weight::from_parts(77_445_000, 6196) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Fusion::FusionAddressToSubstrateAddress` (r:1 w:0) + /// Proof: `Fusion::FusionAddressToSubstrateAddress` (`max_values`: None, `max_size`: Some(113), added: 2588, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Memberships` (r:3 w:0) + /// Proof: `Fusion::Memberships` (`max_values`: None, `max_size`: Some(212), added: 2687, mode: `MaxEncodedLen`) + /// Storage: `Fusion::HasBoost` (r:2 w:0) + /// Proof: `Fusion::HasBoost` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Currencies` (r:1 w:0) + /// Proof: `Fusion::Currencies` (`max_values`: None, `max_size`: Some(127), added: 2602, mode: `MaxEncodedLen`) + /// Storage: `Fusion::Pools` (r:1 w:0) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `Fusion::PoolsWithBoost` (r:2 w:0) + /// Proof: `Fusion::PoolsWithBoost` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn set_pool_boost_allocations() -> Weight { + // Proof Size summary in bytes: + // Measured: `1851275` + // Estimated: `14608207` + // Minimum execution time: 3_011_833_000 picoseconds. + Weight::from_parts(3_204_744_000, 14608207) + .saturating_add(T::DbWeight::get().reads(10_u64)) + } + /// Storage: `Fusion::Pools` (r:1 w:0) + /// Proof: `Fusion::Pools` (`max_values`: None, `max_size`: Some(14604742), added: 14607217, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn withdraw_pool_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `837` + // Estimated: `14608207` + // Minimum execution time: 51_737_000 picoseconds. + Weight::from_parts(61_595_000, 14608207) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + fn deposit_avail_to_fusion() -> Weight { + Weight::from_parts(61_595_000, 14608207) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } +}